Está en la página 1de 168

Generacin de Cdigo basado en Modelos

Tema
Desarrollo de un Framework de generacin de cdigo. Implementacin de un lenguaje de script orientado a la definicin de plantillas, que ante una determinada entrada (definicin del modelo), generar el cdigo final. Definicin de un proceso de desarrollo para dar soporte a proyectos de mediana y gran escala. Extensin de un entorno de desarrollo (IDE) para facilitar la utilizacin del framework de generacin de cdigo implementado.

Autores
Bascal, Martn Pablo Hernndez, Fernando Javier LU: 64951 LU: 64916

Director
Mg. Mara Laura Cobo

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Indice
Introduccin............................................................................................................................6 Testing unitario automtico....................................................................................................7 Mocking..............................................................................................................................8 Integracin continua.............................................................................................................10 Herramientas utilizadas.......................................................................................................12 Java..................................................................................................................................12 NetBeans.........................................................................................................................13 JavaCC............................................................................................................................13 MySQL , Hibernate, JavaDoc-Tools.................................................................................16 Junit..................................................................................................................................19 JMock...............................................................................................................................20 CVS..................................................................................................................................22 Maven..............................................................................................................................23 Maven Plugins.................................................................................................................28 Clean...........................................................................................................................29 Properties....................................................................................................................29 Surefire........................................................................................................................31 Assembly.....................................................................................................................32 Dependency................................................................................................................33 Check-Style.................................................................................................................38 FindBugs......................................................................................................................42 Cobertura.....................................................................................................................44 AntRun.........................................................................................................................47 Tomcat.............................................................................................................................49 Archiva.............................................................................................................................50 Jenkins (antes hudson)....................................................................................................53 El lenguaje...........................................................................................................................55 Tipos nativos....................................................................................................................56 Variables..........................................................................................................................68 Arreglos............................................................................................................................69 Operadores......................................................................................................................71 Precedencia de operadores........................................................................................71 Operadores aritmticos...............................................................................................71 Operadores bit a bit.....................................................................................................72 Operadores de comparacin.......................................................................................72 Operadores de incremento/decremento.....................................................................72 Operadores lgicos.....................................................................................................73 Operadores para strings..............................................................................................73 Estructuras de control......................................................................................................73 If...................................................................................................................................73 While............................................................................................................................74 do-while.......................................................................................................................75 for.................................................................................................................................75 foreach.........................................................................................................................76 break y continue..........................................................................................................76 2

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

switch...........................................................................................................................78 return...........................................................................................................................79 Require, Include, Require.once, Include.once............................................................79 Orientacin a objetos.......................................................................................................79 Definicin de clases.....................................................................................................79 Herencia......................................................................................................................81 Palabras reservadas super y this................................................................................82 Extensiones.....................................................................................................................84 Extensin e inicializacin de objetos en la construccin............................................84 Expresiones lambda....................................................................................................86 El tipo ArrayQuery.......................................................................................................87 Funciones de extensin sobre arreglos......................................................................90 Manipulacin de objetos Java.........................................................................................96 Logging y manejo de errores.........................................................................................101 Autoloader......................................................................................................................102 Writer..............................................................................................................................104 La funcin especial @...............................................................................................105 Configuracin.................................................................................................................105 Proyectos desarrollados....................................................................................................107 CodeGeneratorPoms.....................................................................................................107 CodeGeneratorModules................................................................................................109 CodeGeneratorCommon...........................................................................................109 Paquete freelancesoft.codegenerator.common....................................................109 Paquete freelancesoft.codegenerator.common.array...........................................109 Paquete freelancesoft.codegenerator.common.arrayquery..................................109 Paquete freelancesoft.codegenerator.common.configuration..............................110 Paquete freelancesoft.codegenerator.common.context........................................110 Paquete freelancesoft.codegenerator.common.errorhandle.................................110 Paquete freelancesoft.codegenerator.common.parser.........................................111 Paquete freelancesoft.codegenerator.common.writer...........................................111 CodeGeneratorCommonTests...................................................................................112 CodeGenerator..........................................................................................................113 Paquete freelancesoft.codegenerator.array..........................................................114 Paquete freelancesoft.codegenerator.arrayquery.................................................114 Paquete freelancesoft.codegenerator.arrayquery.steps.......................................114 Paquete freelancesoft.codegenerator.configuration.............................................115 Paquete freelancesoft.codegenerator.context......................................................115 Paquete freelancesoft.codegenerator.errorhandle................................................115 Paquete freelancesoft.codegenerator.parser........................................................115 Paquete freelancesoft.codegenerator.utils............................................................115 Paquete freelancesoft.codegenerator.writer.........................................................115 CodeGeneratorLibrary...................................................................................................115 CodeGeneratorLibraryGenerator...............................................................................116 Essentials...................................................................................................................118 File.........................................................................................................................118 JavaLang...................................................................................................................119 Boolean..................................................................................................................119 3

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Float.......................................................................................................................120 Integer...................................................................................................................120 String.....................................................................................................................121 JavaNet......................................................................................................................121 wrap_java_net_URI...............................................................................................121 wrap_java_net_URL..............................................................................................122 JavaIo........................................................................................................................122 JavaxXml...................................................................................................................123 wrap_javax_xml_parsers_DocumentBuilder........................................................123 wrap_javax_xml_parsers_DocumentBuilderFactory............................................123 wrap_javax_xml_XMLConstants...........................................................................124 wrap_org_w3c_dom_Attr......................................................................................124 wrap_org_w3c_dom_CDATASection....................................................................124 wrap_org_w3c_dom_CharacterData....................................................................124 wrap_org_w3c_dom_Comment............................................................................125 wrap_org_w3c_dom_Document...........................................................................125 wrap_org_w3c_dom_DocumentFragment............................................................126 wrap_org_w3c_dom_DocumentType...................................................................126 wrap_org_w3c_dom_DOMConfiguration..............................................................126 wrap_org_w3c_dom_Element..............................................................................126 wrap_org_w3c_dom_Node...................................................................................127 wrap_org_w3c_dom_Text.....................................................................................128 wrap_org_w3c_dom_TypeInfo..............................................................................129 FsTemplating.............................................................................................................129 fs_templating_Configurable..................................................................................129 fs_templating_Template........................................................................................130 CodeGeneratorTemplates..............................................................................................132 TemplateManager......................................................................................................132 tpl_fs_TemplateManager.......................................................................................132 PhpEntities................................................................................................................134 FSSchemas...................................................................................................................136 entities.xsd.................................................................................................................137 php-entities.xsd.........................................................................................................138 FscodeGeneratorProjectType (Plugin para Netbeans IDE)..........................................141 Uso del parser....................................................................................................................142 Uso del parser por lnea de comandos .........................................................................142 Uso del parser como librera ........................................................................................144 Plan de configuracin........................................................................................................145 Configuracin del servidor.............................................................................................145 Host...........................................................................................................................145 Tomcat.......................................................................................................................145 Java de Sun...............................................................................................................146 CVS...........................................................................................................................146 Archiva.......................................................................................................................148 Maven........................................................................................................................152 Jenkins (o Hudson)....................................................................................................153 Configuracin del cliente...............................................................................................155 4

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Java de Sun...............................................................................................................155 JavaCC......................................................................................................................155 Maven........................................................................................................................155 NetBeans...................................................................................................................156 Configuracin de un cliente windows............................................................................157 CVS...........................................................................................................................158 Java de Sun...............................................................................................................158 Maven........................................................................................................................159 PHP...........................................................................................................................159 Compilar en windows desde linux.................................................................................159 Utilizando el Framework de Generacin de Cdigo..........................................................162 Contenido del entregable...................................................................................................163 Map road............................................................................................................................164 Conclusiones......................................................................................................................165 Referencias........................................................................................................................165

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Introduccin
Como profesionales ya insertos en el mercado laboral sabemos por experiencia propia que durante el desarrollo de software se presentan ciertas tareas que son repetitivas. La intencin de este proyecto es el desarrollo de herramientas para facilitar la ejecucin de tareas rutinarias que se dan en el transcurso de un proyecto de software, principalmente en el rea de negocios. El ciclo de vida de un producto de software est conformado por tareas de diversa ndole, algunas de las mismas no requieren del intelecto o capacidades especficas de miembros del equipo. Si contramos con un framework para generar cdigo asociado a ese tipo de tareas, los tiempos en los cuales se puede llevar a cabo un proyecto se podran reducir drsticamente. Nuestra tesis consiste en el desarrollo de un framework apuntado a la reduccin de tiempos durante el ciclo de vida de un producto de software. A su vez, tambin estamos interesados en enfrentarnos a los problemas que se presentan en todo el proceso de desarrollo a gran escala, y principalmente en un entorno distribuido, en el cual los integrantes de un equipo no necesariamente estn en el mismo lugar fsico. Por esto, investigaremos, documentaremos e implementaremos el uso de herramientas que actualmente existen para producir software de calidad a mediana y gran escala. Durante el desarrollo utilizaremos dos entornos, cliente y servidor. Se describir como instalar y configurar las herramientas necesarias en un servidor para poder compartir el cdigo e implementar integracin continua. Tambin se documentarn los pasos para configurar una mquina cliente permitiendo sumar a un desarrollador al equipo. El producto final resultar en un framework que podr ser utilizado como herramienta durante el desarrollo de aplicaciones. Dicho framework: Recibir como entrada un conjunto de archivos xml que representarn el modelo de negocios. Recibir un conjunto de templates con el fin de indicar como procesar los archivos xml para generar una salida. Luego de su ejecucin, el resultado ser parte del cdigo necesario para la aplicacin final.

Los templates debern ser escritos en un lenguaje que definiremos e implementaremos, lo haremos definiendo una gramtica y utilizando la herramienta JavaCC para generar un intrprete. Por otro lado, tambin sabemos que una herramienta con estas caractersticas no tendra mayores beneficios si no contramos con algn mtodo simple y rpido para definir el modelo. Por lo que desarrollaremos un plugin que extienda al IDE NetBeans para brindar soporte a nuestro lenguaje y la capacidad de definir el modelo de forma grfica.

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Hoy en da, para lograr aplicaciones de calidad, es necesario contar con equipos de varias personas. Cuando manejamos grupos de desarrollo nos enfrentamos con problemticas que no podramos resolver sin el uso de herramientas que dan soporte durante todo el proceso. Pretendemos definir y utilizar un proceso que garantiza la calidad del software. Nos enfocaremos en el rea de desarrollo y en el testing automtico, dejando de lado los procesos que ataan al rea funcional y al testing no automtico. La principal herramienta que nos dar soporte durante todo el desarrollo ser Maven de la organizacin Apache. Maven significa acumulacin de conocimiento y es de utilidad en la gestin de proyectos de software basados en el lenguaje Java. Se basa en el concepto de Modelo de Objetos (POM), puede administrar proyectos, reportes y documentacin. Es de fcil extensin mediante el uso de plugins. En particular, nos ser de utilidad para: Manejo de artefactos y dependencias mediante el uso de repositorios. Ejecucin de tests automticos. Garantizar la cobertura de los tests. Garantizar la uniformidad y documentacin del cdigo fuente mediante la definicin de polticas. Bsqueda de defectos comunes. Generar informes sobre todos los puntos anteriores.

Definiremos dos entornos. Nos referiremos al entorno cliente como la configuracin de software necesaria para que un desarrollador pueda trabajar en el proyecto. Nos referiremos como entorno servidor a la configuracin necesaria en una mquina que dar soporte a todo el equipo, en la cual se implementar control de versiones, se alojarn los repositorios maven y servir para la integracin continua de todas las soluciones.

Testing unitario automtico


Como ya mencionamos en la introduccin, hemos hecho desarrollos empresariales en lo laboral. Una caracterstica que se usa ampliamente en desarrollos a mediana y gran escala es la automatizacin de los tests. Una prueba unitaria es una forma de probar el correcto funcionamiento de un mdulo de cdigo. Esto sirve para asegurar que cada uno de los mdulos funcione correctamente por separado. Luego, con las Pruebas de Integracin, se podr asegurar el correcto funcionamiento del sistema o subsistema en cuestin. Para que una prueba unitaria sea buena se deben cumplir los siguientes requisitos: Automatizable: no debera requerirse una intervencin manual. Esto es especialmente til para integracin continua. Completas: deben cubrir la mayor cantidad de cdigo. 7

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Repetibles o Reutilizables: no se deben crear pruebas que slo puedan ser ejecutadas una sola vez. Tambin es til para integracin continua. Independientes: la ejecucin de una prueba no debe afectar a la ejecucin de otra. Profesionales: las pruebas deben ser consideradas igual que el cdigo, con la misma profesionalidad, documentacin, etc.

Aunque estos requisitos no tienen que ser cumplidos al pie de la letra, se recomienda seguirlos o de lo contrario las pruebas pierden parte de su funcin. En lo que respecta a completitud hay diferentes mtodos de medicin. Ms adelante explicaremos la utilizacin del plugin de maven Cobertura, con este plugin se pude asegurar la cobertura de los tests tomando distintas medidas. Hemos optado por medir cantidad de lneas y no ramas, ya que nos parece excesivo intentar cubrir todos los posibles caminos en el cdigo. El objetivo de las pruebas unitarias es aislar cada parte del programa y mostrar que las partes individuales son correctas. Proporcionan un contrato escrito que el trozo de cdigo debe satisfacer. Estas pruebas aisladas proporcionan cinco ventajas bsicas: Fomentan el cambio: Refactorizar cdigo es mucho ms simple si se cuenta con un conjunto de pruebas unitarias automticas porque ejecutndolas luego de implementar un cambio se puede asegurar, dentro de la medida de lo posible, que no se han introducido nuevos errores. Simplifica la integracin: La integracin del cdigo desarrollado por diferentes personas es ms simple, porque cada unidad se ha probado individualmente. Es menos costoso testear luego de integrar. Documenta el cdigo: En muchos casos es relativamente simple aprender a utilizar cierto trozo de cdigo leyendo en los tests que estn asociados a l, por ejemplo, si se indaga en los cdigos de los templates desarrollados, se puede aprender a escribir los xml que son requeridos como entrada. Separacin de la interfaz y la implementacin: Para facilitar la escritura de tests automticos, es necesario separar claramente la interfaz de la implementacin. En la mayora de los casos se puede utilizar un objeto mock para simular el comportamiento de una interfaz y poder testear independientemente a los objetos que la usan. Los errores estn ms acotados y son ms fciles de localizar: Existen pruebas unitarias que pueden desenmascararlos.

Mocking
Mocking es una tcnica con la cual se simula el comportamiento de objetos completos. Es utilizada en los test unitarios para lograr hacer pruebas de ojetos que usan otros objetos de una manera aislada, es decir, sin interaccin real con esos otros objetos. La nica restriccin es que los objetos mock deben respetar una interfaz. Imitan el 8

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

comportamiento de otro objeto real que tambin implementa la interfaz. La mayora de las libreras de mocking permiten hacer verificaciones sobre los mtodos que el objeto que se est testeando debe invocar sobre esa interfaz, el orden, los parmetros, e incluso retornar algn resultado deseado. Un objeto fake es un objeto que respeta una interfaz y retorna valores por default para cada mtodo. Un objeto mock va un poco ms all, posee la habilidad de: Verificar si un mtodo de la interfaz es invocado o no, y cuantas veces. Verificar el orden en el que se invocan los mtodo de la interfaz. Verificar los parmetros con los cuales se ha invocado cada mtodo. Retornar un valor preestablecido.

Para lograr hacer estos chequeos, las libreras de mocking brindan la posibilidad de setear expectaciones, es decir una forma de decirle al objeto mock lo que se espera que hagan con l. El ejemplo ms claro en el cual se utilizan objetos mock es en el acceso a datos. En una aplicacin tpica tenemos una capa con varios objetos que se encargan de ir contra la base de datos y otra capa con objetos de negocios que utilizan a los de acceso a datos. Si los objetos de la capa de acceso a datos implementan interfaces, entonces pueden ser mockeados y de este modo se puede testear la lgica de negocios sin necesidad de acceder a datos reales. Recordemos que uno de los principios de los test unitarios es que estos deben ser independientes y no depender del entorno, por lo que no se considera correcto que un test unitario dependa de los datos subyacentes en una base de datos. Veamos un ejemplo para terminar de comprender como funciona el mocking de un objeto. Suponiendo que contamos con la siguiente interfaz.
interface Subscriber { void receive(String message); }

Y queremos testear a la clase Publisher que, internamente usa a un objeto que respeta la interfaz Suscriber. Entonces podemos escribir un test similar al siguiente:
import org.jmock.Mockery; import org.jmock.Expectations; class PublisherTest extends TestCase { Mockery context = new Mockery(); public void testOneSubscriberReceivesAMessage() { // set up final Subscriber subscriber = context.mock(Subscriber. class ); Publisher publisher = new Publisher(); publisher.add(subscriber); final String message = "message" ; // expectations

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
context.checking( new Expectations() {{ oneOf (subscriber).receive(message); }}); // execute publisher.publish(message); // verify context.assertIsSatisfied(); } }

Este test verifica que, cuando se invoca al mtodo publish sobre un objeto de tipo Publisher, ste har un llamado a receive sobre suscriber con el mismo parmetro. Todo esto sin necesidad de implementar la interfaz Suscriber.

Integracin continua
La integracin continua es una metodologa, propuesta inicialmente por Martin Fowler, en la cual se intenta integrar partes de cdigo lo ms a menudo posible y de una manera automtica. Con integrar queremos decir, resolver dependencias, compilar y ejecutar tests. Esta tcnica es ampliamente utilizada o sugerida en metodologas giles, como Scrum o XP. La idea es la siguiente: Cuando un desarrollador introduce un cambio, este se hace responsable por los efectos en el proyecto en el que lo est introduciendo. Pero muchas veces pierde de vista las dependencias, en este caso, los proyectos que utilizan al que l est modificando. Con integracin continua, el desarrollador trabaja de la misma manera. Pero en algn momento del da, posiblemente durante la noche, se ejecutarn compilaciones y corridas de tests sobre las ltimas versiones de todos los proyecto. Con lo cual si se introdujo un error se descubre, a lo sumo, al da siguiente. Aplicar integracin continua no es posible sin el uso de un conjunto de herramientas. Se debe contar con un repositorio (Control de versiones sobre el cdigo) y con una mquina con una serie de herramientas que sea capaz de: 1. Descargar del repositorio todos los proyectos. 2. Compilarlos en orden, segn unos dependan de otros. 3. Correr tests que tengan la mayor cobertura posible. 4. Generar informes, sobre todo en el caso de fallos en cualquiera de los pasos. Para lograr sus objetivos, la integracin continua cuenta con una serie de principios: Mantener un repositorio de cdigo. Es necesario mantener un repositorio donde se aloje todo el cdigo. Si el repositorio acepta creacin de ramas, estas deben ser minimizadas ya que en general, la integracin se aplica sobre la rama principal. Automatizar el build. Se debe poder hacer el build con tan slo un comando. Para esto existen diferentes herramientas, en nuestro caso maven. El proceso incluye la 10

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

ejecucin de tests automticos y en muchos casos otros pasos adicionales, como chequeos extras, generacin de informes, entregables, etc. El proceso de build es mucho ms amplio que slo compilar. Hacer el build auto testeable. Deben existir tests automticos que se puedan ejecutar para asegurar la correctitud del cdigo. Todos modifican sobre la lnea base. Para evitar conflictos todos los desarrolladores deben hacer commit de sus cambios tan regularmente como sea posible. Esto tiene varias ventajas, se minimiza el riesgo de conflictos y adems lleva a los desarrolladores a mantener una comunicacin fluida sobre los cambios que introducen. Se debe hacer build de cada cambio. Por cada cambio es esencial hacer build sobre el proyecto que fue modificado. Esto puede ser de manera manual o con herramientas que chequean cambios sobre el control de versiones y disparan el build. Mantener el build rpido. La ejecucin de los builds debe ser lo ms rpida posible para identificar problemas tan pronto como se pueda. Lograr que la obtencin de los ltimos entregables sea sencilla. Debe ser sencillo para desarrolladores y testers obtener las ltimas versiones. Una vez identificado y corregido un error, se debe poder generar una nueva versin del entregable de manera rpida para que pueda ser testeado nuevamente. Deploys automticos. Tambin se debe poder pasar a servidores de testing, e incluso en algunos casos de produccin, de manera automtica.

Hoy en da, la integracin continua es ampliamente utilizada a nivel empresarial para el desarrollo de proyectos a mediana y gran escala. Las ventajas son realmente innumerables, algunas de las mismas podran ser: Los errores de integracin se detectan y corrigen continuamente. Sabemos que mientras antes se detecte y corrija un error es mucho ms barato. Rpida deteccin de cambios incompatibles. Rpida deteccin de cdigo en conflicto. Testing automtico de todo el cdigo de una manera rpida. Mantencin de mtricas e informes sobre diversos aspectos como cobertura y complejidad del cdigo. Mismo estilo en todo el cdigo. Se pueden definir polticas y obligar a que los desarrolladores las sigan, fallando el build si alguna no se cumple. Etc.

Como todo en el desarrollo de software tiene algunas desventajas: 11

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

El tiempo para lograr el ambiente para integracin continua es significativo. Si el proyecto es pequeo tal vez no valga la pena. Es necesario que los tests sean automticos, correctos y que cubran la mayor cantidad de cdigo posible. Se debe invertir en hardware para un servidor de integracin continua.

Como conclusin, en general, las ventajas pesan mucho ms que las desventajas, siempre que el proyecto que estemos encarando no sea demasiado pequeo.

Herramientas utilizadas
A continuacin, explicaremos someramente el uso de las herramientas que seleccionamos. En algunos casos evaluaremos alternativas e intentaremos justificar nuestra eleccin.

Java
Como lenguaje de programacin, hemos elegido al lenguaje Java. No hay demasiado para explicar sobre el mismo, es ampliamente utilizado por toda la comunidad. Lo seleccionamos porque queramos un lenguaje que cumpla con los siguientes requisitos: Que el uso del lenguaje sea gratuito y preferentemente, con libreras de cdigo abierto. Lograr que nuestro software sea multiplataforma, que pudiese correr tanto en windows como en linux. Esto se logra gracias a la mquina virtual de java sin mayores problemas. Contar con un IDE gratuito para utilizar durante el desarrollo. Hay varios IDE para programar en java. Los ms utilizados son NetBeans y Eclipse, ambos son gratuitos y cuentan con numerosos plugins que podremos utilizar. Generar nuestro propio lenguaje basado en su gramtica. Contamos con varias herramientas gratuitas para generar analizadores sintcticos y lxicos basados en gramticas con las cuales podremos generar nuestro propio lenguaje. Contar con herramientas gratuitas para soportar testing unitario y mocking. Hay numerosas libreras para java de ndole gratuito. Contar con herramientas, tambin gratuitas, para dar soporte a la integracin contnua. Para esto tambin existen muchas herramientas con plugins gratuitos que servirn a distintos fines.

El lenguaje Java cumple con todos los requisitos enumerados, por lo que pensamos que es el ideal para ser utilizado en nuestro proyecto. No se puede hablar de otra alternativa, porque ninguna conocida cumple con todos los puntos anteriores. 12

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

NetBeans
Si bien hay varias alternativas para ser utilizadas como IDE durante el desarrollo de proyectos basados en el lenguaje Java, el nmero se reduce si buscamos software gratuito y preferentemente de cdigo abierto. Es indiscutible que existen dos IDEs lderes hoy por hoy, uno es NetBeans y el otro es Eclipse. Ambos proveen todo lo que necesitamos durante el desarrollo de nuestros proyectos y estn en constante evolucin, tambin cuentan con numerosos plugins. Para nosotros es indistinto cul de stos ser utilizado. En particular nos hemos inclinado por NetBeans, dado que nos sentimos ms cmodos con el mismo. A dems cuanta con una API relativamente sencilla para desarrollar nuestros propios plugins. Los defensores de Eclipse alegan que si bien NetBeans es un poco ms flexible, consume ms recursos. Por el momento no hemos tenido este tipo de problemas. De todas formas, dejamos abierta la posibilidad de usar cualquiera de las dos alternativas durante el desarrollo, de hecho hemos compilado todos nuestros proyectos con Eclipse (No debe haber diferencias, ya que ambos se conectan con maven) sin mayores problemas. La nica diferencia es que el IDE de Eclipse marca algunos warnings que no vemos en NetBeans y viceversa, por lo que si queremos implementar la poltica cero warnings utilizando Eclipse deberamos hacer algunos ajustes. Tampoco descartamos la posibilidad del desarrollo de un plugin para Eclipse en el futuro, que brinde soporte a nuestro lenguaje, como lo hemos hecho para NetBeans.

JavaCC
JavaCC es la herramienta que seleccionamos para generar el parser de nuestro propio lenguaje. Significa Java Compiler Compiler y es una de las herramientas ms populares que se utiliza para generar parsers para aplicaciones Java. Lee una especificacin de una gramtica y la convierte en un programa Java que puede reconocer la misma. A dems de la generacin del parser en s mismo, provee otras capacidades como la construccin de un rbol a partir de la gramtica va la herramienta JJTree que ya viene integrada con JavaCC. Esto es particularmente til para implementar intrpretes, se puede hacer un parser que construya un rbol a partir de la gramtica y luego procesar ese rbol para obtener un resultado. Cuenta con su propio generador lxico, con lo cual se puede indicar la forma de obtener los tokens en el mismo archivo en el cual se especifica la gramtica y no se requieren libreras ni herramientas adicionales. Tambin cuenta con ciertos mecanismos mediante los cuales podemos crear una gramtica ms legible. Por ejemplo el uso de lookahead, con el cual le podemos indicar que ante una arregla ambiga vea algunos tokens hacia adelante para seleccionar la prxima regla correctamente. Con esto, no necesitamos agregar reglas para desambig ar que terminan ensuciando la gramtica. Cada caso debe ser evaluado cuidadosamente, no es bueno abuzarse del uso de lookahead. Es ampliamente utilizada y est probado que funciona en ambas plataformas (linux y 13

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

windows) sin problemas. De hecho al probar nuestro desarrollo en diferentes plataformas slo encontramos un problema con el separador de lnea que se solucion de una manera muy sencilla. Caractersticas resaltadas por el equipo de JavaCC: Top-Down: JavaCC genera parsers top-down (recursivos descendentes), por el contrario, herramientas como YACC generan parsers bottom-up. Esto permite el uso de gramticas ms generales (aunque no permite recursin a izquirda). Estos parsers tienen muchas otras ventajas (adems de la gramtica ms general) como ser ms fciles de debuguear, tienen la habilidad de parsear a cualquier no terminal en la gramtica y tambin la habilidad de pasar atributos hacia arriba y abajo en el rbol de parseo. Amplia comunidad de usuarios: JavaCC es lejos, el generador ms usado en aplicaciones Java. Tienen cientos de miles de descargas y estiman varios miles de usuarios serios. Cuentan con miles de usuarios en la lista de mails . Especificacin lxica y gramtica en un nico archivo: Las especificaciones lxicas como expresiones regulares, strings, etc. y las especificaciones de la gramtica (el BNF) son escritas juntas en el mismo archivo. Esto hace que las gramticas sean ms fciles de leer (desde que es posible definir expresiones regulares inline en la especificacin de la gramtica), tambin es ms fcil de mantener. Preprocesador para construir el rbol gramatical: JavaCC viene con JJTree, un constructor para el rbol extremadamente poderoso. Muy customizable: JavaCC ofrece muchas diferentes opciones para customizar su comportamiento y el de los parsers generados. Ejemplos de estas opciones son los tipos de unicode para los streams de entrada, el nmero de tokens para chequear ambigedad, etc. 100% Java puro certificado: JavaCC corre en todas las plataformas Java desde la versin 1.1 o superior. Fue usado en incontables diferentes mquinas sin esfuerzo especial para portarlo. Es un testimonio del aspecto del lenguaje Java: Escribir una vez, correr donde sea. Generacin de documentacin: JavaCC incluye una herramienta llamada JJDoc para convertir archivos de gramtica en archivos de documentacin (opcionalmente en html). Muchos ejemplos: El entregable de JavaCC incluye un amplio rango de ejemplos con gramticas Java y Html. Los ejemplos, junto con su documentacin son una excelente manera de familiarizarse con JavaCC. Multilenguaje: El analizado lxico de JavaCC puede manejar entradas unicode, y las especificaciones lxicas tal vez puedan contener caracteres unicode. Estas facilidades permiten descripciones de elementos de lenguajes como identificadores Java que permitan ciertos caracteres no unicode (que no son ASCII). 14

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Especificaciones de lookahead sintcticos y semnticos: Por default JavaCC genera un parser LL(1). Sin embargo puede haber porciones de la gramtica que no sean LL(1). JavaCC ofrece la capacidad de lookahead sintcticos y semnticos para resolver ambigedades localmente en esos puntos. Por ejemplo, el parser es LL(K) solo en esos puntos, pero permanece LL(1) en cualquier otro lugar para mejor performance. Permite especificaciones BNF extendidas: JavaCC permite BNF extendidos como (A)*, (A)+, etc. - dentro de las especificaciones lxicas y gramaticales. Los BNF extendidos son ms fciles de leer, como por ejemplo en A ::= y(x)* contra A ::= Ax|y. Estados lxicos y acciones lxicas: JavaCC ofrece estados y acciones lxicos similares a lex. Aspectos especficos de JavaCC que lo hacen superiores a otras herramientas es el manejo de estados como TOKEN, MORE, SKIP, etc. Esto permite especificaciones ms limpias y mejor informe de mensajes de errores por parte de JavaCC. Anlisis lxico no sensible a maysculas: Las especificaciones lxicas pueden definir tokens que no sean sensibles a maysculas, tanto en el nivel global para la especificacin completa, o en un sector ms acotado. Capacidades extensivas para depurar: Usando las opciones DEBUG_PARSER, DEBUG_LOOKAHEAD y DEBUG_TOKEN_MANAGER, se puede analizar en profundidad el parseo y el procesamiento de tokens. Tokens especiales: Los tokens que son definidos como especiales son ignorados durante el parseo, pero esos tokens estn disponibles para ser procesados mediante herramientas. Un uso especfico de esto es para el procesamiento de comentarios. Muy buen reporte de errores: El reporte de errores de JavaCC est entre los mejores. Los parsers generados por JavaCC tienen la capacidad de identificar claramente el punto en el que el error se produjo y brindar informacin completa de diagnstico.

Por las razones antes expuestas, creemos que de momento, JavaCC es la eleccin ms acertada para la generacin de nuestro parser. Ejemplo de una regla lxica en la cual indicamos la forma del token =:
<CODE> TOKEN : { < ASSIGN: "=" > }

Ejemplo de una regla gramatical, en la cual indicamos que hacer ante el token continue. En este caso se marcan los lmites por si llega a ser necesario reportar un error. Adems se genera un nodo en el rbol lxico que luego ser interpretado. 15

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
private void continueStatement() #ContinueNode(0) : {Token t;} { t = <CONTINUE> { jjtThis.setTokenLimits(t.beginLine, t.endLine, t.beginColumn, t.endColumn); jjtThis.setOwner(getActualClassName()); } }

Para ms detalle sobre la gramtica, el archivo en donde se define se puede encontrar en el proyecto CodeGenerator. Ms precisamente en:
CodeGeneratorModules/CodeGenerator/src/main/java/freelancesoft/codegenerator/parser/CodeGenerator. jjt

Hemos analizado otras herramientas, entre ellas: ANTLR CUP Jlex Jflex

Tambin hemos ledo varias comparativas entre las diferentes alternativas.

MySQL , Hibernate, JavaDoc-Tools


Estas tres herramientas fueron utilizadas para desarrollar CodeGeneratorLibraryGenerator. Bsicamente es una aplicacin de escritorio que toma el nombre de una clase Java, utiliza JavaDoc-Tools para extraer de la clase toda la informacin posible: Comentario de la clase. Nombre de la clase. Campos pblicos estticos, con tipo y comentario. Mtodos pblicos estticos, con tipo de retorno, parmetros y comentarios. Campos pblicos, con tipo y comentarios. Mtodos pblicos, con tipo de retorno, parmetros y comentarios. Constructores, con parmetros y comentarios.

Una vez extrada toda esta informacin, permite hacer customizaciones sobre las mismas. Todo esto se puede guardar en una base de datos MySQL, para poder hacer posteriores modificaciones. 16

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Luego, se pueden generar los siguientes archivos: Un archivo de tipo fgl que es la implementacin completa de un wrapper equivalente a la clase java, pero escrito en nuestro lenguaje. Un archivo te test para el archivo de tipo fgl. Este contiene tests para todos los campos y mtodos implementados parcialmente. Luego deben ser modificados para llegar a ser tests tiles. Un archivo fgl, tambin parcialmente implementado (debe ser modificado), para cada mtodo de test.

Con esta aplicacin logramos generar wrappers de clases java escritas en nuestro propio lenguaje con un esfuerzo relativamente pequeo. Hemos seleccionado la combinacin: MySQL. Como motor de base de datos. Hibernate. Como ORM (Object-Relational Mapping). JavaDoc-Tools. Para extraer la informacin de las clases Java.

Dado que esta aplicacin se considera de uso interno, no hemos evaluado demasiadas alternativas. Simplemente buscamos que sea algo rpido para desarrollar y usar, de fcil integracin. La clase ReflectionHelper utiliza JavaDoc-Tools para procesar la clase Java. El mtodo start es invocado con un objeto de tipo RootDoc, este objeto contiene toda la informacin que ha recolectado la herramienta acerca de la clase Java, incluyendo los comentarios. Esto es de suma utilidad porque nuestro archivo fgl que representa la misma clase contiene comentario similares. Luego se usa Hibernate, combinado con MySQL para persistir los datos. Un archivo tpico de configuracin para Hibernate es un xml similar al siguiente:
< hibernate-configuration > < session-factory > < property name = "hibernate.dialect" > org.hibernate.dialect.MySQLDialect </ property > < property name = "hibernate.connection.driver_class" > com.mysql.jdbc.Driver </ property > < property name = "hibernate.connection.url" > jdbc:mysql://localhost:3306/CodeGeneratorLibraryGenerator </ property > < property name = "hibernate.connection.username" > **** </ property > < property name = "hibernate.connection.password" > **** </ property > < mapping resource = "freelancesoft/codegeneratorlibrarygenerator/entities/ClassDto.hbm.xml" /> < mapping resource = "freelancesoft/codegeneratorlibrarygenerator/entities/ConstructorDto.hbm.xml" /> < mapping resource = "freelancesoft/codegeneratorlibrarygenerator/entities/ConverterDto.hbm.xml" /> < mapping resource = "freelancesoft/codegeneratorlibrarygenerator/entities/FieldDto.hbm.xml" /> < mapping resource = "freelancesoft/codegeneratorlibrarygenerator/entities/GeneratedClassDto.hbm.xml" /> < mapping resource = "freelancesoft/codegeneratorlibrarygenerator/entities/KnowedTypeDto.hbm.xml" /> < mapping resource = "freelancesoft/codegeneratorlibrarygenerator/entities/MethodDto.hbm.xml" />

17

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
< mapping resource = "freelancesoft/codegeneratorlibrarygenerator/entities/ParameterDto.hbm.xml" /> < mapping resource = "freelancesoft/codegeneratorlibrarygenerator/entities/ReflectionInfoDto.hbm.xml" /> </ session-factory > </ hibernate-configuration >

Tambin hay que definir los mapeos, es decir hay que indicarle a Hibernate como mapear las propiedades de una entidad en tablas de la base de datos:
< hibernate-mapping > < class name = "freelancesoft.codegeneratorlibrarygenerator.entities.ClassDTO" table = "ClassDTO" catalog = "CodeGeneratorLibraryGenerator" lazy = "false" > < id name = "id" type = "java.lang.Long" > < column name = "id" /> < generator class = "identity" /> </ id > < property name = "privateConstructor" type = "boolean" > < column name = "privateConstructor" not-null = "true" /> </ property > < property name = "name" type = "string" > < column name = "name" length = "65535" /> </ property > < property name = "group" type = "string" > < column name = "libraryGroup" length = "65535" /> </ property > < property name = "generatedName" type = "string" > < column name = "generatedName" length = "65535" /> </ property > < property name = "comment" type = "string" > < column name = "comment" length = "65535" /> </ property > < property name = "generatedComment" type = "string" > < column name = "generatedComment" length = "65535" /> </ property > < property name = "extendsOf" type = "string" > < column name = "extends" length = "65535" /> </ property > < property name = "useCustomFromJavaObject" type = "boolean" > < column name = "useCustomFromJavaObject" not-null = "true" /> </ property > < property name = "customFromJavaObject" type = "string" > < column name = "customFromJavaObject" length = "65535" /> </ property > </ class > </ hibernate-mapping >

Para utilizar Hibernate podemos definir mtodos como el siguiente:


public static ReflectionInfoDTO getByClassName(String className) { Session sess = getCurrentSession(); return (ReflectionInfoDTO) sess.createQuery( "select Ref from ReflectionInfoDTO as Ref inner join Ref.classInfo as Ci where Ci.name = ?" ). setString( 0 , className).uniqueResult(); }

De este modo Hibernate nos abstrae del motor de base de datos subyacente, permitiendo hacer consultas directamente sobre los objetos java, inspeccionando sus relaciones y sin necesidad de definir queries SQL. Para ms informacin sobre el uso de estas herramientas ver la seccin CodeGeneratorLibraryGenerator. 18

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Junit
Para escribir nuestros tests hemos seleccionado al framework Junit en su versin 4. Junit es un conjunto de libreras que son utilizadas para hacer pruebas unitarias de aplicaciones Java. Bsicamente es un framework que permite hacer pruebas sobre el comportamiento de una clase. Adems brinda la posibilidad de hacer chequeos sobre las salidas esperadas, en caso de que la salida sea la esperada el test termina exitosamente, caso contrario falla. La principal razn por la que seleccionamos Junit es porque ya ha sido adoptado por la comunidad, a tal punto que los IDEs (tanto NetBeans como Eclipse) lo traen incorporado e incluso traen plantillas para crear clases de tests. Junit se basa en el uso de atributos, un mtodo de test se marca con el atributo @Test, al final del test, se usan asserts para verificar la correctitud de los resultados. Por ejemplo un test sumamente simple para verificar la suma de dos valores podra ser como sigue:
@Test public void simpleAdd() { Money m12CHF= new Money(12, "CHF"); Money m14CHF= new Money(14, "CHF"); Money expected= new Money(26, "CHF"); Money result= m12CHF.add(m14CHF); assertTrue(expected.equals(result)); }

Si se requiere escribir varios tests sobre el mismo conjunto de objetos, se pueden usar los fixtures. Se puede marcar un mtodo con @Before para inicializar, este mtodo ser ejecutado antes de cada test. Se puede marcar otro mtodo con @After que ser ejecutado inmediatamente despus de cada test. Por ejemplo, un fixture tpico podra ser el siguiente:
public class MoneyTest { private Money f12CHF; private Money f14CHF; private Money f28USD; @Before public void setUp() { f12CHF= new Money(12, "CHF"); f14CHF= new Money(14, "CHF"); f28USD= new Money(28, "USD"); } }

Adems de la integracin con diferentes IDEs a travs de plugins, Junit tambin cuenta con una variedad de runners. Por ejemplo, para correr tests y ver los resultados mediante una consola se puede ejecutar el siguiente comando:
org.junit.runner.JUnitCore.runClasses(TestClass1.class, ...);

Tambin tiene atributos para definir expectativas. Por ejemplo, para especificar que se espera una excepcin de tipo IndexOutOfBoundsException:

19

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
@Test(expected= IndexOutOfBoundsException.class) public void empty() { new ArrayList<Object>().get(0); }

Tambin hemos evaluado la librera TestNG, muchos de las caractersticas que ofrece Junit, tambin las ofrece TestNG. Son muy similares en muchos aspectos. Una de las diferencias es que TestNG est un poco ms orientado a realizar tests de integracin, no slo puramente unitarios. De hecho muchos dicen que son complementarias, por lo que no descartamos su uso en el futuro cuando debamos testear integracin entre diferentes libreras, templates, etc.

JMock
En la seccin sobre Mocking hemos explicado la importancia del uso de objetos Mock para realizar tests unitarios. Esta tarea es sumamente ardua si no contamos con alguna librera que nos de soporte. Esta eleccin fue ms difcil, ya que existen muchas libreras para esto, la mayora gratuitas, de cdigo abierto y con caractersticas similares. Para comprender las similitudes, presentaremos una tabla comparativa extrada del artculo Java Mock Frameworks Comparision:
Jmock Actual version Website 2.6-RC1 (7 Dec 2008) EasyMock 2.4 (30 Aug 2008) Mockito 1.7 (24 Jan 2009) SevenMock 2.1.0 (17 Jun 2008) Jmockit 0.94 (30 Jan 2008) rMock 2.0.0 (18 Mar 2007) Unitils 2.2 (23 Dec 2008)

http://jmock.org http://easymoc http://code.goo http://sevenhttps://jmockit. k.org gle.com/p/moc mock.sourcefor dev.java.net kito ge.net Specification- Record/Repla Verify after like definition y/Verify run model. of mocks model. Basic Basic methods expectations expectations behavior (looks are defined via are checked like DSL). calling after calling appropriate (mocks mocks remember their methods with methods actual data. invocations). Other types of Other types of expectations expectations are defined are defined as with rules before frameworks running. methods. + + + Method stubbing and expectations are defined using inner classes.

http://rmock.so http://www.uniti urceforge.net ls.org Mockito-like Verify after run model.

Features

Methods Record/Repla stubbing are y/Verify made using model. inner classes. Expectations Annotations for are defined those methods using helper define basic methods. expectations. Other expectations are defined using DSL-like style.

Value returning for stubbed method Exception throwing for stubbed method Invocations count check Method arguments check

+*

+*

+ +

+ +

+ +

-* -*

+ +

+ +

+* +

20

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
Invocations order for one mock check Iterator-style stubbing Real objects spy Callback invocation from stubbed method Mocking of final classes, methods, static and private fields Mocking of equals() and hashcode() methods Thread safe Invocation order between mocks check Total score + + + + + +

+ +

+ +

+ + +

-* -* -

+* +* -

+ + +

+ +

+ +

6,7

7,5

8,3

3,5

4,8

5,8

5,6

* La caracterstica es soportada, pero no es implementada directamente por el framework. Si bien la tabla est desactualizada porque fue hecha hace tiempo, refleja claramente que las caractersticas son similares. Adems las libreras tambin han evolucionado de manera similar. Por nuestra parte, realizamos pruebas de concepto sobre las siguientes: jMock EasyMock Mockito

Son todas similares, ofrecen casi las mismas caractersticas y produjeron resultados satisfactorios. Terminamos por seleccionar Jmock, principalmente porque la habamos utilizado en ocasiones anteriores y nos sentimos ms cmodos con su uso. Muchos dicen que una de las desventajas de Jmock es que su forma de uso es algo compleja y la curva de aprendizaje es un poco ms grande que la de otras libreras. Justamente, como ya habamos utilizado antes Jmock, estas no son grandes desventajas para nosotros. Adems, la mayora de los mtodos de test no utilizan directamente Jmock si no que lo hacen a travs de nuestro proyecto comn que contiene una clase base de la cual heredan todos los test fixtures. Para ms informacin sobre la utilizacin de Jmock, ver la seccin CodeGeneratorCommonTests de este documento. Un tpico test con objetos mock es como sigue:
... create mock objects ...

21

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

public void testSomeAction() { ... set up ... context.checking(new Expectations() {{ ... expectations go here ... }}); ... call code being tested ... context.assertIsSatisfied(); ... other assertions ... }

CVS
En la actualidad, es casi imposible el desarrollo de proyectos en el que participa ms de un desarrollador sin el uso de algn sistema de control de versiones. Podemos encontrar varios, con diferentes caractersticas. Aunque el objetivo principal de cualquiera de ellos es el mismo, mantener un repositorio de cdigo fuente, permitiendo compartir el cdigo. Los cambios que hace un desarrollador son subidos a este repositorio y pasan a ser visible para el resto del equipo. Casi todos tienen tambin la capacidad de resolver conflictos, es decir, diferentes cambios sobre la misma lnea base de un archivo. La decisin de que sistema de control de versiones utilizar no es una decisin sencilla porque hay varios con diferentes caractersticas, pero el resultado final ser casi el mismo porque los principales requisitos son implementados por casi todas las alternativas. Hemos decidido utilizar CVS (Concurrent Versions System) por las siguientes razones: Es muy sencillo de instalar y configurar en un servidor linux. Se integra con los usuarios del sistema y permite dar permisos a diferentes usuarios simplemente otorgando permisos sobre los directorios del disco. Permite la creacin de ramas y tambin el etiquetado de las versiones. Permite hacer bloqueos no exclusivos de los archivos y merge relativamente sencillo. Hay numerosas herramientas cliente para conectarse al repositorio, tanto en modo texto como grfico, y para diferentes sistemas operativos. Lleva varios aos evolucionando y es sumamente estable. Cuenta con plugins para los IDEs NetBeans y Eclipse. El repositorio es central y no distribuido, es decir que el cdigo se encuentra siempre centralizado en el servidor. Maneja archivos de tipo binario y texto. Tambin es sencillo conectar a casi cualquier herramienta para integracin 22

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

contnua con un repositorio CVS. Etc.

Tambin hemos evaluado algunas otras alternativas: Subversion. Es una evolucin de CVS, hoy por hoy son muy parecidos pero Subversion contina agregando nuevas caractersticas mientras que CVS se mantiene estable. Mercurial. Es un sistema de control de versiones gratuito y distribuido. Git. Es otro sistema de control de versiones de cdigo abierto, gratuito y distribuido. Cada clon del repositorio mantiene el historial de cambios completo, se jacta de ser sumamente rpido en sus operaciones de creacin de ramas y mezcla de archivos.

Maven
Para lograr integracin continua en proyectos basados en el lenguaje Java se usa un conjunto de herramientas. Maven es una de las ms importantes, si no la ms importante, utilizada a tal fin. Es una herramienta sumamente poderosa que ayuda a diferentes aspectos durante todo el ciclo de vida de un proyecto. Es muy flexible y cuenta con muchsimos plugins, en los cuales delega ciertas tareas. No es slo una herramienta para compilar, sino que tambin se ocupa de resolver dependencias, correr tests, hacer diferentes tipos de chequeos (como estilos de programacin y busca de bugs comunes), chequear cobertura sobre los tests unitarios automticos, generar reportes de diferente ndole, hacer deploy de entregables contra un servidor, generar sitios y casi todo lo que sea automatizable durante el transcurso de un proyecto de software. Maven, es una palabra en dialecto Yrddish, que significa acumulador de conocimiento. Comenz originalmente como un intento de simplificar el proceso de build en el proyecto Jakarta Turbine. Haba varios proyectos, cada uno con sus archivos de configuracin Ant. Como repositorio se us CVS y los archivos jar generados eran subidos al repositorio. La gente de apache quera una manera estndar de construir los proyectos, una definicin clara de los alcances de cada proyecto, una forma fcil de publicar informacin a cerca de cada proyecto y tambin la posibilidad de compartir archivos de tipo Jar entre diferentes proyectos. El resultado es una herramienta que puede ser usada para administrar cualquier proyecto basado en Java. El objetivo principal de maven es que un desarrollador pueda comprender el estado general de un esfuerzo de desarrollo en el perodo de tiempo ms corto posible. Para alcanzar esta meta, hay diferentes reas que ataca: Hacer el proceso de construccin simple. Si bien el uso de maven no elimina la necesidad de conocer los mecanismos subyacentes, provee una gran capa de abstraccin sobre los detalles.

23

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Proveer un sistema de construccin uniforme. Maven permite hacer build de un proyecto utilizando un archivo de configuracin de extensin pom (Project Object Model) y un conjunto de plugins que son compartidos por todos los proyectos, brindando un sistema de construccin uniforme. Cuando alguien est familiarizado en como funciona maven sobre un proyecto, entonces ya est familiarizado en como funciona para cualquiera, sin necesidad de intentar comprender detalles por separado, con lo cual se logra un ahorro de tiempo considerable. Proveer informacin sobre el proyecto de calidad. Provee gran cantidad de informacin til que es tomada en parte del archivo pom asociada al proyecto, y en parte del propio cdigo. Por ejemplo puede brindar: Documento de cambios (change log) creado directamente utilizando el cdigo fuente. Resolver dependencias entre proyectos. Listas de correo. Reporte sobre tests unitarios, incluyendo cobertura. Mediante el uso de plugins, tambin se puede lograr cualquier informacin basndose en el archivo pom y el cdigo fuente.

Provee guas para las mejores prcticas durante el desarrollo. Tiene como principio fomentar buenas prcticas y guiar a un proyecto en esa direccin. Por ejemplo especificacin, ejecucin y reporte sobre tests unitarios es parte del ciclo de vida estndar. Se han utilizado las mejores prcticas actuales como gua: Mantener el cdigo asociado a los tests por separado del cdigo fuente, pero en el mismo rbol de cdigo. Usar convenciones de nombre para encontrar y ejecutar tests. Los casos de prueba pueden configurar su propio entorno y no se requieren modificaciones al proceso de build para preparar los tests.

Maven tambin tiene como objetivo ayudar en el flujo de trabajo de un proyecto, como en la gestin y liberacin de entregables y en el seguimiento de problemas. Tambin sugiere pautas sobre la estructura de directorios de un proyecto (a travs de los archType), de modo que al conocer la estructura de un proyecto basado en maven se conoce la de cualquiera con la misma base. Permite la migracin transparente hacia nuevas caractersticas. Provee una manera sencilla de actualizar una instalacin de maven, con lo cual incorporar nuevas caractersticas resulta trivial. Del mismo modo, las actualizaciones sobre plugins se pueden incorporar de forma muy fcil.

No resulta sencillo definir lo que es maven, para clarificar la situacin, debemos tener en claro que maven no es: 24

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Una herramienta para generar sitios y documentacin. Una extensin de Ant para descargar dependencias. Un conjunto de scriptles Ant reusables.

Si bien maven sirve para realizar cualquiera de esas tareas, stas no son sus nicas caractersticas y sus objetivos son algo diferentes. Muy a grandes rasgos, las siguientes son las principales caractersticas de maven: Creacin de proyectos simple y siguiendo las mejores prcticas. En segundos se puede crear un nuevo proyecto o mdulo. Uso consistente entre diferentes proyectos, lo cual implica que la curva de adaptacin de un nuevo desarrollador a un proyecto es relativamente pequea. Administracin de dependencias superior, que incluye actualizacin automtica y resolucin de dependencias transitivas. Permite trabajar con diferentes proyectos al mismo tiempo. Repositorios oficiales en crecimiento con una gran cantidad de libreras listas para ser utilizadas. Es extensible, permite escribir plugins en el lenguaje Java y otros lenguajes de scripting. Acceso inmediato a nuevas caractersticas, en general sin configuracin extra. Integracin con Ant, para manejo de dependencias y deploy fuera de maven. Builds basados en modelos. Permite compilar cualquier nmero de proyectos en diferentes tipos de salida, como jar, war, distribuciones basadas en metadata sobre el proyecto. Sitio con informacin sobre el proyecto. Permite crear un sitio o documento pdf que incluya cualquier informacin que se desee. Administracin y distribucin de entregables. Sin configurar demasiado, puede conectarse el sistema de control de versiones y generar un paquete basado en una determinada etiqueta. Tambin puede publicar artefactos utilizados por otros proyectos. Manejo de dependencias. Recomienda el uso de un repositorio central de archivos jar y otro tipo de dependencias. Viene con un mecanismo integrado para descargar todas las dependencias que un proyecto requiera desde ese repositorio. Esto permite a los usuarios maven reutilizar libreras en diferentes proyectos.

Maven se base en el concepto de ciclo de vida, el proceso para construir y distribuir un artefacto (proyecto) est claramente definido.

25

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Hay tres ciclos de vida incorporados: default, clean y site. El ciclo de vida default maneja hasta el deploy de un proyecto. El ciclo de vida clean maneja la limpieza (eliminacin de artefactos generados de la carpeta target) de un proyecto. El ciclo de vida site maneja la creacin de un sitio de documentacin para el proyecto. Un ciclo de vida est compuesto por fases. Cada ciclo de vida est compuesto por una lista de diferentes fases, cada fase representa una etapa en el ciclo de vida. Por ejemplo, el ciclo de vida default est compuesto por las siguientes fases: Validate. Validar que el proyecto es correcto y que se encuentra toda la informacin necesaria para proseguir. Compile. Compilar el cdigo fuente del proyecto. Test. Testear el cdigo compilado usando un framework de testing unitario adecuado. Package. Tomar el cdigo compilado y empaquetarlo en su forma para distribuir, por ejemplo en un archivo jar. Integration-test. Procesar y si es necesario publicar en un entorno en el cual los tests de integracin puedan correr. Verify. Hacer chequeos para verificar que el paquete es vlido y cumple con los criterios de calidad. Install. Instalar el paquete en el repositorio local, para poder ser utilizado por otros proyectos localmente. Deploy. Copiar el paquete final en un repositorio remoto para poder ser compartido con otros desarrolladores y usado en otros proyectos.

Estas fases, a dems de otras que no estn especificadas, corren en orden. Desde la primera hasta la que se requiera. Es decir, que para que absolutamente todo esto ocurra es suficiente con invocar a maven con la ltima fase a ser ejecutada, en este caso:
mvn deploy

Esto es porque cuando se invoca la ejecucin con una fase, no slo se ejecutar esa fase, si no tambin todas las anteriores en el ciclo de vida. Cabe destacar que los mismos comandos tambin se pueden usar en proyectos multi mdulos (con uno o ms subproyectos), por ejemplo :
mvn clean install

Correr clean y luego install (incluyendo todas las fases anteriores) para cada uno de los subproyectos en orden. Una fase est compuesta por metas. Asociadas a cada fase hay un conjunto de metas. 26

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Una meta representa una tarea (ms pequea que una fase), que contribuye a la construccin y administracin de un proyecto. Una meta puede estar ligada a cero o ms fases. Una meta que no est ligada a ninguna fase puede ser ejecutada por fuera del ciclo de vida mediante una invocacin directa. Por ejemplo, si consideramos el siguiente comando, los argumentos clean y package son fases, mientras que dependency:copydependencies es una meta.
mvn clean dependency:copy-dependencies package

Primero, se ejecutar la fase clean (se van a ejecutar todas las fases anteriores, ms la fase en s misma). Luego se ejecutar la meta depandency:copy-dependencies, para finalmente ejecutar la fase package (y todas las fases que le preceden en el ciclo de vida default). Adems, si una meta se liga a ms de una fase, entonces se va a ejecutar por cada una de ellas. Por otro lado, una fase puede tener cero o ms metas asociadas. Si no tiene metas, entonces esa fase no ejecutar. Pero si tiene ligadas una o ms metas, cuando se ejecute la fase, van a ejecutar todas esas metas. La manera ms comn de comenzar un proyecto es indicando el tipo de paquete que se desea en el archivo pom, algunos tipos vlidos son jar, war, ear y pom. Si no se indica ninguno maven asume jar por default. Cada tipo de paquete tiene metas asociadas a diferentes fases del ciclo de vida, por ejemplo el tipo jar asocia metas de la siguiente manera.
process-resources compile process-test-resources test-compile test package install deploy resources:resources compiler:compile resources:testResources compiler:testCompile surefire:test jar:jar install:install deploy:deploy

Otros tipos de paquetes ligan metas de manera muy diferente, por ejemplo en un proyecto donde todo el contenido es meta data (el valor del nodo <packaging> es pom) slo hay metas ligadas a las fases install y deploy. La segunda forma de agregar metas a las fases es configurando plugins a la seccin <build> del archivo pom. Los plugins son artefactos que proveen de metas a maven. Cada plugin puede tener varias metas, cada una de ellas representa una capacidad diferente del plugin. Por ejemplo, el plugin Compiler tiene dos metas: compile y testCompile. La primera compila el cdigo fuente de la aplicacin, mientras que la segunda compila el cdigo fuente asociado a los tests de la aplicacin. Para clarificar el uso de los plugins, veamos una configuracin tpica. En el siguiente ejemplo, el plugin modello liga la meta modello:java a la fase generate-sources. 27

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
... <plugin> <groupId>org.codehaus.modello</groupId> <artifactId>modello-maven-plugin</artifactId> <version>1.4</version> <executions> <execution> <configuration> <models> <model>src/main/mdo/maven.mdo</model> </models> <version>4.0.0</version> </configuration> <goals> <goal>java</goal> </goals> </execution> </executions> </plugin> ...

El elemento <execution> brinda la posibilidad de que una meta pueda ser ejecutada mltiples veces con diferentes configuraciones. Tambin se puede dotar a la ejecucin de un identificador, de este modo, cuando hay herencia de archivos pom se puede controlar como se mezclan estas ejecuciones. Cuando mltiples ejecuciones estn ligadas a una fase particular, son ejecutadas en el orden en el que fueron especificadas en el archivo pom, con ejecuciones heredadas primero. Algunas metas pueden ser ejecutadas en distintas fases, incluso pueden no estar ligadas por default a una fase, en ese caso queda como responsabilidad del desarrollador asociar las metas a la fase que lo desee. Por ejemplo, si tuviramos una meta display:time que imprime por la salida estndar la hora actual, y quisiramos ejecutarla en la fase testresources para indicar cuando comienzan los tests, podramos tener una configuracin como sigue.
... <plugin> <groupId>com.mycompany.example</groupId> <artifactId>display-maven-plugin</artifactId> <version>1.0</version> <executions> <execution> <phase>process-test-resources</phase> <goals> <goal>time</goal> </goals> </execution> </executions> </plugin> ...

Para mayor detalle sobre el ciclo de vida maven consultar la especificacin en el sitio de apache: http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

Maven Plugins
Hemos adaptado y configurado Maven en todos los sentidos que cremos convenientes 28

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

para construir nuestros proyectos. A continuacin intentaremos explicar y ejemplificar de que manera utilizamos ciertos plugins adicionales, as como tambin configuramos algunos de los que vienen por default. Clean El plugin clean se encarga de eliminar archivos o directorios generados en compilaciones anteriores. Cuenta slo con una meta:
clean:clean Intenta eliminar el directorio de trabajo del proyecto

clean:clean. Intenta eliminar el directorio de trabajo del proyecto.

Algunos de nuestros proyectos ejecutan tests que generan un escenario, es decir un directorio con libreras, templates, archivos de entrada y un directorio para la salida y corren el generador con este escenario. Hemos configurado el plugin clean para limpiar este escenario de la siguiente manera:
<plugin> <artifactId>maven-clean-plugin</artifactId> <version>2.4.1</version> <executions> <execution> <id>scenario-clean</id> <phase>process-test-resources</phase> <goals> <goal>clean</goal> </goals> <configuration> <excludeDefaultDirectories>true</excludeDefaultDirectories> <filesets> <fileset> <directory>${testing.scenario.path}</directory> </fileset> </filesets> </configuration> </execution> </executions> </plugin>

Esta configuracin se puede ver en uno de los archivos pom del proyecto CodeGeneratorPoms. Este archivo es el padre de casi todos los archivos de configuracin de nuestros proyectos, por lo que el clean se ejecutar en cualquiera de ellos sin necesidad de ninguna otra configuracin. El directorio que intenta limpiar est definido como una propiedad del proyecto, se puede ver en la seccin <properties> del mismo archivo, esta propiedad puede ser redefinida por archivos pom hijos. La meta clean est asociada a la fase process-test-resources. Con lo cual es ejecutada siempre antes de correr los tests y elimina escenarios creados anteriormente. Properties El plugin properties sirve para leer y escribir propiedades, desde y hacia archivos. El uso ms comn es leer las propiedades definidas en el archivo pom y escribirlas en otro 29

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

archivo (por ejemplo de extensin .properties) para que puedan ser fcilmente utilizadas desde nuestro cdigo java. Cuenta con las siguiente metas:
properties:help properties:read-project-properties properties:set-system-properties properties:write-active-profileproperties properties:write-project-properties Muestra informacin de ayuda sobre como invocar Lee archivos de propiedades y las escribe como propiedades de proyecto Setea propiedades de sistema Escribe propiedades de un perfil activo a un archivo Escribe propiedades de proyecto a un archivo

Si miramos el archivo pom padre definido en el proyecto CodeGeneratorPoms, hay varias propiedades definidas a nivel proyecto:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <freelancesoft.codegenerator.version>1.0-SNAPSHOT</freelancesoft.codegenerator.version> <freelancesoft.codegenerator.lib.version>1.0SNAPSHOT</freelancesoft.codegenerator.lib.version> <freelancesoft.codegenerator.lib.path>$ {user.home}/.codegenerator/lib</freelancesoft.codegenerator.lib.path> <freelancesoft.codegenerator.tpl.path>$ {user.home}/.codegenerator/tpl</freelancesoft.codegenerator.tpl.path> <check.style.config.location>http://devel.freelancesoft.com:8080/fs_checks.xml</check.style.config.location> <testing.scenario.path>${build.directory}/scenario</testing.scenario.path> <testing.scratch.path>scratch</testing.scratch.path> <testing.lib.path>lib</testing.lib.path> <testing.tpl.path>tpl</testing.tpl.path> <testing.target.path>target</testing.target.path> <testing.lib.res.path>${basedir}/src/main/resources/lib</testing.lib.res.path> <testing.tpl.res.path>${basedir}/src/main/resources/tpl</testing.tpl.res.path> </properties>

Estas propiedades son utilizadas para diversos fines, entre otros, las utilizan muchos casos de test para crear el escenario sobre el cual correr el generador. Para que estas propiedades sean de fcil acceso para nuestros casos de test, las debemos copiar en el target. Esto se puede hacer con la siguiente configuracin de plugin:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>properties-maven-plugin</artifactId> <executions> <execution> <phase>process-test-resources</phase> <goals> <goal>write-project-properties</goal> </goals> <configuration> <outputFile>${project.build.testOutputDirectory}/project.properties</outputFile> </configuration> </execution> </executions> </plugin>

30

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Definiendo el siguiente mtodo en la clase base para los tests:


@BeforeClass public static void setUpClass() throws Exception { poperties = new java.util.Properties(); URL url = ParserTestBase.class.getClassLoader().getResource("project.properties"); if (url == null) { throw new Exception("Project properties are missed"); } else { InputStream stream = url.openStream(); poperties.load(stream); stream.close(); } }

Ya contamos con las propiedades de proyecto accesibles desde cualquier caso de prueba y las podemos usar, por ejemplo, para la creacin de escenarios. Surefire Surefire es el plugin usado durante la fase test del ciclo de vida para ejecutar los casos de prueba de una aplicacin. Cuenta con dos metas:
surefire:help surefire:test Muestra informacin del plugin Corre las pruebas unitarias

Surefire es sumamente flexible, podemos encontrar una configuracin en el proyecto CodeGenerator:


<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <includes> <include>**/ParserTestSuite.java</include> </includes> </configuration> </plugin>

En la cual indicamos al plugin que casos de prueba debe ejecutar. En este caso se configura para que no ejecute absolutamente todos los mtodos de test que encuentre, ya que en el proyecto tambin existen algunos casos de prueba de stress (Para tomar algunas medidas, como nivel mximo de clases heredadas que soporta nuestro lenguaje), no deseamos que esos tests sean ejecutados con cada compilacin. Adems de fallar el build si algn caso de prueba no es exitoso, surefire tambin sirve para generar reportes sobre estos casos de prueba. Genera reportes en dos formatos, texto plano y xml. Para que se generen estos reportes se debe agregar el siguiente nodo a la seccin <reporting> del archivo pom:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> </plugin>

31

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

El reporte en texto plano tiene informacin como la que sigue:


------------------------------------------------------------------------------Test set: freelancesoft.codegenerator.parser.ParserTestSuite ------------------------------------------------------------------------------Tests run: 442, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 14.074 sec

Mientras que el reporte en formato xml contiene informacin de cada uno de los casos de prueba que se ejecut. Si quisiramos un reporte en formato html, ms legible para seres humanos, lo podramos generar con otro plugin: http://maven.apache.org/plugins/mavensurefire-report-plugin/ Assembly El objetivo principal del plugin assembly es crear un archivo simple que contenga todas las dependencias, mdulos, documentacin y otros archivos de un proyecto. De este modo se puede distribuir ese archivo como un nico artefacto. Un proyecto puede construir un assembly fcilmente utilizando uno de los descriptores predefinidos. Existen descriptores para ejecutar operaciones comunes como la creacin de un archivo de tipo zip que contenga todos los artefactos generados junto con la documentacin. Pero tambin existe la posibilidad de crear descriptores propios, lo cual brinda un control mucho mayor sobre cmo las dependencias, mdulos, conjuntos de archivos y archivos individuales, son empaquetados en un assembly. El plugin assembly cuenta con las siguientes metas:
assembly:help assembly:single Muestra informacin a cerca del plugin Crea un artefacto a partir de un descriptor

Tambin tiene otras metas a las que se les dej de dar soporte, en su mayora porque la meta single cumple con los objetivos. En otros casos porque esa funcionalidad se agreg al plugin dependency. En nuestro caso particular es utilizado para los siguiente. El generador de cdigo utiliza libreras y templates. Las libreras pueden depender de otras libreras, a su vez los templates pueden depender de otras libreras y templates. Hemos configurado todo nuestro proceso para que las libreras y templates se manejen de un modo similar a un artefacto de tipo jar. Es decir: Una librera o template es empaquetada, mediante el plugin assembly, en un archivo de tipo zip. A su vez, declara en el archivo pom las libreras o templates de las que depende. Cuando ejecutamos un build sobre un proyecto (de librera o template), maven resuelve las dependencias y mediante el plugin depency, las desempaqueta en un 32

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

directorio especificado. Si somos cuidadosos a la hora de marcar las dependencias, este proceso de resolucin es automtico. Con lo cual, es muy simple descargar y utilizar estos artefactos. En los archivos pom de nuestros proyectos de libreras y templates, contamos con una seccin como la siguiente:
<plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptors> <descriptor>dep.xml</descriptor> </descriptors> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin>

Y su respectivo descriptor:
<assembly> <formats> <format>zip</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <fileSets> <fileSet> <directory>${basedir}/src/main/resources/tpl</directory> <outputDirectory></outputDirectory> </fileSet> </fileSets> </assembly>

Con esta simple configuracin, en la fase package, se genera el archivo zip con nuestros archivos escritos en nuestro propio lenguaje. Adems ese archivo es subido a los repositorios durante la fase deploy. Dependency El plugin dependency brinda la posibilidad de manipular artefactos. Puede copiar y/o descomprimir artefactos desde repositorios locales o remotos a directorios especficos. Cuenta con las siguientes metas:
dependency:analyze Analiza las dependencias del proyecto y determina cules son usadas y declaradas, usadas y no declaradas, no usadas y declaradas Analiza las dependencias y lista las que no coinciden con las declaradas en la

dependency:analyze-dep-mgt

33

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier seccin dependencyManagement dependency:analyze-only Igual que analyze, pero no compila

dependency:analyze-report

dependency:analyze-duplicate

Analiza las dependencias del proyecto y genera un reporte que incluye cules son usadas y declaradas, usadas y no declaradas, no usadas y declaradas Analiza las dependencias y las declaradas en el nodo dependencyManagement y determina dependencias duplicadas Indica a maven que debe generar paths a los repositorios locales para ser usados en el comando java -cp Toma la lista de artefactos definidos en la seccin plugin y los copia a un directorio especfico, puede renombrar o agregar nmero de versin Toma la lista de dependencias, directas o transitivas y las copia en un directorio especfico, puede renombrar o agregar nmero de versin Descarga un artefacto, con dependencias transitivas desde un repositorio remoto

dependency:build-classpath

dependency:copy

dependency:copy-dependencies

dependency:get

dependency:go-offline

dependency:list

Indica a maven que resuelva todas las dependencias del proyecto (dependencias, plugins y reportes) preparndose para pasar a modo offline Alias para resolve, que adems lista las dependencias

dependency:properties

Setea una propiedad para cada dependencia con la ubicacin en el sistema de archivos

dependency:purge-local-repository

dependency:resolve

Indica a maven que debe eliminar del repositorio local todos los artefactos correspondientes a dependencias y opcionalmente resolverlas nuevamente Indica a maven resolver dependencias y mostrar el nmero de versin

dependency:resolve-plugins

Indica a maven resolver plugins, con todas sus dependencias

34

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

dependency:sources

Indica a maven resolver dependencias, con el artefacto de cdigo fuente y mostrar el nmero de versin Muestra el rbol de dependencias del proyecto

dependency:tree

dependency:unpack

Como copy, pero tambin descomprime

dependency:unpack-dependencies

Como copy-dependencies, pero tambin descomprime

Adems del uso tpico, hemos configurado este plugin para que pueda lidiar con artefactos que corresponden a paquetes de libreras o templates, escritos en nuestro propio lenguaje. Podemos ver este tipo de configuracin en archivos pom como el que es utilizado como padre para los archivos de configuracin de proyectos de template:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>unpack-lib</id> <phase>process-test-resources</phase> <goals> <goal>unpack-dependencies</goal> </goals> <configuration> <includeTypes>zip</includeTypes> <includeGroupIds>freelancesoft.codegenerator.lib</includeGroupIds> <outputDirectory>${freelancesoft.codegenerator.lib.path}</outputDirectory> <overWriteReleases>true</overWriteReleases> <overWriteSnapshots>true</overWriteSnapshots> </configuration> </execution> <execution> <id>unpack-tpl</id> <phase>process-test-resources</phase> <goals> <goal>unpack-dependencies</goal> </goals> <configuration> <includeTypes>zip</includeTypes> <includeGroupIds>freelancesoft.codegenerator.tpl</includeGroupIds> <outputDirectory>${freelancesoft.codegenerator.tpl.path}</outputDirectory> <overWriteReleases>true</overWriteReleases> <overWriteSnapshots>true</overWriteSnapshots> </configuration> </execution> </executions> </plugin>

Con esta configuracin, todos los artefactos declarados como dependencias, incluyendo 35

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

las dependencias transitivas, son descargados desde los repositorios y descomprimidos en los directorios que corresponde antes de la ejecucin de los casos de prueba. Otro aspecto interesante de este plugin es la generacin de un reporte sobre las dependencias del proyecto. Si ejecutamos:
mvn site

En el sitio generado del proyecto veremos una seccin Dependencies que contiene informacin muy til:

36

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

37

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Check-Style El plugin check-style genera un reporte acerca del estilo de programacin de los desarrolladores. No slo es capaz de generar un reporte, si no que tambin se lo puede configurar para que falle la compilacin si no se siguen ciertas convenciones preestablecidas en cuanto al estilo de programacin. Para hacer los chequeos utiliza una herramienta externa. Gracias a este plugin podemos asegurar un estilo uniforme, an cuando varias personas trabajen en el proyecto. El plugin cuenta con las siguientes metas:
checkstyle:checkstyle Realiza un anlisis del estilo sobre el cdigo y genera un informe con las violaciones

checkstyle:check

Realiza un chequeo de violaciones sobre la ltima corrida, lee el archivo de salida de CheckStyle cuenta el nmero de violaciones y las muestra por consola

En nuestro caso, no hemos utilizado este plugin para todos los proyectos, pero s para los que consideramos importante que se sigan ciertos lineamientos en cuanto al estilo de programacin, como el proyecto CodeGenerator y el proyecto CodeGeneratorCommon. Un ejemplo de como configuramos el plugin es el siguiente:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-checkstyle-plugin</artifactId> <configuration> <logViolationsToConsole>false</logViolationsToConsole> <consoleOutput>true</consoleOutput> <propertyExpansion>basedir=${basedir}</propertyExpansion> <configLocation>${check.style.config.location}</configLocation> <excludes> **/CodeGeneratorParserBase.java, **/CodeGeneratorParserBaseTreeConstants.java, **/JJTCodeGeneratorParserBaseState.java, **/TokenMgrError.java, **/CodeGeneratorParserTreeConstants.java, **/Token.java, **/JavaCharStream.java, **/CodeGeneratorParserBaseTokenManager.java, **/CodeGeneratorParserBaseConstants.java, **/ParseException.java </excludes> </configuration> <executions> <execution> <id>check</id> <goals> <goal>check</goal> </goals> </execution> </executions> </plugin>

De este modo, check-style queda configurado para fallar si no se siguen nuestras convenciones. A dems tambin se puede ver que excluimos ciertas clases del chequeo 38

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

de estilo, esto es porque son clases generadas por JavaCC y no es posible lograr total uniformidad sobre las mismas. En cuanto a las reglas que hemos definido, se puede apreciar una propiedad de proyecto, el valor default de esa propiedad est dado en el archivo pom padre. Nuestras reglas se pueden ver en http://devel.freelance-soft.com/xml/fs_checks.xml. Bsicamente tomamos el archivo sun_checks.xml que viene en el descargable de CheckStyle y relajamos o modificamos diferentes reglas. Algunas de las modificaciones que aplicamos son las siguientes: Quitamos el mdulo NewlineAtEndOfFile. Con este mdulo se exige que cada archivo de cdigo fuente termine en un carcter de nueva lnea. Directamente quitamos el mdulo porque no funcionaba bien al modificar y compilar cdigo fuente en distintas plataformas (windows y linux). Los mdulos JavadocMethod, JavadocType y JavadocVariable se encargan de chequear que cada mtodo, tipo o variable respectivamente tenga el correspondiente comentario JavaDoc. Para estos mdulos modificamos una propiedad para que se permita violar la regla en mtodos, tipos y variables privadas. El mdulo ConstantName exige que los nombres de constantes estn escritos en maysculas. Modificamos propiedades, para que no se produzca una violacin si no se respeta la regla para variables privadas o protegidas. El mdulo AvoidStarImport evita imports que finalicen con un carcter asterisco. Agregamos una excepcin para org.junit.Assert.*, ya que este paquete se usa nicamente para los tests y resulta conveniente importarlo de este modo. El mdulo LineLength se encarga de chequear que ninguna lnea supere una determinada cantidad de caracteres. Aumentamos esa cantidad de caracteres a 185. Eliminamos el mdulo AvoidInlineConditionals, con el cual no es posible definir condicionales en una nica lnea, con lo cual resultara imposible utilizar el operador ternario ?. El mdulo HiddenField evita que se oculten campos, un caso tpico en el que se ocultan campos es cuando una variable de un mtodo tiene el mismo nombre que un atributo interno. Agregamos propiedades al mdulo para que no realice chequeos sobre constructores o mtodos setter. Quitamos el mdulo FinalParameters, que chequea que mtodos, constructores, bloques catch y foreach tengan sus parmetros declarados como final. Quitamos el mdulo TodoComment, con el cual no es posible dejar comentario TODO en el cdigo. Este mdulo es de utilidad si lo nico que queremos es generar el reporte sobre estilos, pero no es posible utilizarlo si queremos que el build falle cuando no se respeta alguna regla.

39

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Agregamos el mdulo AvoidStaticImport, que evita importaciones de paquetes estticos, con una propiedad para que se permita org.junit.Assert.* ya que es la manera ms simple para trabajar sobre los casos de test. El mdulo ClassDataAbstractionCoupling mide el nmero de instancias de otras clases, dentro de una clase dada. Este mdulo fue agregado con un valor mximo de 100. El mdulo ClassFanOutComplexity mide el nivel de herencia para una determinada clase. Este mdulo fue agregado con un mximo de 20. El mdulo CyclomaticComplexity chequea complejidad ciclomtica. Fue agregado con un mximo de 15. Se agreg el mdulo DefaultComesLast, que chequea que el default est despus de todos los casos en un switch. Se agreg el mdulo MethodCount que chequea el nmero de mtodos dentro de una clase. Se agreg el mdulo ModifiedControlVariable que asegura que la variable de control de un ciclo for no sea modificada en el cuerpo del mismo. Se agreg el mdulo NpathComplexity que chequea otra medida de complejidad, similar a la ciclomtica. Adems tambin se hicieron otras modificaciones de menor importancia.

Como dijimos anteriormente, el objetivo principal de este plugin es la generacin de un reporte sobre el estilo de programacin de los desarrolladores, para que este reporte sea generado se debe agregar lo siguiente a la seccin <reporting> del archivo pom:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-checkstyle-plugin</artifactId> <configuration> <logViolationsToConsole>false</logViolationsToConsole> <consoleOutput>true</consoleOutput> <propertyExpansion>basedir=${basedir}</propertyExpansion> <configLocation>${check.style.config.location}</configLocation> <excludes> **/CodeGeneratorParserBase.java, **/CodeGeneratorParserBaseTreeConstants.java, **/JJTCodeGeneratorParserBaseState.java, **/TokenMgrError.java, **/CodeGeneratorParserTreeConstants.java, **/Token.java, **/JavaCharStream.java, **/CodeGeneratorParserBaseTokenManager.java, **/CodeGeneratorParserBaseConstants.java, **/ParseException.java </excludes> </configuration> </plugin>

Con esta configuracin, si ejecutamos: 40

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
mvn site

Encontraremos un reporte en el sitio generado. Este reporte cuenta con varias secciones, una de ellas muestra las reglas aplicadas. Las dems son referentes a las violaciones encontradas:

A dems de esta herramienta tambin hemos analizado el uso, como alternativa o complemento, del plugin pmd. Hicimos algunas pruebas de concepto, llegando a las siguientes conclusiones: Pmd intenta chequear, no solo estilo de programacin, si no tambin posibles errores. CheckStyle es ms certero y configurable, en lo que a estilo se refiere. En lo que respecta a la bsqueda de posibles errores en el cdigo, existen otras herramientas, como FindBug, que son ms adecuadas. Es decir producen resultados que a nuestro criterio son ms tiles. Preferimos utilizar una herramienta que se ocupe de tareas ms pequeas y de una manera ms adecuada, en lugar de una que intente abarcar ms de un 41

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

aspecto de un problema. Es posible utilizar CheckStyle y Pmd en conjunto, pero hay muchsimas reglas que se solapan y no consideramos adecuado hacer un doble chequeo sobre las mismas. Con lo cul el mantenimiento de las reglas que se desean aplicar sera mucho ms costoso.

Por estas razones hemos decidido, de momento, descartar el uso de Pmd y optar por la combinacin CheckStyle-FindBugs. FindBugs FindBugs busca errores en programas java, est basado en el concepto de patrones de errores. Un patrn de error es una porcin de cdigo, que generalmente se corresponde a un error. Los patrones de errores surgen por varias razones: Caractersticas complejas del lenguaje. Mtodos que suelen entenderse mal. Modificaciones durante el mantenimiento que introducen errores comunes. Otros errores comunes, como tipogrficos, mal uso de operadores booleanos, etc.

FindBugs usa anlisis esttico para inspeccionar bytecode java en busca de patrones de errores. Est comprobado que en la mayora de los casos encuentra errores reales, por el tipo de anlisis que hace, muchas veces reporta falsos errores (pero el porcentaje suele ser menor al %50). El plugin de maven que da soporte a FindBugs brinda las siguientes metas:
findbugs:check Falla el build si existe alguna violacin a FindBugs, por default crea un reporte en el directorio de compilacin Genera un reporte, por default corre en la fase site

findbugs:findbugs

findbugs:gui

Ejecuta una interfaz de usuario que sirve para depurar los posibles errores Muestra ayuda sobre el plugin

findbugs:help

Al igual que CheckStyle, no utilizamos FindBugs sobre todos nuestros proyectos, de momento est configurado para correr sobre CodeGenerator y CodeGeneratorCommon. Una configuracin tpica, en el archivo pom de un proyecto, se ve como sigue:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>findbugs-maven-plugin</artifactId> <configuration>

42

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
<fork>false</fork> <excludeFilterFile>findbugs-exclude.xml</excludeFilterFile> </configuration> <executions> <execution> <id>check</id> <goals> <goal>check</goal> </goals> </execution> </executions> </plugin>

Con esto, el plugin falla el build si encuentra violaciones. A dems, si se encuentran violaciones se puede ejecutar:
mvn findbugs:gui

Con lo cual veremos una interfaz de usuario sumamente til para depurar los errores:

Por otra parte, tambin se puede utilizar findbugs para generar un reporte en el sitio de proyecto a cerca de los posibles errores que se hayan encontrado. Para esto se debe agregar la siguiente configuracin al archivo pom en la seccin <reporting>:
<plugin>

43

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
<groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> </plugin>

Con lo cual encontraremos las siguientes secciones en el reporte generado en el sitio de proyecto:

En conclusin, el uso de la combinacin FindBugs-CheckStyle posibilita el mantenimiento de cdigo uniforme y libre de errores comunes. Cobertura Este plugin provee a maven de la capacidad de utilizar la Cobertura. Cobertura es una herramienta gratuita, que calcula el porcentaje de cdigo que ha sido probado por los tests unitarios automticos. Es de utilidad para detectar porciones de cdigo que carecen de pruebas suficientes. Cobertura posee las siguientes caractersticas: Puede ser ejecutado desde ant, maven o lnea de comandos. Instrumenta bytecodes java, luego de que el cdigo fue compilado. Puede generar reportes en formatos html o xml. Muestra los porcentajes, en cuanto a lneas y ramas que fueron cubiertos en cada clase, paquete y sobre el proyecto completo. Muestra la complejidad ciclomtica de McCabe de cada clase, paquete, y sobre el proyecto completo. 44

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

El resultado html puede ser ordenado de forma ascendente o descendente en cuanto a nombre de clase, porcentaje de lneas cubiertas, porcentaje de ramas cubiertas, etc.

Para configurar este plugin, debemos agregar las siguientes lneas al archivo pom:
<configuration> <check> <haltOnFailure>true</haltOnFailure> <branchRate>0</branchRate> <lineRate>85</lineRate> <totalBranchRate>0</totalBranchRate> <totalLineRate>78</totalLineRate> <packageLineRate>80</packageLineRate> <packageBranchRate>0</packageBranchRate> <regexes> ... <regex> <pattern>.*UnnamedVariable</pattern> <lineRate>80</lineRate> <branchRate>0</branchRate> </regex> </regexes> </check> </configuration>

Como puede apreciarse en la configuracin, hemos decidido implementar cobertura de lneas, pero no de ramas ya que nos parece una exigencia extrema. Configurado de este modo, el plugin falla el build en el caso de que no se cumplan los porcentajes de cobertura deseados. Tambin cuenta con la posibilidad de agregar un reporte al sitio del proyecto, para que este reporte sea generado debemos agregar en la seccin <reporting> del archivo pom las siguientes lneas:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>cobertura-maven-plugin</artifactId> </plugin>

Luego, si ejecutamos:
mvn site

En el sitio generado encontraremos un nuevo reporte con datos sumamente tiles:

45

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Lo interesante de este reporte es que, no slo muestra porcentaje de cobertura, si no que los nombres de clase estn directamente asociados al cdigo fuente y adems muestra con diferentes colores lneas cubiertas y no cubiertas:

Existe una alternativa a Cobertura que hemos evaluado, es la herramienta Emma. Emma hace prcticamente lo mismo que Cobertura, trabajan de similar manera (instrumentando a nivel bytecode), tambin cuenta con plugin para maven y posee casi todas las mismas caractersticas. Luego de algunas pruebas de concepto, hemos optado por Cobertura, por 46

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

las siguientes razones: Aparentemente el proyecto principal de Cobertura est siendo mantenido de una manera mucho ms activa que el de Emma. Cobertura cuenta con integracin directa con NetBeans, se pueden ver directamente en el IDE los reportes generados, incluso marca con diferentes colores el nivel de cobertura directamente sobre el cdigo fuente. El reporte generado por Cobertura es mucho ms rico que el que genera Emma. Cobertura posee una capacidad mayor para ser configurable. Cobertura toma ms medidas que Emma. La nica ventaja que encontramos de Emma sobre Cobertura, es que es ms eficiente a la hora de instrumentar. Con esto se logra ejecutar un build de manera ms rpida, de momento eso no es problema para nosotros.

Con el uso de esta herramienta, podemos asegurar que en la mayora de nuestros proyectos hemos logrado una cobertura mayor al %85. Esto teniendo en cuenta que medimos cobertura de lneas y que a dems, contamos con excepciones para ciertas clases, para las cuales no es posible llegar a ese nmero. Esto es debido a que tenemos clases generadas por JavaCC, con lneas prcticamente imposibles de cubrir. Tambin tenemos porciones de cdigo que surgen de programar a la defensiva, es decir, chequear errores que jams se deberan dar. AntRun Apache ant es una librera y lnea de comando que sirve para manejar el proceso descripto en un archivo de build. El uso principal de esta herramienta es construir aplicaciones Java. Provee tareas predefinidas para compilar, ensamblar, testear y correr aplicaciones Java. Tambin puede ser utilizado para aplicaciones no Java, por ejemplo C o C++. Ms precisamente, ant puede ser utilizado para cualquier proceso que pueda ser descripto en trminos de objetivos y tareas. El plugin AntRun provee la habilidad de correr tareas ant desde maven. Incluso se pueden embeber scripts ant dentro del archivo pom. La intencin del plugin no es ensuciar el archivo pom, por lo que se recomienda (para grandes definiciones), escribir las tareas en un archivo build.xml y utilizarlo dentro del archivo pom. Uno de los objetivos principales del plugin, es facilitar la migracin de proyectos desde ant a maven. Algunos proyectos pueden estar utilizando funcionalidad a medida escrita para ant y que no soporta maven por default. El plugin provee de las siguientes metas:
antrun:help antrun:run Muestra informacin de ayuda acerca del plugin Permite correr tareas ant

Uno de nuestro proyectos, fs-schemas, consiste de un conjunto de distintos archivos xml. 47

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Uno de ellos (fs-checks.xml) es el que define nuestro estilo de programacin y es el que utiliza el plugin CheckStyle. Los dems son los esquemas que describen archivos xml vlidos para utilizar como entrada del generador de cdigo. Todos estos archivos deben estar disponibles a travs de la red para poder ser utilizados. Para actualizar estos archivos en el servidor utilizamos el protocolo FTP. Para poder subir los archivo va FTP consideramos un plugin para maven llamado Maven Wagon FTP, este requiere de libreras adicionales dentro del repositorio maven, lo cual nos pareci un despropsito. Por eso decidimos utilizar tareas ant para subir los archivos. Con la siguiente configuracin, maven utiliza ant para realizar esta tarea:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <executions> <execution> <id>ftp-xml-install</id> <phase>install</phase> <configuration> <tasks> <ftp action="del" server="${ftp.xml.server}" remotedir="/var/www/html/xml" userid="${ftp.xml.user}" password="${ftp.xml.pass}" depends="yes" verbose="yes"> <fileset> <include name="**" /> </fileset> </ftp> <ftp action="rmdir" server="${ftp.xml.server}" remotedir="/var/www/html/xml" userid="${ftp.xml.user}" password="${ftp.xml.pass}" depends="yes" verbose="yes"> <fileset> <include name="**" /> </fileset> </ftp> <ftp action="send" server="${ftp.xml.server}" remotedir="/var/www/html/xml" userid="${ftp.xml.user}" password="${ftp.xml.pass}" depends="yes" verbose="yes"> <fileset dir="${project.build.outputDirectory}"> <include name="**" /> </fileset> </ftp> </tasks> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>ant</groupId> <artifactId>ant-commons-net</artifactId> <version>1.6.5</version> </dependency> <dependency> <groupId>ant</groupId> <artifactId>ant-nodeps</artifactId> <version>1.6.5</version> </dependency> </dependencies> </plugin>

48

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

De este modo ejecutando la fase install, mantenemos actualizados todos nuestros esquemas y el archivo con polticas para CheckStyle, el cual puede ser reutilizado entre diferentes proyectos ya que se encuentra disponible en lnea.

Tomcat
Casi todas las herramientas que se utilizan hoy en da requieren de cierto soporte del lado servidor. Casi todos los manejadores de repositorios maven y administradores para la integracin continua estn implementados sobre la base de Java Servlet y/o JavaServer pages. Una buena pregunta es: Quin dar soporte a estas ltimas dos tecnologas para que podamos instalar el resto de las aplicaciones que deseamos utilizar? En el mercado existen varias implementaciones exitosas, algunas de las ms conocidas son Tomcat, Glassfish, Jboss y Jetty. Sobre las tres hemos hecho algunas pruebas de concepto instalando diferentes aplicaciones. Si buscamos en internet, podremos encontrar varios cuadros comparativos y diversas opiniones sobre todos estos servidores de aplicaciones. No nos detendremos en un listado exhaustivo de sus caractersticas. Simplemente intentaremos listar las razones que nos llevaron a seleccionar tomcat como nuestro servidor de aplicaciones. En lneas generales, JBoss y Jetty son las que menos caractersticas ofrecen. Pero son ideales para lograr una aplicacin standalone, es decir para correr una aplicacin simplemente ejecutando el distribuible que se descarga desde la pgina del autor. De hecho, una gran cantidad de estas aplicaciones ofrecen la descarga de un archivo jar, con Jetty integrado, simplemente con ejecutar el jar tenemos nuestra aplicacin funcionando y podemos accederla desde un navegador bajo un puerto especfico. Dado que tendremos varias aplicaciones corriendo, nos pareci conveniente tener slo una instancia de servidor, que nos brinde la posibilidad de un administrador mediante el cual podamos ejecutar y parar las diversas aplicaciones. Por todo esto, descartamos Jboss o Jetty, creemos que su aspecto ms interesante es para embeberlo y lograr aplicaciones standalone. Glassfish es un producto mucho ms nuevo que Tomcat. Viene en sus dos versiones, edicin open source y oracle. Mientras que Tomcat es un producto de apache y es totalmente cdigo abierto. Aqu surgen varios puntos a tener en cuenta. Glassfish parece ser sencillo y sumamente flexible. Por ser ms nuevo podemos pensar que Tomcat es ms estable, pero Glassfish se est desarrollando ms activamente. Yendo al grano, no hemos encontrado grandes diferencias para el uso que nosotros le daremos que nos lleven a seleccionar uno u otro. El punto principal por el cual seleccionamos Tomcat es que luego de hacer pruebas en un servidor real, parece que Tomcat consume mucho menos recursos, esto teniendo en cuenta que no tendremos una gran cantidad de aplicaciones corriendo. En nuestro caso, estamos limitados de recursos, sobre todo de memoria en el servidor.

49

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Archiva
Maven utiliza el concepto de repositorio para manejar artefactos, ya sean nuestros propios archivos o de terceros, los cuales podemos utilizar como dependencias. Al ejecutar un build podemos resolver dependencias contra repositorios oficiales, pero si deseamos hacer un mantenimiento de nuestros propios paquetes, debemos contar con nuestro propio manejador. Los manejadores de repositorios maven sirven para dos propsitos: actan como proxies altamente configurables entre los repositorios de una organizacin y los repositorios maven pbicos y adems proveen a una organizacin de un lugar centralizado donde alojar sus propios artefactos. Utilizar un proxy para repositorios maven tiene varios beneficios. Se incrementa sustancialmente la velocidad a la hora de obtener dependencias ya que utilizan una cach para todos los artefactos que obtienen desde el repositorio maven central. Si un desarrollador requiere una versin especfica de un artefacto especfico y estamos utilizando un manejador de repositorio maven, las dependencias (incluyendo las dependencias transitivas) se descargarn slo una vez desde los repositorios remotos. Con una conexin de internet de alta velocidad, esto parece ser un tema menor, pero si cada desarrollador est constantemente descargando cientos de megabytes por dependencias de terceros, la verdadera ganancia se encuentra en tiempo que toma maven para chequear por nuevas versiones y descargar dependencias. Configurando a maven para descargar dependencias desde un repositorio local puede ahorrar cientos de requests http y en proyectos de gran tamao con varios mdulos, puede ahorrar gran tiempo a la hora de compilar. En nuestro caso particular, no contamos con un repositorio totalmente local porque no poseemos la infraestructura. Es decir, trabajamos desde nuestras casas utilizando un servidor que s cuenta con un repositorio local. De todas formas los beneficios siguen siendo enormes. Cuando compilamos de manera local, las dependencias sern descargadas desde nuestro servidor, pero builds nocturnos se ejecutarn descargando dependencias directamente desde la red local. Una versin snapshot de un artefacto, es una versin que an se encuentra en desarrollo y recibe modificaciones constantemente. Si un proyecto depende de muchos artefactos snapshot, Maven necesitar chequear por versiones actualizadas de estos artefactos. Dependiendo de la configuracin, maven har chequeos por actualizaciones peridicamente o por cada build. Cuando maven chequea por una actualizacin de un artefacto snapshot, debe interrogar al repositorio remoto por la ltima versin. Dependiendo de la conexin a internet, y de la carga del repositorio central de maven, una actualizacin de un artefacto snapshot puede agregar segundos a un build. Cuando contamos con un manejador de repositorio local con un proxy, el manejador de repositorio puede hacer chequeos peridicos por actualizaciones de snapshots, y las aplicaciones interactuarn directamente con el repositorio local. Si desarrollamos grandes proyectos con muchos mdulos y muchas dependencias de tipo snapshots, con el uso de un repositorio local, se puede pasar de tardar varios segundos, a solo algunos milisegundos para resolver y descargar dependencias. Adems del ahorro en cuanto a tiempo y ancho de banda, un repositorio local provee a 50

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

una organizacin el control sobre lo que maven descarga. Se pueden incluir o excluir artefactos especficos de los repositorios pblicos. Tener este tipo de control sobre los que es descargado desde el repositorio central es un prerrequisito para organizaciones que requieren un control estricto sobre las dependencias que son utilizadas en toda la organizacin. Por otra parte, una organizacin puede desear estandarizar la versin que usa de ciertos artefactos, como por ejemplo Spring o Hibernate, puede hacerlo de una manera muy sencilla dando acceso slo a las versiones que quiera en el manejador de repositorio. Otras organizaciones tambin pueden estar interesadas en utilizar slo artefactos con licencias compatibles a las suyas. Si una corporacin est desarrollando una aplicacin que desea distribuir, puede asegurarse que no se utilice una librera con licencia copy-left, como GPL. Los manejadores de paquetes proveen a las organizaciones de un nivel de control con el cual pueden asegurar que toda su arquitectura y polticas son respetadas. Ms all de los beneficios de contar con un proxy entre los repositorios remotos y la organizacin, un administrador de repositorio tambin provee de algo esencial para la adopcin plena de maven. Adems de resolver dependencias con artefactos de terceros, tambin provee de un mecanismo para compartir nuestros propios artefactos en sus dos tipos de versiones, release y snapshot. Un administrador de repositorio maven provee con un destino para hacer deploy. Una vez instalado el administrador, se puede comenzar a utilizar maven para alojar nuestros propios paquetes. Despus de un tiempo este podr ser el punto central de colaboracin entre diferentes equipos. Existe una lista de administradores de repositorio que la gente de apache sugiere en la pgina de maven, entre ellos se encuentran los siguientes: Nexus absorbi todas las caractersticas de su predecesor (Proximity). Proximity es un producto que cre Tamas Cservenak en el ao 2005, dos aos ms tarde la empresa Sonatype crea Nexus junto a Tamas. Artifactory es un administrador de repositorio maven 2 a nivel empresarial. Ofrece caractersticas avanzadas en cuanto a proxy, caching y seguridad. Lo utilizan desde pequeos grupos de desarrollo hasta grandes corporaciones, desarrollando productos en los que participan desde decenas hasta cientos de desarrolladores. Artifactory logra una robusta plataforma de administracin de artefactos, tiene una interfaz de usuario basada en Ajax y puede utilizarse simplemente descargando, descomprimiendo y corriendo. Apache Archiva es un administrador de repositorio extensible. Es perfecto para utilizar junto con herramientas como maven, Continumm y ANT. Tiene varias caractersticas como proxy, seguridad, almacenamiento, bsqueda, indexado, reporte de uso y ms.

En cuanto a nuestra experiencia con el uso de estas herramientas, no encontramos diferencias en su utilizacin desde maven. Es decir todas sirven de igual manera para conectarlas con maven, resolver dependencias y hacer deploy de nuestros propios artefactos. Las diferencias fundamentales se encuentran en otras caractersticas. Pensamos que la interfaz de usuario ms rica la provee artifactory, ya que est basada en requerimientos ajax a travs de la red. 51

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Su interfaz es ms completa y provee de ms caractersticas de configuracin. A nuestro criterio tiene dos problemas. El primero es que ofrece versiones pagas y open source, o sea que no es totalmente libre. Esto no termina de ser un problema ya que con la versin gratuita sera suficiente para nosotros por el momento, la versin paga ofrece un mayor nmero de caractersticas, pero casi todas apuntadas al uso empresarial. El segundo problema es que si bien su interfaz es ms rica, consume ms recursos. Por ahora estamos limitados en cuanto a cantidad de memoria o nmeros de request simultneos. Por estas razones estamos utilizando Archiva.

52

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Si bien la interfaz de Archiva es ms rudimentaria, provee de todas las caractersticas que requerimos a un costo (en cuanto a recursos) bastante menor. Adems es desarrollado por la organizacin Apache y es totalmente libre.

Jenkins (antes hudson)


Sabemos que es responsabilidad de cada desarrollador medir el impacto de un cambio. Pero en grandes proyectos, donde muchos artefactos dependen de otros esto es muy difcil de lograr. Muchas veces, con cambios en proyectos de este tipo, el mejor acercamiento al que podemos llegar es implementar integracin continua centralizada en un servidor. De este modo, un desarrollador puede introducir un cambio con el cual deja de funcionar un proyecto que depende del proyecto en el cual se est introduciendo el cambio y este problema se detectar a ms tardar al da siguiente, ya que podemos configurar nuestro servidor de integracin continua para ejecutar todos los build de todos 53

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

los proyectos en orden, en un horario donde la carga sea baja. Hasta hace un tiempo atrs, la mejor opcin para implementar integracin continua centralizada en un servidor para aplicaciones java era la herramienta hudson. Hudson era una herramienta de cdigo abierto soportado por la empresa Sun, cuando Oracle compr Sun ya no se le di el mismo soporte. Hubo problemas incluso por el nombre hudson. Por estas razones surgi una rama totalmente libre y de cdigo abierto denominada Jenkins. La realidad es que si bien en el futuro Jenkins y Hudson tomarn diferentes caminos, hoy en da prcticamente no hay ninguna diferencia. Hemos decidido usar Jenkins simplemente porque no existe ninguna restriccin y es mantenido por la comunidad. Utilizando esta herramienta hemos definido una serie de builds en el servidor para soportar integracin continua de todos nuestros proyectos:

CodeGeneratorPoms-deploy: descarga por cvs la solucin CodeGeneratorPoms y ejecuta maven con las metas clean deploy. CodeGeneratorModules-deploy: descarga por cvs la solucin CodeGeneratorModules y ejecuta maven con las metas clean deploy. CodeGenerator-coverage: descarga por cvs la solucin CodeGeneratorModules/CodeGenerator y ejecuta maven con las metas cobertura:clean cobertura:check. CodeGeneratorLibrary-deploy: descarga por cvs la solucin CodeGeneratorLibrary y ejecuta maven con las metas clean deploy. CodeGeneratorTemplates-deploy: descarga por cvs la solucin CodeGeneratorTemplates y ejecuta maven con las metas clean deploy. FscodeGeneratorProjectType-deploy: descarga por cvs la solucin FscodeGeneratorProjectType y ejecuta maven con las metas clean deploy. CodeGenerator-nightly-build: ejecuta todas las acciones anteriores en orden, 54

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

detenindose ante la primer falla. La idea de utilizar estas definiciones, es que si un desarrollador introduce un cambio en alguno de estos proyectos, luego de hacer el commit a travs de cvs debe ejecutar manualmente el build que corresponda asegurndose de que quede en estado verde. Por las noche, en un horario en el que no se sobrecargar al servidor, se ejecutar automticamente el ltimo build. Diariamente deberamos corroborar que el build nocturno finaliz correctamente, de hecho se lo puede configurar para que enve un e-mail en caso de algn fallo.

El lenguaje
En esta seccin explicaremos aspectos del lenguaje creado para la generacin de cdigo. No lo haremos de forma extensiva ya que excede los lmites de esta documentacin. El primer aspecto a tener en cuenta es que es un lenguaje de scripting con delimitadores.
<%% %%>

Los delimitadores funcionan de igual manera que los que utiliza php, <?php y ?>. Todo lo que se encuentre dentro de los lmites de <%% y %%> es considerado cdigo del lenguaje y ser interpretado. Todo lo que se encuentre por fuera de los limitadores ser considerado parte del template y se intentar escribirlo en el archivo actual de salida, si no hay ningn archivo en donde escribir an, se proceder a mostrar un error. Para clarificar el uso de los delimitadores veamos un ejemplo:
<%% Writer.open(__Config.get("scratch") $ "/dir/testFile"); Writer.echo("String test 1 - "); @("String test 2 - "); %%>String test 3<%% Writer.close(); %%>

En el bloque de cdigo anterior se pueden apreciar tres formas de escribir en el archivo testFile. La primera, es invocando directamente a la funcin del lenguaje a tal fin. En la segunda se usa un alias de la funcin anterior. Mientras que en la tercera se utilizan los delimitadores. Esto, sumado a la posibilidad de incluir otros archivos es sumamente atractivo para combinar el uso del lenguaje con templates que representen la estructura 55

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

de ciertas partes del cdigo a generar. Si ejecutamos el generador directamente sobre un archivo con el contenido del ejemplo anterior, se generar un archivo de nombre testFile con el contenido String test 1 - String test 2 - String test 3. Este ejemplo se sumamente simple, pero demuestra el poder del generador. En cuanto a la sintaxis del lenguaje es un lenguaje basado en C, hereda del mismo la mayor parte de las estructuras de control, la manera de formar expresiones es la misma. Pero a dems cuenta con otras estructuras, muchas para dar soporte a orientacin a objetos.

Tipos nativos
El lenguaje soporta 6 tipos primitivos. Cuatro tipos escalares: Boolean. Es el tipo ms simple, expresa un valor de verdad. Como literal puede ser true o false. Integer. Es un nmero del conjunto = {..., -2, -1, 0, 1, 2, }. Los integer pueden ser especificados mediante notacin decimal (base 10), hexadecimal (base 16), octal (base 8) o binaria (base 2), opcionalmente precedidos por un signo (- o +). Los tamaos de un Integer dependen de la plataforma, es decir de la mquina virtual de java subyacente. No estn limitados por el lenguaje de generacin, si no por el lenguaje Java. Float. Los nmeros de punto flotante (tambin conocidos como "flotantes", "dobles" o "nmeros reales") pueden ser especificados usando cualquiera de las siguientes sintaxis:
<%% a = 1.234; b = 1.2e3; c = 7E-10; %%>

String. Un String es una cadena de caracteres. La forma de especificar un literal es la misma que en el lenguaje Java y las limitaciones tambin estn dadas por la mquina virtual subyacente.

Y dos tipos compuestos: Array. Un array (matriz) es en realidad un mapa ordenado. Un mapa es un tipo de datos que asocia valores con claves. Este tipo es optimizado para varios usos diferentes; puede ser usado como una matriz real, una lista (vector), tabla asociativa (caso particular de implementacin de un mapa), diccionario, coleccin, pila, cola y probablemente ms. Ya que los valores de un array pueden ser otros array, tambin es posible crear rboles y array multidimensionales. Por default las claves de los arreglos estarn ordenadas, primero estarn las claves enteras de menor a mayor y luego las claves de tipo string en orden 56

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

alfabtico. La sentencia foreach sobre un arreglo recorrer el arreglo segn el orden de sus claves. Object. Para dar soporte a la orientacin a objetos, existe el tipo Object. Todos los objetos que se crean, heredarn del mismo.

Sobre los tipos escalares existe conversin explcita. Es decir, 0 se convierte a FALSE en un contexto en el que se espera un valor de tipo Booleano. Cualquier otro valor numrico se convierte a TRUE. En los casos en que el generador detecte una conversin extraa, loguear un warning. Si no puede continuar debido a que no puede convertir entre tipos escalares loguear un error irrecuperable. El lenguaje no requiere (ni soporta) la definicin explicita de tipos en la declaracin de variables; el tipo de la variable se determina por el contexto en el cual se emplea la variable. Es decir, si se asigna un valor string a una variable var, entonces var se convierte en un string. Si un valor integer es entonces asignado a la misma variable var, sta se convierte en integer. Detrs de cada tipo escalar hay realmente un objeto, por lo que una variable de tipo escalar puede ser tratada como un objeto para invocar mtodos que soporta directamente el lenguaje. Se da soporte nativo para los siguientes mtodos del tipo Integer: compareTo
public int compareTo(Object o) Compara este objeto entero con otro objeto. Retorna: el valor 0 si el entero es igual al argumento; un valor menor a 0 si el entero es numricamente menor que el argumento; y un valor mayor a 0 si el entero es numricamente mayor al argumento.

equals
public boolean equals(Object obj) Compara este objeto con el especificado. El resultado es verdadero si y solo si el argumento es un entero con el mismo valor. Parmetros: obj El objeto con el cual comparar. Retorna: Verdadero si el objeto es el mismo; falso en caso contrario.

floatValue
public float floatValue() Retorna el valor de este entero como un float. Retorna: El valor numrico de este objeto convertido a float.

57

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

toString
public String toString() Retorna un objeto de tipo string con el valor de este entero. Retorna: Una representacin de tipo string con este entero en base 10.

Para el tipo float: compareTo


public int compareTo(Object o) Compara numricamente contra otro objeto de punto flotante. Parmetros: o El objeto contra el cul comparar. Retorna: El valor 0 si el argumento es un nmero de punto flotante con el mismo valor al de este objeto; un valor menor a 0 si el argumento es numricamente mayor a este objeto; y un valor mayor a cero si el argumento es numricamente menor a este objeto.

equals
public boolean equals(Object obj) Compara este objeto contra el objeto especificado. El resultado es verdadero si y slo si el argumento es un objeto de tipo Float y representa el mismo valor numrico que este objeto. Parmetros: obj el objeto con el cul comparar. Retorna: Verdadero si los objetos representan el mismo valor; falso en caso contrario.

isInfinite
public boolean isInfinite() Retorna verdadero si el valor es infinitamente grande en magnitud, falso en caso contrario. Retorna: Verdadero si el valor representado es positivo infinito o negativo infinito; falso en caso contrario.

isNaN
public boolean isNaN() Retorna verdadero si el valor no es un nmero (Not a Number en ingls), falso en caso contrario. Retorna: Verdaderso si el valor representado por este objeto es NaN; falso en caso contrario.

toString
public String toString()

58

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier Retorna una representacin de tipo String de este objeto. Retorna: Una representacin String de este objeto.

El tipo String es uno de los que cuenta con ms soporte nativo, posee los siguientes mtodos: charAt
public char charAt(int index) Retorna un String con el carcter en el ndice especificado. El rango de ndices puede ir desde 0 a length() - 1. El primer carcter se considera en la posicin 0, en segundo en la 1 y as siguiendo. Parmetros: index El ndice del valor que se espera obtener. Retorna: Un String representando el carcter en la posicin index. El primer valor se considera en el ndice 0.

compareTo
public int compareTo(String anotherString) Compara dos Strings alfabticamente. La comparacin se basa en el valor unicode de cada carcter de los Strings. La secuencia de caracteres en este objeto es comparada lexicogrficamente con la secuencia de caracteres del argumento. El resultado es un entero negativo si este String precede lexicogrficamente al del argumento. El resultado es un entero negativo si este String sigue lexicogrficamente al del argumento. El resultado es cero si los dos Strings son iguales; compareTo retorna cero cuando equals es verdadero. Esta es la definicin de orden lexicogrfico. Si dos Strings son diferentes, entonces o bien tienen un carcter diferente en un mismo ndice (valido para ambos), o su longitud es diferente, o ambos. Si tienen caracteres diferentes en una o ms posiciones, entonces sea k el ndice ms pequeo en el que difieren; entonces el string con el carcter ms pequeo en la posicin k precede lexicogrficamente al otro. En este caso compareTo retorna la diferencia entre los valores de los caracteres en la posicin k, es decir: this.charAt(k)-anotherString.charAt(k) Si no hay una posicin en la que los caracteres difieran, entonces el String ms corto precede lexicogrficamente al ms largo. En este caso compareTo retorna la diferencia entre las longitudes de los Strings, esto es: this.length()-anotherString.length() Parmetros: anotherString El String con el cul comparar. Retorna: El valor 0 si el argumento es igual a este objeto; un valor menor a 0 si el String es lexicogrficamente menor al argumento; y un valor mayor a 0 si el String es lexicogrficamente mayor al argumento.

compareToIgnoreCase
public int compareToIgnoreCase(String str) Compara dos Strings lexicogrficamente, ignorando las diferencias entre maysculas y minsculas. Parmetros:

59

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier str El String con el cual comparar. Retorna: Un entero negativo, cero, o un entero positivo. Ya sea que el argumento sea mayor, igual, o menor a este String. Ignorando consideraciones sobre maysculas y minsculas.

concat
public String concat(String str) Concatena el String especificado al final de este String. Si el largo del argumento es 0, entonces este objeto es retornado. En cualquier otro caso, un nuevo objeto de tipo String es creado y retornado, internamente contiene un String que representa la concatenacin de la secuencia de caracteres de este objeto con la secuencia de caracteres del argumento. Parmetros: str El String que ser concatenado al final de este. Retorna: Un String que representa la concatenacin de los caracteres de este objeto con la secuencia de caracteres del argumento.

endsWith
public boolean endsWith(String suffix) Prueba si este String termina con el sufijo especificado. Parmetros: suffix El sufijo. Retorna: Verdadero si la secuencia de caracteres de este objeto es sufijo de la secuencia de caracteres representada por el argumento; falso de otra manera. Notar que el resultado ser verdadero si el argumento es un String vaco o igual a este objeto.

equals
public boolean equals(Object anObject) Compara este String con el objeto especificado. El resultado es verdadero si y slo si el argumento es no nulo y es un objeto de tipo String que representa la misma secuencia de caracteres que este objeto. Parmetros: anObjet El objeto con el cul comparar. Retorna: Verdadero si los String son iguales; falso en caso contrario.

equalsIgnoreCase
public boolean equalsIgnoreCase(String anotherString) Compara este String con otro String, ignorando consideraciones sobre maysculas y minsculas. Sern considerados iguales si tienen la misma longitud y los caracteres correspondientes son iguales. Parmetros: anotherString El string contra el cul comparar. Retorna:

60

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier Verdadero si el argumento es no nulo y los strings son iguales sin tener en cuenta maysculas y minsculas; falso en caso contrario.

indexOf
public int indexOf(int ch) Retorna el ndice dentro de este String de la primer ocurrencia del carcter especificado. Si un carcter con el valor ch especificado est en la secuencia de caracteres representada por ese objeto, entonces el ndice (en unidades unicode) de la primer ocurrencia de ese carcter es retornado. Si no existe ninguna ocurrencia del carcter ch, -1 es retornado. Parmetros: ch Un carater. Retorna: El ndice de la primer ocurrencia del carcter de valor ch dentro de la secuencia de caracteres representada por este Objeto; o -1 si el carcter no aparece dentro de dicha secuencia.

indexOfWithFrom
public int indexOfWithFrom(int ch, int fromIndex) Retorna la primer ocurrencia del carcter especificado dentro de este String, comenzando la bsqueda en el ndice especificado. Si una ocurrencia del carcter ch dentro de la secuencia de caracteres representada por este String ocurre en un ndice no menor a fromIndex, entonces el ndice de la primer ocurrencia es retornado. No hay restricciones sobre el valor fromIndex. Si es negativo, tiene el mismo efecto que si fuese cero: se buscar en el String completo. Si es mayor a la longitud del String, tiene el mismo efecto que si fuese igual a dicha longitud: se retornar -1. Nota: Estamos pensando en eliminar este mtodo y unirlo con indexOf, dejando el parmetro fromIndex como opcional. La posibilidad de utilizar parmetros con valores default fue agregada luego de este mtodo. Parmetros: ch Un carcter. FromIndex El ndice en el cual comenzar la bsqueda. Retorna: El ndice de la primer ocurrencia del carcter en la secuencia de caracteres representada por este objeto que es mayor que o igual a fromIndex, o -1 si el carcter no se encuentra.

lastIndexOf
public int lastIndexOf(int ch) Retorna el ndice dentro de este String de la ltima ocurrencia del carcter especificado. Si no existen ocurrencias del carcter, retorna -1. La bsqueda se hace hacia atrs comenzando por el ltimo carcter. Parmetros: ch Un carcter. Retorna: El ndice de la ltima ocurrencia del carcter dentro de la secuencia de caracteres representada por este objeto, o -1 si no existe tal ocurrencia.

lastIndexOfWithFrom
public int lastIndexOfWidthFrom(int ch, int fromIndex)

61

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier Retorna el ndice dentro de este String de la ltima ocurrencia del carcter especificado, buscando hacia atrs y comenzando en el ndice especificado. Si no existe ocurrencia del carcter especificado antes de la posicin fromIndex, retrona -1. Nota: Estamos pensando en eliminar este mtodo y unirlo con lastIndexOf, dejando el parmetro fromIndex como opcional. La posibilidad de utilizar parmetros con valores default fue agregada luego de este mtodo. Parmetros: ch Un carcter unicode. fromIndex El ndice desde donde comenzar la bsqueda. No hay restriccin en cuanto a los valores de fromIndex. Si es mayor o igual a la longitud del String, tiene el mismo efecto que si fuese igual a la longitud de este String: se busca en la secuencia completa de caracteres. Si es negativo, tiene el mismo efecto que si fuese -1: -1 es retornado. Retorna: El ndice de la ltima ocurrencia del carcter dentro de la secuencia de caracteres representada por este objeto que es menor que o igual a fromIndex, o -1 si el carcter no se encuentra antes de este punto.

length
public int length() Retorna la longitud de este String. La longitud es igual al nmero de caracteres unicode en el objeto. Retorna: La longitud de la secuencia de caracteres representada por este objeto.

matches
public boolean matches(String regex) Indica si esta String concuerda o no con la expresin regular dada. Parmetros: regex La expresin regular. Retorna: Verdadero, si y slo si, este String machea con la expresin regular dada.

regionMatches
public boolean regionMatches(int toffset, String other, int ooffset, int len) Prueba si dos regiones de Strings son iguales. Un substring de este objeto es comparado con un substring del argumento other. El resultado es verdadero si esas porciones representan la misma secuencia de caracteres. El substring de este objeto a ser comparado comienza en el ndice toffset y tiene longitud len. El substring del argumento other a ser comparado comienza en el ndice ooffset y tiene longitud len. El resultado es falso, s y solo si al menos una de las siguientes condiciones es verdadera: toffset es negativo. ooffset es negativo. toffset+len es mayor a la longitud de este objeto. ooffset+len es mayor a la longitud de other. Existe algn entero no negativo k menor que len tal que this.charAt(toffset+k) != other.charAt(ooffset+k) Parmetros: toffset el ndice de comienzo de la regin en este String. other un argumento String. ooffset el ndice de comienzo de la regin del String other.

62

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier len el nmero de caracteres a comparar. Retorna: Verdadero si la regin especificada de este String coincide con la regin del String other; falso en cualquier otro caso.

regionMatchesIgnoreCase
public boolean regionMatchesIgnoreCase(int toffset, String other, int ooffset, int len) Prueba si dos regiones de Strings son iguales ignorando cuestiones de maysculas y minsculas. Un substring de este objeto es comparado con un substring del argumento other. El resultado es verdadero si esas porciones representan la misma secuencia de caracteres. El substring de este objeto a ser comparado comienza en el ndice toffset y tiene longitud len. El substring del argumento other a ser comparado comienza en el ndice ooffset y tiene longitud len. Parmetros: toffset el ndice de comienzo de la regin en este String. other un argumento String. ooffset el ndice de comienzo de la regin del String other. len el nmero de caracteres a comparar. Retorna: Verdadero si la regin especificada de este String coincide con la regin del String other sin consideraciones de maysculas o minsculas; falso en cualquier otro caso.

replace
public String replace(String target, String replacement) Cada substring de este string que machea con target es reemplazado con replacement. El reemplazo procede desde el comienzo hacia el final de la cadena, por ejemplo reemplazar aa con b en aaa resulta en ba y no en ab. Parmetros: target la secuencia de caracteres en la cual reemplazar. replacement la secuencia de caracteres a usar como reemplazo. Retorna: El String resultante de llevar a cabo el reemplazo.

replaceAll
public String replaceAll(String regex, String replacement) Reemplaza cada substring de este String que machea con la expresin regular de reemplazo. Parmetros: regex la expresin regular a buscar. replacement la cadena de reemplazo. Retorna: El String resultante de llevar a cabo el reemplazo.

replaceFirst
public String replaceFirst(String regex, String replacement) Reemplaza la primer ocurrencia dentro de este String que machea con la expresin regular de reemplazo.

63

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier Parmetros: regex la expresin regular a buscar. replacement la cadena de reemplazo. Retorna: El String resultante de llevar a cabo el reemplazo.

startsWith
public boolean startsWith(String prefix) Verdadero si este String comienza con el prefijo especificado. Parmetros: prefix el prefijo. Retorna: Verdadero si cada carcter en la secuencia especificada por el argumento prefix es prefijo de la secuencia de caracteres representada por este String; falso en caso contrario. El valor retornado ser verdadero si el argumento es vaco o igual a este String.

startsWithWithOffset
public boolean startsWith(String prefix, int toffset) Prueba si este String comienza con prefix, comenzando en el ndice especificado. Nota: Estamos pensando en eliminar este mtodo y unirlo con startsWith, dejando el parmetro toffset como opcional. La posibilidad de utilizar parmetros con valores default fue agregada luego de este mtodo. Parmetros: prefix el prefijo. toffset donde comenzar a buscar dentro del String. Retorna: Verdadero si la secuencia de caracteres representada por el argumento es un prefijo del substring de este objeto comenzando en la posicin toffset; falso en caso contrario. El resultado es falso si toffset es negativo o mayor a la longitud de este String; en cualquier otro caso el resultado es el mismo que el de la expresin: this.substring(toffset).startsWith(prefix)

substring
public String substring(int beginIndex, int endIndex = null) Retorna un nuevo String que es un substring de este objeto. El substring comienza en la posicin especificada como beginIndex y: si el parmetro endIndex no est presente, se extiende hasta el final del String si el parmetro est presente, se extiende hasta la posicin endIndex 1 Parmetros: beginIndex el ndice de comienzo. endIndex (opcional) el ndice de finalizacin. Retorna: El substring especfico.

toLowerCase
public String toLowerCase()

64

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier Convierte todos los caracteres de este String a minsculas. Retorna: El String, convertido a minsculas.

toString
public String toString() Este objeto (que actualmente es un String) es retornado. Retorna: El mismo objeto.

toUpperCase
public String toUpperCase() Convierte todos los caracteres de este String a maysculas. Retorna: El String, convertido a maysculas.

trim
public String trim() Retorna una copia de este String, eliminando los espacios en blanco al comienzo y al final. Si este objeto es el String vaco, o el primer y el ltimo carcter en la cadena representada por este String tienen cdigos mayores a '\u0020' (carcter de espacio), entonces una referencia a este objeto es retornada. De otra manera, si no hay caracteres con un cdigo mayor a '\u0020' en el String, entonces un nuevo String representando a la cadena vaca es creado y retornado. En cualquier otro caso, sea k el primer ndice del String en cuya posicin existe un carcter con cdigo mayor a '\u0020', y sea m el ndice del ltimo carcter cuyo cdigo es mayor a '\u0020'. Un nuevo String es creado, representando el substring que comienza en el carcter k y termina en el carcter m, esto es el resultado de this.substring(k, m+1). Retorna: Una copia del String con los espacios removidos al principio y final de la cadena, o este String si no tiene espacios al comienzo o final.

split
public array(String) split(String regex) Parte este String alrededor de las coincidencias con la expresin regular dada. Parmetros: regex la expresin regular. Retorna: El arreglo de Strings resultante de partir este String segn la expresin regular dada en regex.

Sobre el objeto Object, brindamos dos mtodos nativos: equals


public boolean equals(Object obj)

65

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier Indica si un objeto es igual a este objeto. El mtodo equals implementa una relacin de equivalencia sobre referencias no nulas: Es reflexiva: para cualquier referencia no nula x, x.equals(x) debe ser verdadero. Es simtrica: dadas dos referencias x e y no nulas, x.equals(y) retorna verdadero si y slo si y.equals(x) retorna verdadero. Es transitiva: dadas tres referencias no nulas x, y, z, si x.equals(y) es verdadero y y.equals(z) es verdadero, entonces x.equals(z) es verdadero. Es consistente: dadas dos referencias no nulas x e y, mltiples invocaciones de x.equals(y) retornan verdadero o falso consistentemente. Para toda referencia no nula x, x.equals(null) retorna falso. Parmetros: obj la referencia a un objeto con el cul comparar. Retorna: Verdadero si este objeto hace referencia al mismo que el argumento; falso en caso contrario.

dump
public static String dump(Object obj, Integer depth = null) Retorna un String con informacin estructurada de un objeto, incluyendo tipo y valor. Los arreglos y los objetos son explorados recursivamente para mostrar informacin sobre su estructura de manera identada. Parmetros: obj Objeto sobre el cual se desea obtener informacin. depth (opcional) profundidad hasta la cual llegar en la exploracin. El lenguaje utiliza una profundidad de 100 por default, es decir que si no se provee de este parmetro se mostrarn los primeros 100 elementos/propiedades. Retorna: Un String con la informacin estructurada sobre el objeto obj.

Dado que de momento no contamos la posibilidad de debuggear el cdigo escrito en nuestro lenguaje, la funcin dump es de vital importancia para conocer el contenido de las variables en ejecucin y as poder depurar el cdigo. Algunos ejemplos del funcionamiento de la funcin dump son los siguientes: Si ejecutamos:
<%% Log(Object.dump(array("el 1", "k1" => "el 2"))); %%>

Por consola se imprimir la siguiente informacin:


array(2) { [0]=> string(4) "el 1" ["k1"]=> string(4) "el 2" }

El mtodo tambin opera sobre arreglos anidados, si ejecutamos: 66

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
<%% Log(Object.dump(array( 1, array(2), 3 ))); %%>

El resultado por consola ser:


array(3) { [0]=> int(1) [1]=> array(1) { [0]=> [0]=> int(2) } [2]=> int(3) }

Y con objetos ms complejos tambin es de utilidad. Si ejecutamos:


<%% class MyClass { public _att1 = "att1"; public function MyClass() {} } class MyClass2 extends MyClass { public _att2 = "att2"; public _att3 = new MyClass(); } public function MyClass2() : super() {}

Log(Object.dump(new MyClass2())); %%>

E resultado ser:
Object::MyClass2(2) { [MyClass2::public:_att2]=> string(4) "att2" [MyClass2::public:_att3]=> Object::MyClass(1) { [MyClass::public:_att1]=> string(4) "att1" } [MyClass::public:_att1]=> string(4) "att1" }

67

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Variables
Las variables en nuestro lenguaje son creadas ante el primer uso. La mayora de las variables tienen un mbito simple, pero su alcance es propagado por archivos incluidos. Por ejemplo:
<%% a = 1; include("b.inc"); %%>

En este caso se crear una variable de nombre a y esta variable ser accesible tanto en el archivo que est definido como dentro del cdigo en el archivo b.inc. Para funciones ralas, es decir funciones definidas dentro de un archivo, pero que no pertenecen a ningn objeto las reglas son las siguientes:
<%% function test(...) { a } %%>

Cuando el parser encuentra la variable a, primero busca si existe en el mbito local de la funcin (dentro del cuerpo de la misma) si no existe en el mbito local, se buscar como parmetro si tampoco existe como parmetro, se buscar en el mbito global si tampoco existe en el mbito global, entonces ser creada como una variable local al cuerpo de la funcin

Cuando introducimos objetos, el mbito de las variables es similar, solo con algunas diferencias.
<%% class MyClass { public function test(...) { a } } %%>

En este caso, cuando el parser encuentra la variable a, primero busca si existe en el mbito local del mtodo si no existe en dicho contexto, la buscar como parmetro de la funcin si tampoco existe como parmetro, la buscar como atributo interno de la clase 68

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

si tampoco existe, recin entonces es creada como una variable local al cuerpo del mtodo

Si bien an no hemos hablado de expresiones lambda ya que estas son introducidas en la seccin sobre extensiones al lenguaje, cabe destacar que tambin tienen un mbito algo diferente para buscar las variables a las que se accede en el cuerpo. Inicialmente funcionan igual que una funcin, pero si buscan hacia arriba entonces depende del contexto en el que son ejecutadas. Una vez introducido el concepto de expresiones lambda, esto quedar un poco ms claro mediante algunos ejemplos.

Arreglos
Ya hemos definido el concepto de un arreglo para nuestro lenguaje, lo que no hemos aclarado an es la forma de declararlos, inicializarlos y acceder a sus valores. Un valor array puede ser creado por la construccin de lenguaje array(). sta toma un cierto nmero de parejas clave => valor separadas con coma.
array( key => value , ... ) // key puede ser un integer o string // value puede ser cualquier valor

Si no especifica una key para un valor dado, entonces es usado el mximo de los ndices Integer y la nueva key ser ese valor mximo ms 1. Si se especifica una key que ya tiene un valor asignado, ese valor ser sobrescrito.
<%% // Este array es lo mismo que... array(5 => 43, 32, 56, "b" => 12); // ...este array array(5 => 43, 6 => 32, 7 => 56, "b" => 12); %%>

Es posible modificar un array existente al definir valores explcitamente en l. Esto es posible al asignar valores al array al mismo tiempo que se especifica la key entre corchetes. Tambin es posible omitir la key, lo que resulta en una pareja de corchetes vacos ([]).
arr[key] = value; arr[] = value; // key puede ser un integer o un string // value puede ser cualquier valor

Adems de la sintaxis tpica sobre arreglos, se brinda soporte nativo para los siguientes mtodos: clear
void clear()

69

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier Elimina todos los elementos del arreglo.

containsKey
boolean containsKey(Object key) Retorna verdadero si el arreglo contiene la clave especfica, el tipo del argumento key debera ser Integer o String. Parmetros: key la clave a buscar en el arreglo Retorna: Verdadero si el arreglo contiene la clave especificada; falso en caso contrario.

containsValue
boolean containsValue(Object value) Retorna verdadero si el arreglo contiene el valor especificado. Parmetros: value valor a buscar en el arreglo. Retorna: Verdadero si el arreglo contiene el valor especificado; falso en caso contrario.

isEmpty
boolean isEmpty() Retorna verdadero si este arreglo est vaco. Retorna: Verdadero si el arreglo est vaco; falso en caso contrario.

remove
Object remove(Object key) Quita del arreglo el objeto asociado a la clave key si es que est presente. Retorna el valor al que estaba asociada la clave, o NULL si es que la clave no exista en el arreglo. Un retorno nulo tambin puede indicar que la clave estaba asociada a ese valor. Luego de esta operacin no habr en el arreglo elemento asociado a la clave. Parmetros: key clave del elemento a eliminar del arreglo. Retorna: Valor previo asociado a la clave, o NULL si el valor no estaba presente.

size
int size() Retorna el nmero de elementos en el arreglo, si el arreglo tiene ms elementos que el mximo entero soportado, entonces retorna Integer.MAX_VALUE. Retorna: El nmero de elementos del arreglo.

70

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Por supuesto con estas operaciones no es suficiente, por lo que existen varias extensiones sobre arreglos que explicaremos en seccione subsecuentes de esta documentacin.

Operadores
Un operador es una construccin del lenguaje que toma uno o ms valores y produce otro valor, por lo que la construccin en s misma se convierte en una expresin. En nuestro lenguaje hemos implementado la mayora de los operadores tpicos de todos los lenguajes de programacin que heredan del lenguaje C. Precedencia de operadores La siguiente tabla lista en orden la precedencia de los operadores, con los operadores de mayor precedencia en la parte superior. Los operadores en la misma lnea tienen la misma precedencia, en cuyo caso su asociatividad decide cul es el orden de evaluacin. Asociatividad Izquierda no asociativo no asociativo derecha Izquierda Izquierda no asociativo no asociativo Izquierda Izquierda Izquierda Izquierda Izquierda Izquierda derecha Operadores [ ++ -Instanceof ! */% +-$ < <= > >= == != !== & ^ | && || ?: = += -= *= /= $= %= &= |= ^=

Operadores aritmticos Ejemplo -a a+b Nombre Negacin Adicin Resultado Opuesto de a. Suma de a y b. 71

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

a-b a*b a/b a%b Operadores bit a bit Ejemplo a&b a|b a^b Nombre And (y) Or (o inclusivo)

Sustraccin Multiplicacin Divisin Mdulo

Diferencia de a y b. Producto de a y b. Cociente de a y b. Resto de a dividido por b.

Resultado Los bits que estn activos en ambos a y b son activados. Los bits que estn activos ya sea en a o en b son activados. Los bits que estn activos en a o en b, pero no en ambos, son activados.

Xor (o exclusivo)

Operadores de comparacin Ejemplo a == b a != b a<b a>b a <= b a >= b Nombre Igual Diferente Menor que Mayor que Menor o igual que Mayor o igual que Resultado TRUE si a es igual a b despus de la manipulacin de tipos. TRUE si a no es igual a b despus de la manipulacin de tipos. TRUE si a es estrictamente menor que b. TRUE si a es estrictamente mayor que b. TRUE si a es menor o igual que b. TRUE si a es mayor o igual que b.

Operadores de incremento/decremento Ejemplo Nombre ++a Pre-incremento Efecto Incrementa a en uno, y luego retorna a.

72

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

a++ --a a--

Post-incremento Pre-decremento

Retorna a, y luego incrementa a en uno. Decrementa a en uno, luego retorna a.

Post-decremento Retorna a, luego decrementa a.

Operadores lgicos Ejemplo Nombre !a a && b a || b Not (no) And (y) Or (o inclusivo) Resultado TRUE si a no es TRUE. TRUE si tanto a como b son TRUE. TRUE si cualquiera de a o b es TRUE.

Operadores para strings Ejemplo Nombre a$b a $= b Concatenacin Concatenacin asignada Resultado a concatenado a b. a se concatena con b y luego se asigna a a.

Estructuras de control
Todo script en nuestro lenguaje est compuesto por un conjunto de sentencias, a continuacin explicaremos las sentencias ms comunes. En su mayora son heredadas del lenguaje C y se comportan de manera similar. Algunas, tienen un funcionamiento similar a sentencias del lenguaje PHP, como son los Include, Require, Include.once y Require.once. If El constructor if permite la ejecucin condicional de porciones de cdigo.
if (expr) sentencia

Si la expresin evala a TRUE, se ejecuta la sentencia, caso contrario se ignora. Ejemplo:


<%% if(true) Writer.echo("GOOD");

73

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

if(true) Writer.echo("GOOD"); else Writer.echo("BAD"); if(false){ Writer.echo("BAD"); } else{ Writer.echo("GOOD"); } if(1 == 1) if(false) Writer.echo("BAD"); else Writer.echo("GOOD"); else Writer.echo("BAD"); %%>

La sentencia if, tambin acepta la palabra else.


if (expr) sentencia else sentencia2

En ese caso si la expresin evala a FALSE, se ejecuta la sentencia2. While La sentencia while es la forma ms simple de lograr bucles, se comporta igual que en el lenguaje C. La sintaxis bsica tiene la siguiente forma.
while (expr) sentencia

La sentencia se ejecuta tantas veces como la expresin evale a TRUE. El valor de la expresin es verificado cada vez al inicio del bucle, por lo que incluso si este valor cambia durante la ejecucin de las sentencias anidadas, la ejecucin no se detendr hasta el final de la iteracin. A veces, si la expresin while se evala como FALSE desde el principio, las sentencias anidadas no se ejecutarn ni siquiera una vez. Ejemplo:
<%% i = 0; while(i < 11){ Writer.echo(i); i = i + 1; } %%>

74

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

do-while Es similar a la sentencia while, la diferencia es que en este caso est garantizado que la sentencia dentro del bucle se ejecuta al menos una vez, ya que la expresin de condicin es evaluada al final de cada iteracin. Es decir si utilizamos while, como la expresin se evala al comienzo, puede suceder que nunca se ejecute el cuerpo, mientras que si utilizamos do-while, como la expresin se evala al final, siempre se ejecuta al cuerpo al menos una vez. Su forma es la siguiente.
do sentencia while (exp)

Ejemplo:
<%% i = 0; do{ Writer.echo(i); i = i + 1; }while(i < 11); %%>

for La sentencia for es la forma ms compleja de realizar un bucle, pero tambin la ms flexible. Se comporta igual que la sentencia for para el lenguaje C. La sintaxis es la siguiente.
for (expr1; expr2; expr3) sentencia

El comportamiento es el siguiente: La primera expresin es siempre evaluada al comienzo. En el comienzo de cada iteracin se evala la segunda expresin, si evala a TRUE, se ejecuta el cuerpo de la sentencia. Si evala a FALSE ya no se contina con el bloque. Al final de cada iteracin, la ltima expresin es evaluada.

Cada una de las expresiones puede estar vaca o contener mltiples expresiones separadas por comas. En la expr2, todas las expresiones separadas por una coma son evaluadas pero el resultado se toma de la ltima parte. Que la expr2 est vaca significa que el bucle deber ser corrido indefinidamente. 75

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Ejemplo:
<%% for(i = 0, j = 10; i < 10; i = i + 1, j = j - 1){ Writer.echo(i); Writer.echo(j); } %%>

foreach El constructor foreach es similar al del lenguaje PHP y respeta su comportamiento. Funciona slo sobre arreglos. Su sintaxis es la siguiente.
foreach (valor in expresin_array) sentencias foreach (clave => valor in expresin_array) sentencias

La primera forma recorre el array dado por expresin_array. En cada iteracin, el valor del elemento actual se asigna a valor y el puntero interno del array avanza una posicin (as en la prxima iteracin se estar observando el siguiente elemento). La segunda forma adems asigna la clave del elemento actual a la variable clave en cada iteracin. Ejemplo:
<%% arr = array(1 => "c", "a" => "a", "b", 0 => "d"); foreach(key => value in arr) { Writer.echo(key); Writer.echo(value); } foreach(value in array(3, 2, 1)) { Writer.echo(value); } %%>

break y continue Break termina la ejecucin de la estructura actual for, foreach, while, do-while o switch. Continue se utiliza dentro de las estructuras de bucle o switch para saltarse el resto de la actual iteracin del bucle y continuar la ejecucin en la evaluacin de la condicin (al comienzo de la siguiente iteracin). Ejemplo:
<%%

76

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

// WHILE BREAK i = 0; while(true){ if(i == 11) break; Writer.echo(i); i++; } // WHILE CONTINUE i = -1; while(i<11){ i++; if(i == 5) continue; Writer.echo(i); } // DO-WHILE BREAK i = 0; do{ if(i == 11) break; Writer.echo(i); i++; }while(true); // DO-WHILE CONTINUE i = -1; do{ i++; if(i == 5) continue; Writer.echo(i); }while(i<11); // FOR BREAK for( i = 0; ; i++){ if(i == 11) break; Writer.echo(i); } // FOR CONTINUE for( i = 0; i < 11 ; i++){ if(i == 5) continue; Writer.echo(i); } // FOREACH BREAK NO KEY arr = array(0,1,2,3,4,5,6,7,8,9,10,11); foreach(value in arr) { if(value == 5) break; Writer.echo(value); } // FOREACH CONTINUE NO KEY foreach(value in arr) { if(value == 5) continue; Writer.echo(value); } // FOREACH BREAK WITH KEY arr = array(0,1,2,3,4,5,6,7,8,9,10,11); foreach(key => value in arr) { if(value == 5) break; Writer.echo(value); } %%>

77

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

switch Switch se utiliza para seleccionar uno (o ms) de entre varios caminos de ejecucin. Se puede lograr el mismo efecto anidando sentencias if.
<%% function monthToString( month ){ switch (month) { case 1: Writer.echo("January"); break; case 2: Writer.echo("February"); break; case 3: Writer.echo("March"); break; case 4: Writer.echo("April"); break; case 5: Writer.echo("May"); break; case 6: Writer.echo("June"); break; case 7: Writer.echo("July"); break; case 8: Writer.echo("August"); break; case 9: Writer.echo("September"); break; case 10: Writer.echo("October"); break; case 11: Writer.echo("November"); break; case 12: Writer.echo("December"); break; default: Writer.echo("Invalid month.");break; } } function numberDays( month, year){ switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: numDays = 31; break; case 4: case 6: case 9: case 11: numDays = 30; break; case 2: if ( ((year % 4 == 0) && !(year % 100 == 0)) || (year % 400 == 0) ) numDays = 29; else numDays = 28; break; default: Writer.echo("Invalid month."); break; } Writer.echo(numDays); } monthToString(1); monthToString(12); monthToString(15); numberDays( numberDays( numberDays( numberDays( numberDays( numberDays( %%> 2, 2000); 2, 2001); 1, 2008); 7, 2008); 12, 2008); 11, 2008);

78

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

return La sentencia return debe ser utilizada dentro del mbito de una funcin o mtodo de un objeto. Caso contrario se producir un error y se lo informar al usuario. Inmediatamente termina la ejecucin de la funcin o mtodo y retorna su argumento. En el caso de funciones o mtodos que no contengan, o que contengan pero no lleguen a ejecutar la sentencia return, se devolver el valor NULL. Require, Include, Require.once, Include.once Todas estas sentencias toman un argumento (el nombre de un archivo) y lo incluyen. Las diferencias son las siguientes. Entre Require e Include: Si Include no encuentra el archivo simplemente mostrar un warning, mientras que si Require no encuentra un archivo habr un error fatal. El comportamiento sin agregar .once es que cada vez que se ejecuta la sentencia se incluir el archivo especificado, mientras que al agregar .once se incluir nicamente la primera vez que se ejecuta la sentencia para el mismo archivo.

Orientacin a objetos
Para dar soporte a la orientacin a objetos se han introducido una serie de elementos. Se soporta la mayor parte de las caractersticas de los lenguajes orientados a objetos: Es posible definir clases, con atributos privados, protegidos o pblicos. Los mtodos tambin pueden ser privados, protegidos o pblicos. A su vez, tanto atributos como mtodos pueden ser estticos. Se permite herencia simple. Se permite sobrescribir atributos y mtodos definidos en una clase padre. No existe la idea de atributos ni mtodos abstractos. Aunque se puede simular. Tampoco existe la nocin de interfaz. Aunque se puede simular.

Definicin de clases La sintaxis bsica para definir una clase es la siguiente.


<%% class MyClass { public att1; protected att2; private att3; public static att4; public function fcn1 { }

79

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
protected function fcn2 { } private function fcn3 { } public static function fcn4 { } public function MyClass() { } } %%>

Tanto los atributos como los mtodos son precedidos del modificador. En cuanto al constructor, si existe una funcin con el mismo nombre que la clase, es considerada el constructor de la misma. Si no existe dicha funcin, no se podr crear una instancia de esa clase directamente. No est permitida la sobrecarga directa de mtodos ni constructores, es decir que una clase no puede tener dos mtodos con el mismo nombre. Lo que si es posible es utilizar parmetros con valores por defecto con la siguiente sintaxis.
<%% function myFunc(att1, , att2 = Default2, att3 = Default3) { } %%>

Los primeros parmetros son requeridos. Los parmetros con valores defecto deben ser los ltimos que estn en la declaracin de la funcin o mtodo. Es decir, una vez que se encuentra un parmetro con un valor por defecto comenzando en la lista desde la izquierda hacia la derecha, ya no puede haber parmetros que no tengan valores por defecto. Al invocar una funcin, est permitido omitir uno o varios de los parmetros con valores por defecto, en cuyo caso tomarn el valor que tienen por defecto en la declaracin. Esta es una caracterstica que tambin posee el lenguaje PHP y el comportamiento es prcticamente el mismo. Para crear instancias de objetos se utiliza la palabra reservada new. Por ejemplo:
<%% class MyClass{ public pubField = "pub"; public constInit; private privField = "priv"; public function MyClass(){ constInit = "initialized"; }

obj1 = new MyClass(); Writer.echo(obj1.pubField); %%>

80

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Los campos y mtodo que se pueden utilizar sobre la instancia del objeto creado, son nicamente los pblicos. Para acceder a un campo o mtodo se utiliza el modificador ., como se puede ver en el ejemplo. Con el mismo modificador tambin es posible acceder a campos y mtodos estticos, anteponiendo el nombre de la clase en donde estn definidos. Herencia Para lograr herencia se utiliza la palabra reservada extends. La sintaxis bsica es la siguiente:
<%% class MyClass extends AnotherClass { } %%>

En este caso la clase MyClass hereda todos los atributos y mtodos de la clase AnotherClass, incluyendo los estticos. Dentro de la clase MyClass podremos acceder a todos los elementos que estn definidos en AnotherClass como pblicos y protegidos. Los elementos definidos como privados son solo accesibles dentro del mbito de la misma clase. Tambin dentro de la clase MyClass podremos sobrescribir cualquier atributo o mtodo definido en la clase AnotherClass como pblico o protegido. Para clarificar el uso de la herencia veamos un ejemplo:
<%% class ParentClass{ public parentField = "parentField"; public function setParentField(newValue){ parentField = newValue; } public function getParentField(){ return parentField; } public function ParentClass(){ } } class SunClass extends ParentClass{ public sunField = "sunField"; public function setSunField(newValue){ sunField = newValue; } public function getSunField(){ return sunField; }

81

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

public function SunClass(){ } } class SunOfSunClass extends SunClass{ public sunField = "overrited"; public function SunOfSunClass(){ } } obj = new SunClass(); anotherObj = new SunOfSunClass(); Writer.echo(obj.getParentField()); Writer.echo(obj.getSunField()); obj.setParentField("newParentField"); obj.setSunField("newSunField"); Writer.echo(obj.getParentField()); Writer.echo(obj.getSunField()); Writer.echo(anotherObj.getParentField()); Writer.echo(anotherObj.getSunField()); anotherObj.setParentField("newParentField"); anotherObj.setSunField("newSunField"); Writer.echo(anotherObj.getParentField()); Writer.echo(anotherObj.getSunField()); %%>

Palabras reservadas super y this La palabra reservada super se utiliza para acceder a atributos y mtodos definidos en la clase padre. De este modo, se pueden acceder a atributos o mtodos definidos en la clase padre, an cuando la clase hija los redefina.
<%% class Parent { public aField = "parentField"; public function aMethod() { return "parentMethod"; } public function Parent(){} } class Sun extends Parent { public aField = "sunField"; public function aMethod() { return "sunField"; } public function getSuperField() { return super.aField; } public function getSuperMethod() {

82

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
return super.aMethod(); } public function Sun(){} } sun = new Sun(); Writer.echo(sun.getSuperField()); Writer.echo(sun.getSuperMethod()); %%>

En el ejemplo, las ltimas sentencias estn accediendo al atributo y mtodo definidos en la clase padre. Otro uso de la palabra reservada super es en los constructores, la sintaxis es la siguiente:
<%% class MyClass extends AnotherClass { public function MyClass() : super(...) { } } %%>

Si utilizamos la palabra reservada super en un constructor, cuando se cree una nueva instancia del objeto, lo primero que suceder es que se ejecutar el constructor del padre. La palabra super utilizada en este contexto equivale al llamado a una funcin y puede ser parametrizada, al pasar parmetros al constructor padre, se puede acceder a los parmetros del constructor propio. En cuanto a la palabra reservada this, sirve para hacer referencia a la propia instancia y de este modo desambigar el uso de atributos o funciones. Si dentro de un mtodo tenemos un parmetro con nombre x, y x tambin est definido como atributo del objeto. x por s solo har referencia al parmetro, mientras que this.x har referencia al atributo. Podemos ver un ejemplo de este tipo de usos:
<%% class MyClass{ private aField = "aField"; public function doWork(){ Writer.echo(this.aField); } public function MyClass(){ } } obj = new MyClass(); obj.doWork(); %%>

83

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Extensiones
Un aspecto muy interesante que quisimos lograr sobre los arreglos es el uso de un pseudo lenguaje, algo similar a lo que logr la empresa microsoft sobre C# con la tecnologa LinQ. De este modo, podremos lograr consultas sobre los elementos de un arreglo de una manera relativamente simple y fcil de leer, adems de declarativa. Teniendo en cuenta que uno de los objetivos es procesar archivos xml para lograr un resultado y que las libreras que procesan xml retornan en su mayora elementos en arreglos, esto sera sumamente til. Para comprender la potencia de contar con estas caractersticas, veamos un ejemplo:
File.create(__Config.getInputPath()).listFiles(). select(f => this.getFileInfo(f)). where( fInfo => !fInfo.isDirectory && fInfo.isXml && (this._modulesInclude == null || this._modulesInclude.containsValue(fInfo.fileName)) && (this._modulesExclude == null || !this._modulesExclude.containsValue(fInfo.fileName)) ).orderBy(fInfo => fInfo.originalFile, this._fileComparator). forEach(fInfo => { inputFound = true; docBuilder = wrap_javax_xml_parsers_DocumentBuilderFactory.newInstance().newDocumentBuilder(); doc = docBuilder.parseUri(fInfo.absolutePath); doc.normalize(); tpls.forEach(tpl => { Log(String.format("Running template %s (%s)", array(tpl.getId(), fInfo.fileName))); tpl.setModule(fInfo.fileName); tpl.run(doc); Log(""); }); });

La porcin de cdigo del ejemplo son lneas extradas de uno de los templates escritos en nuestro lenguaje. Si bien se estn utilizando caractersticas del lenguaje que an no hemos explicado, se puede apreciar como de una manera simple, declarativa y en pocas lneas se pueden recorrer todos los archivos de entrada para ser procesados. Con el fin de lograr una implementacin de la tecnologa LinQ para el lenguaje C#, la empresa microsoft tuvo que introducir una serie de caractersticas al lenguaje, lo hizo a partir de la versin 4. Nuestra implementacin tiene otro enfoque y es ms limitada por el momento. La primer limitacin es que funciona nicamente sobre arreglos, adems no hemos implementado todos los mtodos que deseamos, pero quedar pendiente para futuras versiones del lenguaje agregar nuevos mtodos (se puede hacer de una manera relativamente sencilla). Adems de procesar arreglos de una manera declarativa, se puede hacer eficientemente. Para lograr esto nosotros tambin tuvimos que introducir una serie de caractersticas, las cuales intentaremos explicar a continuacin. Extensin e inicializacin de objetos en la construccin Una de las caractersticas que hemos introducido al lenguaje es la posibilidad de extender e inicializar un objeto cuando se construye, para lo cual luego de la sentencia new sigue 84

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

una parte opcional para tal fin. La sintaxis es la siguiente:


new Object(...) { extensiones { inicializacin ... } }

Esto puede aplicarse a cualquier objeto de cualquier tipo. La seccin de extensin puede estar vaca, en el caso de que no est vaca puede contener cualquier definicin vlida dentro de una definicin de clase, es decir que se pueden definir nuevos atributos y mtodos que estarn disponibles nicamente para el objeto recin creado. Por otra parte, la seccin de inicializacin es opcional, las sentencias en esta seccin se ejecutan en el mbito del objeto recin creado. Esta seccin es particularmente til para inicializar objetos en la creacin, lo cual combinado con el uso de expresiones lambda permitir la definicin de una especie de lenguaje sobre arreglos. Veamos un ejemplo para comprender la potencialidad de esta nueva caracterstica, si ejecutamos el parser sobre un archivo con el siguiente contenido.
<%% class Parent { public parentField; private parentPrivateField; public function parentFunction() { return parentPrivateField; } } public function Parent() {}

sunFieldValue = "sunField"; obj = new Parent() { private sunField; public className; public localFuncAssigned; private function setParentPrivateField(value) { this.parentPrivateField = value; } public function getSunField() { return sunField; } { this.sunField = sunFieldValue; localVar = "parentPrivateField"; setParentPrivateField(localVar); className = typeof(this); localFuncAssigned = localFunc();

} }; function localFunc() { return "localFuncAssigned"; }

85

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Log(obj.getSunField()); Log(obj.parentFunction()); Log(obj.className); Log(localVar); Log(obj.localFuncAssigned); %%>

El resultado ser el siguiente.


sunField parentPrivateField Parent parentPrivateField localFuncAssigned

Expresiones lambda Otra extensin que fue necesario introducir en el lenguaje para lograr nuestro objetivo es la de expresiones lambda. En nuestro lenguaje una expresin lambda es un nuevo tipo, es el tipo __LamdaExpression. Este tipo no es ni un tipo ni una clase en s mismo, si no que debe ser creado mediante una sintaxis especial (en realidad existen dos formas de crear una expresin lambda):
(<parametros>) => <expression>

Esta es la primer sintaxis con la cual se puede crear una expresin lambda, la seccin de parmetros es igual que para cualquier otra funcin, por lo que tambin se aceptan parmetros opcionales. En el caso de que haya un nico parmetro, los parntesis son opcionales. Se pueden utilizar nicamente los parntesis para indicar una expresin sin parmetros. Luego del smbolo => debe ir una expresin, y el resultado de evaluar la expresin lambda es el resultado de evaluar la expresin que se encuentra luego del smbolo => con los parmetros actuales.
(<parametros>) => { <cuerpo> }

Con la segunda forma de creacin, luego del smbolo => debe ir el cuerpo, al igual que si fuese el cuerpo de una funcin. En este caso pueden existir varias sentencias en lugar de una nica expresin. El resultado de evaluar la expresin lambda ser: El resultado de la sentencia return dentro del cuerpo si es que esta sentencia existe. NULL en caso contrario.

Con la sintaxis de creacin no se evala la expresin lambda, si no que se crea un objeto 86

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

de tipo __LambdaExpression. Este es un objeto especial que posee una nica funcin eval. Esta funcin contendr los parmetros y el cuerpo de la expresin lambda, y ejecutar esa expresin al ser invocada. Al ser objetos, las expresiones lambda pueden pasarse como parmetros a funciones e incluso, a otras expresiones lambda. Veamos algunos ejemplos clarificadores.
<%% expr1 = (expr, par) => expr.eval(par); expr2 = par => par; Writer.echo(expr1.eval(expr2, "Yeah1!")); Writer.echo( ((expr, par) => expr.eval(par)).eval( par => par, "Yeah2!" ) ); %%>

<%% factorial = (n) => { if( n == 0 ) return 1; return n * this.eval( n - 1 ); }; for( i = 0; i < 6; i++) Writer.echo(factorial.eval(i)); %%>

Combinando estas caractersticas, se logra extender el lenguaje de manera que pueden escribirse funciones que tomen como parmetros expresiones lambda y aplicando estas expresiones sobre los elementos de arreglos logramos ciclar sobre arreglos y procesarlos de manera declarativa. El tipo ArrayQuery No es suficiente con procesar arreglos de manera declarativa, tambin tenemos que lograr que se haga de una manera eficiente. Supongamos que tenemos el siguiente arreglo.
arr = array(1 => 1, 2 => 2, 3 => 3, 4 => 4);

Y queremos filtrarlo de manera declarativa por valores menores a 3 y mayores a 1. Declarativamente podramos escribir algo como lo que sigue.
newArr = arr. where(v => v < 3). where(v => v > 1);

87

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Supongamos la funcin de extensin where trabaja directamente sobre arreglos. Es decir, al aplicarse sobre un arreglo, recorre todos los elementos del mismo y retorna un nuevo arreglo con los elementos filtrados. Ahora pensemos en la implementacin de las sentencias del ejemplo. Sucedera algo como: 1. Se ejecuta el primer where. 2. La funcin where crea un nuevo arreglo vaco y luego cicla sobre los elementos del arreglo original. Para cada elemento, evala la expresin lambda v => v < 3, si el resultado es verdadero agrega el elemento al arreglo que retornar como resultado, en caso de que la evaluacin de la expresin lambda de falso ese elemento no se agrega. 3. Luego la funcin where retorna el nuevo arreglo. 4. Se ejecuta el segundo where sobre el resultado del primero. 5. La funcin where crea un nuevo arreglo vaco y luego cicla sobre los elementos del arreglo original. Para cada elemento, evala la expresin lambda v => v > 1, si el resultado es verdadero agrega el elemento al arreglo que retornar como resultado, en caso de que la evaluacin de la expresin lambda de falso ese elemento no se agrega. 6. El resultado del segundo where es retornado y asignado a la variable newArr. Con este modelo estaramos ciclando sobre el arreglo 2 veces para aplicar un filtro, uno por cada funcin where. Esto, con llamados sucesivos de funciones sobre arreglos sera sumamente ineficiente. Por este motivo se introduce el concepto de funciones sobre arreglos de primer orden y funciones sobre arreglos de segundo orden. Las funciones de primer orden retornan variables de tipo __ArrayQuery, mientras que las de segundo rden pueden retornar cualquier tipo de resultado. Una variable de tipo __ArrayQuery no es un arreglo en s misma. Podra verse como un conjunto de datos necesarios para aplicar funciones sobre arreglos. Puede pensarse como el siguiente conjunto de datos: Un arreglo sobre el cul operar. Una lista de funciones a aplicar sobre los elementos del arreglo.

Las funciones de primer orden son funciones que pueden aplicarse directamente sobre arreglos, o sobre variables de tipo __ArrayQuery. Su comportamiento es el siguiente: 1. Si son aplicadas sobre una variable de tipo Array, crean una de tipo __ArrayQuery, y suman a la informacin en el __ArrayQuery cul es el arreglo sobre el cul operar. De aqu en ms trabajan sobre la variable de tipo __ArrayQuery. Si, en cambio son aplicadas sobre una variable de tipo __ArrayQuery, trabajan directamente sobre la misma. 2. Agregan una funcin a la lista de funciones del __ArrayQuery. 3. Retornan la variable de tipo __ArrayQuery. 88

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Las funciones de segundo orden, tambin son funciones que pueden aplicarse directamente sobre arreglos, o sobre variables de tipo __ArrayQuery. El comportamiento es similar a las de primer orden: 4. Si son aplicadas sobre una variable de tipo Array, crean una de tipo __ArrayQuery, y suman a la informacin en el __ArrayQuery cul es el arreglo sobre el cul operar. De aqu en ms trabajan sobre la variable de tipo __ArrayQuery. Si, en cambio son aplicadas sobre una variable de tipo __ArrayQuery, trabajan directamente sobre la misma. 5. Agregan una funcin a la lista de funciones del __ArrayQuery. 6. Disparan la evaluacin del __ArrayQuery. 7. Luego de la evaluacin completa del __ArrayQuery, deciden cul ser el resultado final. Para formalizar el funcionamiento del __ArrayQuery, digamos que puede verse como la siguiente estructura de datos:
__ArrayQuery { // Arreglo con cualquier tipo de elementos array(mix) arreglo; // Arreglo con una lista de n funciones a aplicar sobre los elementos del arreglo anterior array(fcn) funciones; }

Donde: n>0 las funciones desde 1.. n-1 son de primer orden la funcin nmero n es de segundo orden

y un pseudo algoritmo para evaluar un __ArrayQuery sera como sigue.


Para cada elemento elem del arreglo { PasarSiguiente = verdadero; Para cada funcin fcn del arreglo de funciones { Si PasarSiguiente { evaluar fcn con elem; PasarSiguiente = Preguntar a fcn si se debe evaluar la siguiente funcin sobre elem; } } } Resultado = Preguntar a la funcin nmero n el resultado; Retornar Resultado;

Cada vez que se encuentra una funcin de segundo orden, se dispara automticamente la evaluacin del __ArrayQuery. De este modo, podemos lograr algo mucho ms eficiente, ya que podemos acumular tantas funciones de primer orden como sea necesario y luego 89

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

evaluarlas todas ciclando nicamente una vez sobre el arreglo. A grandes rasgos, este es el modo en el que se procesan las funciones de extensin sobre arreglos. Para ms informacin al respecto, referirse al proyecto CodeGenerator. Ahora, veamos como se implementara el ejemplo al inicio de esta seccin aplicando estos nuevos conceptos:
newArr = arr. where(v => v < 3). where(v => v > 1). toArray();

En este caso: where es una funcin de primer orden. toArray es una funcin de segundo orden. Cuando se encuentra la funcin toArray se dispara la ejecucin del __ArrayQuery, que contiene informacin sobre las tres funciones aplicadas. Al aplicarse la evaluacin, se ciclar nicamente una vez sobre el arreglo original. El primer where filtrar los valores >= a 3, por lo que al segundo llegarn nicamente los valores < a 3. El segundo where filtrar los valores <= a 1, por lo que a la funcin toArray llegarn nicamente los valores x tal que 1 < x < 3. toArray recolectar todos los valores que le lleguen y generar un nuevo arreglo. El resultado asignado a la variable newArr ser un arreglo con el valor 2.

Funciones de extensin sobre arreglos Dada la explicacin de como llegamos a implementar estas funciones de extensin, ahora haremos mencin de cules son las que implementamos. Muchas de las funciones que deseamos implementar quedaron fuera de esta entrega, pero tenemos intenciones de agregar muchas ms en el futuro. aggregate
mix aggregate(mix seed, __LambdaExpression func = NULL, __LambdaExpression resultSelector = NULL) Aplica una funcin de acumulacin sobre una secuencia. El valor de semilla es usado como valor inicial del acumulador y la funcin especificada es usada para seleccionar el valor del resultado. En el caso de que se invoque nicamente con un parmetro, este parmetro es utilizado como funcin de acumulacin y no como semilla. Parmetros: seed semilla a ser utilizada como valor inicial func (opcional) funcin de acumulacin resultSelector (opcional) funcin de seleccin de resultado

90

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Retorna: Resultado de la acumulacin.

all
Boolean all(__LambdaExpression predicate) Determina si todos los elementos de un arreglo cumplen una condicin. El parmetro predicate debe ser una expresin lambda con uno o dos parmetros. En el caso de que tenga 2 parmetros se le pasar el valor del arreglo, si tiene dos, se le pasar clave y valor. Debe retornar un valor booleano. Ante una evaluacin falsa del predicado corta el ciclo retornando falso. Parmetros: predicate predicado a aplicar sobre los elementos del arreglo Retorna: Verdadero si todos los elementos del arreglo cumplen con el predicado; falso en caso contrario.

any
Boolean any(__LambdaExpression predicate) Determina si algn elemento de un arreglo cumple una condicin. El parmetro predicate debe ser una expresin lambda con uno o dos parmetros. En el caso de que tenga 2 parmetros se le pasar el valor del arreglo, si tiene dos, se le pasar clave y valor. Debe retornar un valor booleano. Ante una evaluacin verdadera del predicado, corta el ciclo retornando verdadero. Parmetros: predicate predicado a aplicar sobre los elementos del arreglo Retorna: Verdadero si algn elemento del arreglo cumple con el predicado; falso en caso contrario

average
mix average(_LambdaExpression selector = NULL) Computa el promedio de entre los valores de un arreglo. Si el parmetro selector est presente, se utiliza para transformar los valores (o claves y valores) del arreglo. Parmetros: selector selector para transformar los valores del arreglo. Retorna: El promedio de entre los valores del arreglo

concat
__ArrayQuery concat(array(mix) second) Concatena dos arreglos. Parmetros: second arreglo a concatenar al final de la secuencia actual Retorna: Un arreglo que es el resultado de concatenar el arreglo actual, seguido del arreglo second

91

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

count
Integer count(__LambdaExpression predicate) Cuenta los elementos de un arreglo que satisfacen una condicin. El parmetro predicate debe tomar valor (o clave y valor) y retornar verdadero si el elemento se debe sumar a la cuenta. Parmetros: predicate predicado a aplicar sobre los elementos del arreglo para determinar si deben ser contados Retorna: Nmero de elementos del arreglo para el cual el predicado es verdadero

distinct
__ArrayQuery distinct(__LambdaExpression comparer = NULL) Retorna los elementos diferentes de un arreglo. Si el parmetro comparer est presente se utiliza para comparar los elementos del arreglo dos a dos, debe tomar dos elementos del arreglo y retornar verdadero si y slo si dichos elementos son iguales segn la comparacin que se intenta hacer. En el caso de que el parmetro no est presente, se utiliza el comparador de igualdad default del lenguaje. Parmetros: comparer (opcional) expresin que ser utilizada para comparar los elementos del arreglo dos a dos Retorna: Un arreglo con los elementos diferentes de este arreglo segn la comparacin

elementAtOrNull
mix elementAtOrNull(Integer index) Retorna el elemento que se encuentra en la posicin index del arreglo, comenzando a contar en la posicin 0. En el caso de que no exista elemento en dicha posicin, retorna el valor NULL. Parmetros: index posicin a buscar en el arreglo Retorna: El elemento en la posicin index; o NULL si no existe tal elemento

elementAt
mix elementAtOr(Integer index) Retorna el elemento que se encuentra en la posicin index del arreglo, comenzando a contar en la posicin 0. En el caso de que no exista elemento en dicha posicin, se produce un error irrecuperable. Parmetros: index posicin a buscar en el arreglo Retorna: El elemento en la posicin index

except
__ArrayQuery except(array(mix) second, __LambdaExpression comparer = NULL) Produce el conjunto diferencia entre este arreglo y el arreglo second. Si el parmetro comparer est presente se utiliza para comparar los elementos del arreglo dos a dos, debe tomar dos elementos del arreglo y retornar verdadero si y slo si dichos elementos son iguales segn la comparacin que se intenta hacer.

92

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier En el caso de que el parmetro no est presente, se utiliza el comparador de igualdad default del lenguaje. Parmetros: second arreglo con elementos a quitar del resultado comparer (opcional) expresin para comparar los elementos de los arreglos dos a dos y determinar si son iguales Retorna: Arreglo resultante de la diferencia entre el actual y second

firstOrNull
mix firstOrNull(__LambdaExpression predicate = NULL) Retorna el primer elemento del arreglo que satisface la condicin predicate. Predicate es una expresin que toma valor (o clave y valor) y debe retornar verdadero si el elemento del arreglo satisface la condicin requerida. El bucle sobre el arreglo es cortado al encontrar un elemento que satisfaga la condicin. Si el parmetro predicate no est presente simplemente se retorna el primer elemento del arreglo. En este caso, si el arreglo es un arreglo vaco se retorna NULL. Parmetros: predicate (opcional) expresin que determina si un elemento cumple la condicin para ser retornado Retorna: El primer elemento que cumple con la condicin

first
mix first(__LambdaExpression predicate = NULL) Retorna el primer elemento del arreglo que satisface la condicin predicate. Predicate es una expresin que toma valor (o clave y valor) y debe retornar verdadero si el elemento del arreglo satisface la condicin requerida. El bucle sobre el arreglo es cortado al encontrar un elemento que satisfaga la condicin. Si el parmetro predicate no est presente simplemente se retorna el primer elemento del arreglo. En este caso, si arreglo es un arreglo vaco se produce un error irrecuperable. Parmetros: predicate (opcional) expresin que determina si un elemento cumple la condicin para ser retornado Retorna: El primer elemento que cumple con la condicin

foreach
void foreach(__LambdaExpression fcn) Cicla sobre el arreglo aplicando la funcin fcn. Esta funcin debe tomar el elemento del arreglo, o la clave y el valor. Si tiene algn valor de retorno ser ignorado. Parmetros: fcn expresin a ser aplicada sobre cada uno de los elementos del arreglo

ifEmpty
__ArrayQuery ifEmpty(mix elem) Si este arreglo tiene elementos es retornado, en caso contrario se retorna un arreglo con un nico elemento: elem. Parmetros: elem elemento a retornar en un arreglo si este arreglo es vaco

93

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier Retorna: El arreglo; o un arreglo con el elemento elem si el arreglo era vaco

lastOrNull
mix lastOrNull(__LambdaExpression predicate = NULL) Retorna el ltimo elemento del arreglo que satisface la condicin predicate. Predicate es una expresin que toma valor (o clave y valor) y debe retornar verdadero si el elemento del arreglo satisface la condicin requerida. Si el parmetro predicate no est presente simplemente se retorna el ltimo elemento del arreglo. En este caso, si el arreglo es un arreglo vaco se retorna NULL. Parmetros: predicate (opcional) expresin que determina si un elemento cumple la condicin para ser retornado Retorna: El ltimo elemento que cumple con la condicin

last
mix last(__LambdaExpression predicate = NULL) Retorna el ltimo elemento del arreglo que satisface la condicin predicate. Predicate es una expresin que toma valor (o clave y valor) y debe retornar verdadero si el elemento del arreglo satisface la condicin requerida. Si el parmetro predicate no est presente simplemente se retorna el ltimo elemento del arreglo. En este caso, si el arreglo es un arreglo vaco se produce un error irrecuperable. Parmetros: predicate (opcional) expresin que determina si un elemento cumple la condicin para ser retornado Retorna: El ltimo elemento que cumple con la condicin

orderBy
__ArrayQuery orderBy(__LambdaExpression keySelector, __LambdaExpression comparer) Ordena los elementos de un arreglo en orden descendente. keySelector es utilizado para seleccionar los elementos a comparar, es decir, recibe un elemento del arreglo y debe retornar el elemento a comparar, dicho elemento puede ser el mismo del arreglo. comparer es utilizado para comparar los elementos dos a dos, es decir, recibe dos elementos retornados por keySelector y debe retornar: 0 si y slo si los elementos son iguales. Un valor mayor a 0 si el primer parmetro es mayor al segundo. Un valor menor a 0 si el primer parmetro es menor al segundo. Parmetros: keySelector expresin para seleccionar los elementos a comparar comparer expresin que compara dos elementos Retorna: Un nuevo arreglo con los elementos de este arreglo ordenados en forma descendente

select
__ArrayQuery select(__LambdaExpression selector) Proyecta los elementos de un arreglo en una nueva forma. Selector toma cada uno de los valores (o claves y valores) del arreglo y debe retornar dicho elemento en su nueva forma.

94

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier Parmetros: selector expresin para proyectar cada uno de los elementos del arreglo Retorna: Un nuevo arreglo con los valores de este arreglo proyectados por la expresin selector

singleOrNull
mix singleOrNull(__LambdaExpression predicate = NULL) Busca entre los elementos de este arreglo si existe alguno que cumpla con el predicado. Predicate es una lambda expression que toma cada valor (o clave y valor) del arreglo y debe retornar verdadero si y slo si el elemento cumple con la condicin deseada. Si el predicado no est presente, se considera que cualquier elemento del arreglo cumple con la condicin. Si existe un nico elemento que cumple con la condicin, este elemento es retornado. Si no existen elementos que cumplan con la condicin o existe ms de uno, se retorna el valor NULL. Parmetros: predicate (opcional) predicado para evaluar la condicin sobre los elementos del arreglo Retorna: El nico elemento que cumple con la condicin; o NULL

single
mix single(__LambdaExpression predicate = NULL) Busca entre los elementos de este arreglo, si existe alguno que cumpla con el predicado. Predicate es una lambda expression que toma cada valor (o clave y valor) del arreglo y debe retornar verdadero si y slo si el elemento cumple con la condicin deseada. Si el predicado no est presente, se considera que cualquier elemento del arreglo cumple con la condicin. Si existe un nico elemento que cumple con la condicin, este elemento es retornado. Si no existen elementos que cumplan con la condicin, se produce un error irrecuperable. Parmetros: predicate (opcional) predicado para evaluar la condicin sobre los elementos del arreglo Retorna: El nico elemento que cumple con la condicin

toArray
array(mix) toArray() Retorna este arreglo. Si ya estamos hablando de un arreglo un arreglo con los mismos elementos es retornado. Si es un __ArrayQuery, se retorna un arreglo que est formado por todos los elementos del __ArrayQuery evaluado. Esta funcin no es til por s solo, si no al combinarla con otras funciones de primer orden, ya que sirve para disparar la evaluacin de un __ArrayQuery y convertirlo en un arreglo del lenguaje. Retorna: Un arreglo con los mismos elementos de este arreglo

where
__ArrayQuery where(__LambdaExpression predicate) Retorna los elementos de este arreglo filtrados por la expresin predicate. Predicate debe ser una expresin lambda que toma cada uno de los valores (o claves y valores) del arreglo original y retorna verdadero si y slo si el valor actual debe estar incluido en el arreglo que se devolver como resultado.

95

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier Parmetros: predicate predicado que determina si los elementos del arreglo deben ser incluidos Retorna: Un nuevo arreglo con los elementos nicamente para los que predicate retorn verdadero

Aclaracin importante: Muchas de las expresiones lambda utilizadas por estas funciones cuentan con la posibilidad de tomar tanto la clave como el valor de los elementos del arreglo. Cabe destacar que la clave es correctamente pasada slo a la primer funcin aplicada, es decir cuando el objeto sobre el cual se aplica es un arreglo del lenguaje. Si el objeto es de tipo __ArrayQuery y la expresin lambda espera la clave del elemento adems del valor, recibir el valor NULL como clave. Esto es porque los objeto de tipo __ArrayQuery no son realmente arreglos sino que se consideran un conjunto de elementos y por lo tanto sus elementos no estn asociados a una clave.

Manipulacin de objetos Java


Uno de los objetivos de nuestro lenguaje fue que sea fcil de extender, que no resulte difcil escribir una librera con clases de cualquier tipo. Pero como lograr este objetivo? Que mejor que permitir manipular objetos Java desde nuestro lenguaje. Para poder manipular objetos Java desde nuestro lenguaje damos soporte a dos funciones, java.lang.ClassLoader.addJar y java.lang.ClassLoader.loadClass. addJar
public static void addJar(String jarPath) Agrega un archivo de tipo jar a los archivos de libreras java en los cuales se buscarn clases cuando se invoque loadClass. Parmetros: jarPath locacin fsica del archivo de libreras java

loadClass
public static void Class loadClass(String name) Lee una clase java, para ser ms preciso del tipo java.lang.Class y la retorna. Parmetros: name nombre completo (con el package) de la clase java Retorna: Objeto de tipo java.lang.Class

Esta ltima funcin retorna un objeto de un tipo que es del lenguaje Java y no pertenece a nuestro propio lenguaje, sin embargo es tratado tambin como un objeto de nuestro lenguaje. Es decir que hay ciertos mtodos que se pueden aplicar directamente sobre un objeto de tipo java.lang.Class como si fuese un objeto propio del lenguaje. Los mtodos que estn permitidos son los siguientes. 96

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

getConstructor
public Constructor getConstructor(array(Class) parameterTypes) Retorna un objeto de tipo Constructor que refleja un constructor pblico de la clase que representa este objeto. El parmetro parameterTypes es un arreglo de objetos del tipo Class que identifica el tipo de los parmetros del constructor en el orden en el que fueron declarados. Parmetros: parameterTypes el arreglo de parmetros Retorna: El objeto que representa el constructor pblico que machea con los parmetros especificados en el arreglo parameterTypes

getField
public Field getField(String name) Retorna un objeto de tipo Field que refleja un campo pblico de esta clase. El parmetro name es el nombre simple del campo que se desea obtener. Tambin se busca en campos declarados en clases ancestro. Paremtros: name el nombre del campo a buscar Retorna: El objeto de tipo Field de esta clase especificado por name

getMethod
public Method getMethod(String name, array(Class) parameterTypes) Retorna un objeto de tipo Method que refleja un mtodo pblico especificado en esta clase. El parmetro name es el nombre simple del mtodo que se desea obtener. ParameterTypes es un arreglo con los tipos de los parmetros formales del mtodo que se desea obtener, si es nulo es tratado como un arreglo vaco. Parametros: name el nombre del mtodo parameterTypes lista de los tipos de los parmetros formales del mtodo Retorna: El objeto de tipo mtodo que refleja el mtodo de esta clase que machea con name y parameterTypes

Sobre un objeto de tipo Constructor se soporta un nico mtodo. NewInstance


public Object newInstance(array(Object) initargs) Usa el constructor representado por este objeto para crear e inicializar un nuevo objeto del tipo del que este constructor declara, con los parmetros initargs especficos. El arreglo de parmetros puede ser de longitud 0 o NULL, en cuyo caso se trata como si fuese de longitud 0. Parmetros: initargs arreglo de objetos para pasar al constructor como argumentos Retorna: Un objeto creado a partir del constructor que este objeto representa

97

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Sobre el tipo Field, se soportan dos mtodos. get


public Object get(Object obj) Retorna el valor actual del campo representado por este campo, sobre el objeto obj. Si el campo es esttico, el parmetro obj es ignorado y podra ser NULL. Parmetros: obj objeto sobre el cual obtener el valor del campo Retorna: Valor del campo representado por este campo

set
public void set(Object obj, Object value) Asigna al campo representado por este campo el valor especificado en value, sobre el objeto especificado en obj. Si se trata de un campo esttico, el valor de obj es ignorado y podra ser NULL. Parmetros: obj objeto sobre el cual se desea asignar el valor al campo representado por este objeto value valor que se desea asignar al campo representado por este objeto

Finalmente, sobre objetos de tipo Method se soporta tambin un nico mtodo. invoke
public Object invoke(Object obj, array(Object) args) Invoca el mtodo subyacente representado por este objeto, sobre el objeto especificado en obj, con los parmetros especificados en args. Si el mtodo representado por este objeto es esttico, el parmetro obj es ignorado y podra ser NULL. Si el mtodo representado por este objeto no tiene argumentos, el parmetro args puede tener longitud 0 o ser NULL. Parmetros: obj objeto sobre el cul invocar el mtodo representado por este objeto args argumentos con los cules invocar el mtodo Retorna: El valor retornado por la ejecucin del mtodo representado por este objeto, si es que tiene valor de retorno

Con todas estas caractersticas es suficiente para crear y manipular cualquier objeto de tipo Java, tambin es suficiente para manipular cualquier clase Java. Es decir, ya podemos crear objetos, obtener y asignar valores de campos, invocar mtodos sobre objetos, obtener y asignar valores de campos estticos e invocar mtodos estticos. An as, todava hay un objeto del lenguaje Java que no podemos manipular por completo, es el arreglo nativo de Java. Para manipular arreglos del lenguaje Java hemos introducido la clase JavaArray, la clase JavaArray tiene soporte para los siguiente mtodos. 98

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

get
public static Object get(Object arr, Integer index) Obtiene el valor del objeto en la posicin index en el arreglo arr, comenzando en la posicin 0. Parmetros: arr el arreglo index el ndice Retorna: El valor en arr del objeto en la posicin index

getBoolean
public static Boolean getBoolean(Object arr, Integer index) Obtiene el valor del objeto en la posicin index en el arreglo arr, comenzando en la posicin 0, como un Boolean. Parmetros: arr el arreglo index el ndice Retorna: El valor en arr del objeto en la posicin index

getFloat
public static Boolean getFloat(Object arr, Integer index) Obtiene el valor del objeto en la posicin index en el arreglo arr, comenzando en la posicin 0, como un Float. Parmetros: arr el arreglo index el ndice Retorna: El valor en arr del objeto en la posicin index

getInt
public static Boolean getInt(Object arr, Integer index) Obtiene el valor del objeto en la posicin index en el arreglo arr, comenzando en la posicin 0, como un Integer. Parmetros: arr el arreglo index el ndice Retorna: El valor en arr del objeto en la posicin index

getLength
public static Integer getLength(Object arr) Obtiene la longitud de el arreglo representado por arr. Parmetros: arr arreglo sobre el cual se desea obtener la longitud

99

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier Retorna: Un entero que representa la longitud del arreglo en arr

newInstance
public static Object newInstance(Class componentType, Integer length) Crea un nuevo arreglo con el tipo de los componentes componentType y de longitud length. Parmetros: componentType tipo de los componentes del arreglo que se desea crear length longitud del arreglo que se desea crear Retorna: Arreglo recin creado, cuyo tipo de los componentes es componentType y de longitud length

newInstanceWithDimensions
public static Object newInstanceWithDimensions(Class componentType, array(Integer) dimensions) Crea un arreglo, cuyos componentes son del tipo representado por componentType y de dimensions.length dimensiones. La longitud de la dimensin i es dimensions[i]. Parmetros: componentType tipo de los componentes del arreglo a crear dimensions arreglo de enteros, con la longitud de cada uno de los subarreglos a crear Retorna: Un arreglo segn las especificaciones componentType y dimensions

set
public static void set(Object arr, Integer index, Object value) Asigna el valor value en la posicin index del arreglo arr, comenzando a contar en la posicin 0. Parmetros: arr arreglo al cual se le desea asignar un valor index ndice en el cul se desea asignar el valor value valor a asignar

setBoolean
public static void setBoolean(Object arr, Integer index, Boolean value) Asigna el valor value en la posicin index del arreglo arr, comenzando a contar en la posicin 0, como un Boolean. Parmetros: arr arreglo al cual se le desea asignar un valor index ndice en el cul se desea asignar el valor value valor a asignar

setFloat
public static void setFloat(Object arr, Integer index, Float value) Asigna el valor value en la posicin index del arreglo arr, comenzando a contar en la posicin 0, como un Float. Parmetros: arr arreglo al cual se le desea asignar un valor

100

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier index ndice en el cul se desea asignar el valor value valor a asignar

setInt
public static void setInt(Object arr, Integer index, Integer value) Asigna el valor value en la posicin index del arreglo arr, comenzando a contar en la posicin 0, como un Integer. Parmetros: arr arreglo al cual se le desea asignar un valor index ndice en el cul se desea asignar el valor value valor a asignar

Ahora s, con todas estas caractersticas introducidas, podemos manipular todo lo necesario sobre el lenguaje Java para escribir libreras en nuestro propio lenguaje que por debajo usen Java. De hecho, muchas de las libreras ya implementadas, utilizan esta tcnica y en realidad son wrappers de libreras Java.

Logging y manejo de errores


Cualquier template o librera, tiene la posibilidad de informar progreso (o cualquier otra cosa) al usuario mediante la salida estndar. Para imprimir una cadena de caracteres, o tipo nativo por la salida estndar, se usa el mtodo especial Log.
<%% Log(""); Log("This is a String"); Log(1); Log(1.1); Log(true); %%>

A su vez, tambin contamos con una infraestructura para informar errores y warnings, as como tambin para terminar la ejecucin ante la presencia de un error fatal. Durante su ejecucin, el parser va recolectando informacin sobre los errores que se producen. Al finalizar se pueden explorar estos logs programticamente e informar al usuario sobre los mismos. Si se produce un error del que no es posible recuperarse, finaliza la ejecucin del parser y se informa al usuario.
<%% // Informa al parser que debe recolectar este warning para informarlo al final de su ejecucin. Log.warning("This is a warning"); // Informa al parser que debe recolectar este error para informarlo al final de su ejecucin. Log.error("This is an error"); // Finaliza la ejecucin del parser indicndole que debe informar la causa del error fatal. Log.fatal("This is a fatal error"); %%>

101

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

El plugin desarrollado informar de estos errores mediante los mecanismos que provee el IDE a tal fin.

Autoloader
Cuando se intenta utilizar una clase inexistente se produce un error irrecuperable. Para que no sea necesario incluir un archivo por cada clase que se desea utilizar se introdujo una nueva caracterstica. Existe una clase especial denominada Autoloader. Si no se encuentra una determinada clase segn su nombre, antes de fallar, el parser intentar encontrar esta clase con los objetos registrados como Autoloaders. La clase Autoloader cuenta con los siguientes campos y mtodos. DEFAULT_PRIORITY
public static Float DEFAULT_PRIORITY La prioridad utilizada por default cuando ninguna otra prioridad fue asignada. Es decir, si se registran objetos sin invocar antes a Autoloader.setPriority, todos los objetos sern registrados con esta prioridad.

add
public static void add(Autoloader autoloader) Agrega un objeto a la lista de objetos a los cuales se interrogar para incluir clases que an no existen ante su primer uso. La prioridad utilizada ser la ltima que se ha asignado con Autoloader.setPriority, o Autoloader.DEFAULT_PRIORITY si nunca se ha invocado al mtodo para asignar prioridad.

SetPriority
public static void setPriority(Float newPriority) Asigna una nueva prioridad al Autoloader, la prxima vez que se invoque al mtodo Autoloader.add, el objeto ser registrado con prioridad newPriority. Parmetros: newPriority prioridad a asignar

getPriority
public static Float getPriority() Retorna la prioridad actual, es decir la prioridad con la que se registrar al prximo objeto mediante la invocacin del mtodo Autlodader.add. Retorna: Prioridad actual

autload
public void autload(String className) Este mtodo no tiene implementacin actual y debe ser reimplementado por todos los herederos. La idea de este mtodo es que ser invocado con el nombre de una clase que no se pudo encontrar an, la ejecucin del mtodo debera intentar incluir un archivo si es que conoce en qu archivo est la especificacin de la clase de nombre className. Luego de la inclusin la clase de nombre className ya debera existir. Parmetros: className nombre de la clase que an no existe y se est intentando utilizar

102

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Entonces, el parser sigue el siguiente pseudo algoritmo si no encuentra la definicin de una clase.
Sea className el nombre de la clase cuya definicin no se ha encontrado. Para los autoloader registrados de 1.. n ordenados por prioridad de registracin ascendente hacer { invocar autoloader.autoload(className) si existe className finalizar el ciclo y retornar si no existe class name autoloader = prximo autoloader en la lista } Error irrecuperable, className no existe!

Una implementacin tpica de Autoloader es como sigue.


<%% /** * This class is responsible for auto load all freelancesoft library * classes. * */ class FSLibAutoloader extends Autoloader { private specialClasses = array( "JavaWrapper" => __Path.getCurrentDirectory() $ "/java/wrap/JavaWrapper.fgl", "JavaConverter" => __Path.getCurrentDirectory() $ "/java/wrap/JavaConverter.fgl", "JavaArrayConverter" => __Path.getCurrentDirectory() $ "/java/wrap/JavaArrayConverter.fgl", "String" => __Path.getCurrentDirectory() $ "/java/wrap/java/lang/String.fgl", "Integer" => __Path.getCurrentDirectory() $ "/java/wrap/java/lang/Integer.fgl", "Float" => __Path.getCurrentDirectory() $ "/java/wrap/java/lang/Float.fgl", "Boolean" => __Path.getCurrentDirectory() $ "/java/wrap/java/lang/Boolean.fgl", "File" => __Path.getCurrentDirectory() $ "/java/wrap/java/io/File.fgl" ); /** * Tries to auto load a class. * * @param String className * The name of the class that must be loaded. */ public function autoload(className) { specialPath = this.specialClasses[className]; if (specialPath == null) { // Find if ther is as a java wrap file = File.create(__Path.getCurrentDirectory() $ "/java/" $ className.replaceAll("_", "/") $ ".fgl"); if(file.exists()) { Require.once(file.getAbsolutePath()); } else { // Find if ther is as a library class file = File.create(__Path.getCurrentDirectory() $ "/" $ className.replaceAll("_", "/") $ ".fgl"); if(file.exists()) { Require.once(file.getAbsolutePath()); } } } else { Require.once(specialPath); } } /**

103

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
* Default constructor. Simply adds this to Autoloader. * */ public function FSLibAutoloader() { } } Autoloader.add(new FSLibAutoloader()); %%>

De este modo, no es necesario incluir un archivo cada vez que deseamos utilizar la clase definida en el mismo. Sino que estos objetos pueden encargarse de buscar estos archivos por nosotros. En el ejemplo, el objeto conoce la locacin de los archivos que corresponden a ciertas clases especiales como Integer, Float, String, etc. para cualquier otro nombre de clase intentar buscar el archivo utilizando el carcter _ como si fuese el separador para nombre de directorios. Si el archivo existe (tomando como base el directorio actual), lo incluir. En cualquier otro caso se pasar a invocar al mtodo autoload del prximo objeto segn su prioridad o fallar si no existe tal implementacin registrada.

Writer
Para crear y escribir los archivos generados, existe la clase especial writer con los siguientes mtodos. open
public static void open(String fileName) Abre un archivo para escribir. Luego de invocar open, las siguientes invocaciones a Writer.echo escribirn sobre el archivo recin abierto. A su vez, las secciones fuera de los delimitadores <%% y %%> se interpretarn al igual que si se invocara Writer.echo. Parmetros: fileName nombre del archivo sobre el cual se desea escribir

close
public static void close() Cierra el ltimo archivo abierto por una invocacin a Writer.open. Si no existe un archivo abierto se producir un error irrecuperable.

echo
public static void echo(Object toWrite) Intenta escribir un objeto sobre el ltimo archivo abierto. El parmetro toWrite ser convertido a String antes de ser escrito en el archivo. Si no existe un archivo abierto se producir un error irrecuperable. Parmetros: toWrite objeto a ser escrito sobre el ltimo archivo abierto

104

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

La funcin especial @ La funcin @ es un alias de la funcin Writer.echo, pero funciona en diferentes contextos. Tambin funciona fuera de los lmites de <%% y %%>. Entonces, hay varias maneras de escribir en un archivo, por lo que las siguientes sentencias son equivalentes.
<%% Writer.echo("to write"); %%> <%% @("to write"); %%> to Write @("to write")

El hecho de que la funcin @ escape a los caracteres de scripting es particularmente til en templates, para que sean ms legibles, sin necesidad de tantos caracteres de escape.

Configuracin
Para configurar el parser antes de ejecutarlo hay ciertos parmetros que pueden ser asignados y luego sern accesibles dentro del cdigo escrito en nuestro lenguaje. Para esto existe la clase especial __Config con los siguientes mtodos. getFsLibPath
public static String getFsLibPath() Obtiene el directorio raz en donde se encuentran las libreras que hemos implementado. Retorna: Directorio donde estn nuestras libreras

getConfigPath
public static String getConfiigPath() Obtiene el directorio en donde los templates deberan buscar archivos de configuracin. Retorna: Directorio en donde buscar archivos de configuracin

getTemplatesPath
public static String getTemplatesPath() Obtiene el directorio en donde el parser buscar archivos de template. Retorna: Directorio donde el parser buscar archivos de template

getInputPath
public static String getInputPath() Obtiene el directorio donde el parser buscar archivos de entrada para que procesen los templates. Retorna: Directorio donde buscar archivos de entrada

getTargetPath 105

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier public static String getTargetPath() Obtiene el directorio donde se espera que los templates generen contenido. Retorna: Directorio base en donde generar los archivos

getTemplateMainFile
public stati String getTemplateMainFile() Obtiene el nombre de los archivos principales de templates, es decir el primero que se ejecutar por cada template. El valor default de esta propiedad de configuracin es main.fgl. Con lo cual el parser buscar este archivo en el directorio base en donde se deberan encontrar los templates. Retorna: Nombre del archivo principal de template

get
public static String get(String key) Obtiene un parmetro genrico de configuracin asociado a una clave, que puede ser asignado desde el propio lenguaje. Parmetros: key clave del parmetro de configuracin Retorna: Valor del parmetro de configuracin asociado a la clave key; o el valor NULL si no existe ningn valor asociado a la clave

set
publis static void set(String key, Object value) Asocia un valor a un parmetro de configuracin, de modo que la prxima vez que se invoque __Config.get(key) se obtendr el valor value. Parmetros: key clave a la cual se le desea asignar el valor value value nuevo valor para la clave key

A su vez, existe otra clase especial con dos mtodos, que sirven para que los archivos de template puedan hacer referencias relativas a su propia ubicacin. Esta es la clase __Path y cuenta con los siguientes mtodos. getCurrent
public static String getCurrent() Obtiene la ruta absoluta el archivo que el parser est procesando actualmente. Retorna: Ruta absoluta del archivo que se est procesando

getCurrentDirectory
public static String getCurrentDirectory()

106

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier Obtiene la ruta absoluta del directorio donde se encuentra el archivo que el parser est actualmente procesando. Retorna: Ruta absoluta del directorio en donde se encuentra el archivo actualmente en proceso

Proyectos desarrollados
A continuacin, explicaremos los proyectos que hemos desarrollado para dar soporte a esta idea. No ahondaremos en demasiados detalles ya que el cdigo est completamente comentado y se puede consultar el mismo para mayor detalle. Del mismo modo, se puede ejecutar la meta site sobre los proyectos y as consultar la documentacin generada.

CodeGeneratorPoms
CodeGeneratorPoms es un proyecto multi-mdulo, que consta de tres proyectos. Cada uno de ellos contiene un archivo pom que ser utilizado como padre para descriptores de otros proyectos. El objetivo es contar con un lugar comn donde se puedan definir caractersticas comunes que puedan compartir diferentes proyectos. Los subproyectos son los siguientes. CodeGeneratorParentPom. Contiene un descriptor que directa o indirectamente es usado por casi todos los dems proyectos. Define caractersticas como: Variables que contienen versin actual del generador, directorio default para instalar libreras, directorio default para instalar templates, rutas para crear escenarios durante los tests, rutas para obtener libreras y templates durante los tests, url del archivo de estilos de programacin definido. Versin de la mquina virtual utilizada. Configuracin para limpiar escenarios creados durante los tests. Descripcin de los repositorios internos maven. CodeGeneratorLibraryParentPom. Contiene un descriptor con caractersticas utilizadas por todas las libreras desarrolladas como: Configuracin para empaquetar una librera. Configuracin para desempaquetar las libreras que se utilicen como dependencias. CodeGeneratorTemplatesParentPom. Contiene un descriptor con caractersticas utilizadas por todos los templates desarrolladas como: Configuracin para empaquetar un template. Configuracin para desempaquetar los templates y libreras que se utilicen como dependencias. Adems en este proyecto agregamos archivos ampliamente utilizados durante el 107

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

desarrollo. Dado que nuestro servidor no cuenta con recursos suficientes para ejecutar jenkins, creamos herramientas para simular corridas de builds. De este modo podemos asegurar que ante el impacto de un cambio en un proyecto no dejan de funcionar los proyectos que lo utilicen como dependencia. Una de las herramientas es deployall, se utiliza por lnea de comandos y cuenta con los siguientes argumentos.
Modo de uso: deployall.php [opciones] Sin opciones hace update por cvs, deploy de todos los proyectos y chequea cobertura del proyecto CodeGenerator Opciones: -cvsu -e -h -i -mvn -nc -nm -nu -vbox Usuario cvs Nombre de los proyectos a excluir separado por comas Muestra esta ayuda Nombre de los proyectos a incluir separado por comas Ociones Maven No correr cobertura:clean cobertucha:check sobre el proyecto CodeGenerator No Maven runs No cvs update Corre vboxdeployall.php con parmetros por default antes de finalizar

Esta herramienta funciona tanto en entornos windows como linux. Dado que la mayor parte del tiempo desarrollamos sobre entornos linux, tambin agregamos el archivo vboxdeployall. Este hace casi lo mismo que el anterior, pero en realidad enciende una mquina virtual preconfigurada con un entorno windows. Es decir que podremos ver el resultado de deployall sobre la ltima versin del cdigo en un entorno windows.
Modo de uso: vboxdeployall.php [opciones] Sin opciones abre la mquina virtual, ejecuta deployall.php y apaga la mquina virtual Opciones: -mn Machine Name. Default: TesisXP -u -p -a SSH user. Default: codegenerator SSH pass. Default: codegenerator Arguments. Default: "-nc -cvsu cvsadmin -mvn clean\ install"

108

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

CodeGeneratorModules
CodeGeneratorModules es un proyecto multi-mdulo que contiene los proyectos principales del generador de cdigo. Es decir, es el corazn del generador. Est compuesto por tres proyectos: CodeGeneratorCommon, CodeGeneratorCommonTests y CodeGenerator. CodeGeneratorCommon Este proyecto tiene principalmente dos objetivos. El primero es agrupar clases comunes que se utilizarn durante el parseo. El segundo es definir todas las interfaces necesarias para implementar un parser de nuestro lenguaje en su totalidad. Paquete freelancesoft.codegenerator.common Contiene la implementacin de una pila que es utilizada por el parser como pila del lenguaje durante la interpretacin. Adems, varias clases Manager con implementaciones actuales. De este modo, la implementacin actual de una clase a la cual se le delega un trabajo especfico, puede cambiarse durante la ejecucin. Todas estas clases tienen dos mtodos estticos, setCurrent para asignar la implementacin actual y current para obtener la implementacin actual. Estas clases son las siguientes: ConfigurationManager. Con la implementacin actual de Configuration. ContextFactoryManager. Con la implementacin actual de ContextFactory. LogManager. Con la implementacin actual de Recordable. StackManager. Con la implementacin actual de LanguageStack. StackTraceManager. Con la implementacin actual de Stack<TreeNode>. WriterManager. Con la implementacin actual de Writer.

Al crear el parser, automticamente sern asignadas todas las implementaciones actuales para estas interfaces pero pueden ser cambiadas en cualquier momento. Paquete freelancesoft.codegenerator.common.array Define la interfaz LanguageArray, la cual debe respetar cualquier implementacin de un arreglo del lenguaje. Adems, la excepcin UnsupportedKeyException que puede ser arrojada por los mtodos de LanguageArray. Paquete freelancesoft.codegenerator.common.arrayquery Define las interfaces necesarias para implementar el pseudo lenguaje sobre arreglos. 109

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

ArrayQuery. Interfaz que debe respetar la estructura de datos que mantiene las funciones de primer y segundo orden aplicadas sobre un arreglo. Simplemente define mtodos para agregar implementaciones de dichas funciones. LastQueryStep. Interfaz que debe implementar una funcin de segundo orden sobre un arreglo del lenguaje. Define slo dos mtodos, simplemente creando un objeto que la implemente y registrndolo con una clase de tipo factory es suficiente para tener disponible una nueva funcin sobre arreglos. NoLastQueryStep. Interfaz que debe implementar una funcin de primer orden sobre un arreglo del lenguaje. Define cuatro mtodos, para que haya una nueva funcin de primer orden sobre arreglos disponible en el lenguaje se debe crear un objeto que respete esta interfaz y registrarlo con una clase de tipo factory. QueryStep. Interfaz que define dos mtodos que deben implementar tanto los objetos que representen funciones de primer orden, como los que representen funciones de segundo orden.

Con estas interfaces y su correspondiente implementacin, resulta relativamente sencillo agregar una nueva funcin sobre objetos de tipo arreglo del lenguaje. Paquete freelancesoft.codegenerator.common.configuration Define una nica interfaz, Configuration. Es la que se debe implementar para dar soporte al objeto del lenguaje __Config. Paquete freelancesoft.codegenerator.common.context En todo lenguaje existen entidades que tienen un contexto en el cual ejecutan, como variables, clases, objetos, funciones, mtodos. Este paquete contiene interfaces varias que deben implementarse para dar vida a esas entidades, tambin contiene las excepciones que manejan esos objetos. No nombraremos todas una por una, slo diremos que existe una ContextFacotry, que se encarga de crear estos contextos y las dems clases representan esos contextos en s mismos. Cuando el parser requiere la creacin de una entidad, pedir a la implementacin de ContextFactory la creacin de un contexto en el cual debe ejecutar esa entidad, pasando las caractersticas de la entidad. De este modo, ContextFactory, junto con la implementacin de los contextos apropiados, toma ciertas decisiones sobre caractersticas del lenguaje (como por ejemplo el alcance de una variable segn el contexto en el cul fue definida) que no son inherentes al parser. Paquete freelancesoft.codegenerator.common.errorhandle Define interfaces y algunas clases que estn relacionadas con el manejo de errores y warnings. Manejamos errores irrecuperables, para lo que define IrrecuperableError y IrrecuperableCause. La clase Record contiene informacin variada, 110

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Define todos los mensajes de error (en el futuro pude llegar a internacionalizarse de una manera muy sencilla). Define los tipos de error (warning, error y error irrecuperable). Adems un objeto de este tipo contiene toda la informacin necesaria para informar adecuadamente sobre un warning o error. Como lneas (inicio y fin), columnas (inicio y fin) en las que se produjo el error, una descripcin de la causa, el tipo, el archivo en el que se produjo y la excepcin asociada al error (si es que existe).

Este paquete tambin contiene la interfaz Recordable, la cual debe ser implementada por el manejador de errores del lenguaje. Paquete freelancesoft.codegenerator.common.parser Define interfaces varias que tienen que ver con la implementacin del core del parser. LanguageParser. Interfaz que debe respetar la implementacin del parser propiamente dicho. TreeNode. Interfaz para cualquier nodo en el rbol de parseo. En general estos nodos son interpretados en una segunda pasada del parser. BreakableNode. Interfaz que implementan los nodos que deben ser informados si se ejecuta una sentencia break, en general para detener la ejecucin de un ciclo o evitar la ejecucin de las sentencias siguientes. ContinueableNode. Interfaz que implementan los nodos que deben ser informados ante la ejecucin de una sentencia continue, en general para evitar que se ejecute un conjunto de sentencias que le siguen al continue. ReturnableNode. Similar a la anterior, pero la implementan nodos que deben ser informados si se ejecuta una sentencia return. FieldInitializatorNode. Interfaz que implementan ciertos nodos que inicializan campos de clases o instancias de clases. ConstructorInitializatorNode. Interfaz para la caracterstica extendida del lenguaje de inicializacin dinmica de objetos.

Paquete freelancesoft.codegenerator.common.writer Define slo la interfaz Writer, la cual debe ser implementada para objetos que se encargan de escribir los archivos de salida que son generados por una interpretacin. El parser delega todas las escrituras en objetos de este tipo, ya sea que se produzcan por la sentencia Writer.echo, por el alias @ o por cadenas fuera de los delimitadores <%% y %%>.

111

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

CodeGeneratorCommonTests Este proyecto contiene clases que darn soporte para realizar tests unitarios automticos en todos los otros tests. Hay una clase principal, ParserTestBase, que servir como clase base para todas las clases de tests. El resto de las clases que se encuentran en este proyecto dan soporte a ParserTestBase. Entre otras cosas, ParserTestBase brinda: Inicializacin preconfigurada para tests del propio parser, libreras o templates. Con la cual contamos con un parser inicializado apropiadamente para correr sobre un escenario. Mocking sobre la salida estndar, con lo cual se puede verificar que una ejecucin ha mostrado lo que se desee sobre la salida estndar. Mocking sobre la clase Writer, con lo cual se puede verificar que se ha invocado a Writer.echo, Writer.open y Writer.close con los parmetros adecuados luego de una ejecucin. Creacin de escenarios sobre los cules podemos agregar archivos de configuracin, entrada, librera o templates a gusto. Posibilidad de verificar que dado un escenario y un conjunto de archivos de salida, los archivos que gener el parser luego de su ejecucin coinciden con los esperados. Posibilidad de obtener archivos especficos localizados en una direccin relativa al test actualmente corriendo. Posibilidad de agregar archivos con contenido especfico. Posibilidad de verificar contenido de archivos especficos contra archivos dentro de un proyecto o agregados con el mecanismo anterior. Posibilidad de indicar que se espera un determinado warning, error o error irrecuperable. Posibilidad de verificar que los errores y warnings que antes se han indicado se produjeron luego de una ejecucin. Verificacin automtica de que no se han producido errores o warnings inesperados, es decir que no se produjo ninguno que no se ha indicado previamente.

Heredando de esta clase resulta relativamente sencillo llevar a cabo un test unitario automtico, tanto para el parser en s mismo como para una librera o template. Por ejemplo, un test de una librera no cuenta con muchas lneas.
@Test public void M_createAttribute_Success() throws Throwable { initializeTest();

112

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
// setup writerExpectations.one("wrap_org_w3c_dom_Attr").checking(); // execute parser.parseUnit(); ContextFactoryManager.current().getRootContext().getField(XML_VARIABLE_NAME_1, null).setValue( getFixedFilePath("xml/testFile_001.xml")); parser.interpret(); // verify writerExpectations.assertIsSatisfied(); }

Pero s est verificando muchas cosas. Si su ejecucin es exitosa, sabemos que el mtodo createAttribute crea una instancia de la clase esperada, tambin se invoc Writer.echo con el argumento esperado y adems, no se produjo ningn error o warning durante la ejecucin del parser. Verificar todo esto implicara una cantidad de cdigo considerable, pero puede hacerse en unas cuantas lneas gracias al soporte brindado por la clase ParserTestBase. Del mismo modo, un test para verificar el comportamiento de un template es relativamente sencillo.
@Test public void setterDefault() throws Throwable { // Setup scenario.input.addFile("setterDefault.xml", "default.xml"); scenario.expectedTarget.addDirectory("classes"). addDirectory("default"). addFile("setterDefault.php", "DefaultEntity.php"); writerExpectations.logUntilRun("default", "php-entities"). oneOfLog("Generating class DefaultEntity"). oneOfLog(""). checking(); // Run parser.parseUnit(); parser.interpret(); // Verify writerExpectations.assertIsSatisfied(); scenario.verifyTarget(); }

No slo se est verificando el comportamiento correcto (archivos generados) para una determinada entrada, sino que tambin sabemos que se inform del progreso mediante la salida estndar de manera correcta y que no se produjeron errores o warnings. CodeGenerator El proyecto CodeGenerator es uno de los principales ya que aqu se implementan todas las interfaces definidas en CodeGeneratorCommon. Adems cuenta con la implementacin del parser. La distribucin de los paquetes tambin es similar a la del proyecto CodeGeneratorCommon.

113

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Paquete freelancesoft.codegenerator.array En este paquete se encuentra la implementacin de todas las interfaces definidas en freelancesoft.codegenerator.common.array. Adems tambin cuenta con otras clases para dar soporte a arreglos del lenguaje. La nica clase que es visible por fuera del paquete es LanguageArrayFactory, que contiene un mtodo de creacin para arreglos que retorna un objeto de tipo LanguageArray. De este modo, la implementacin interna de los arreglos queda totalmente encapsulada. Paquete freelancesoft.codegenerator.arrayquery En este paquete encontramos las clases que hacen posible las funciones de primer y segundo orden sobre arreglos del lenguaje. Dentro de lo posible, la implementacin tambin se encuentra confinada al paquete. Una de las principales clases pblicas (visibles por fuera del paquete) es la clase ArrayQueryFactory. Esta clase es utilizada directamente por el parser para consultar sobre las funciones disponibles. Cuenta con un bloque esttico donde se debe registrar cada implementacin de una funcin para que est disponible y se pueda utilizar desde el lenguaje. De momento tiene registradas las siguientes implementaciones.
static { initializators.put(WhereStep.NAME, WhereStep.getInitializator()); initializators.put(ConcatStep.NAME, ConcatStep.getInitializator()); initializators.put(IfEmptyStep.NAME, IfEmptyStep.getInitializator()); initializators.put(ToArrayStep.NAME, ToArrayStep.getInitializator()); initializators.put(AggregateStep.NAME, AggregateStep.getInitializator()); initializators.put(AllStep.NAME, AllStep.getInitializator()); initializators.put(AnyStep.NAME, AnyStep.getInitializator()); initializators.put(AverageStep.NAME, AverageStep.getInitializator()); initializators.put(CountStep.NAME, CountStep.getInitializator()); initializators.put(DistinctStep.NAME, DistinctStep.getInitializator()); initializators.put(ElementAtStep.NAME, ElementAtStep.getInitializator()); initializators.put(ElementAtOrNullStep.NAME, ElementAtOrNullStep.getInitializator()); initializators.put(ExceptStep.NAME, ExceptStep.getInitializator()); initializators.put(FirstStep.NAME, FirstStep.getInitializator()); initializators.put(FirstOrNullStep.NAME, FirstOrNullStep.getInitializator()); initializators.put(LastStep.NAME, LastStep.getInitializator()); initializators.put(LastOrNullStep.NAME, LastOrNullStep.getInitializator()); initializators.put(SingleStep.NAME, SingleStep.getInitializator()); initializators.put(SingleOrNullStep.NAME, SingleOrNullStep.getInitializator()); initializators.put(SelectStep.NAME, SelectStep.getInitializator()); initializators.put(ForEachStep.NAME, ForEachStep.getInitializator()); initializators.put(OrderByStep.NAME, OrderByStep.getInitializator()); }

Paquete freelancesoft.codegenerator.arrayquery.steps Lo nico que contiene esta clase es la implementacin de cada una de las funciones sobre arreglos registradas en ArrayQueryFactory. Son todas clases que implementan LastQueryStep o NoLastQueryStep. Desde el lenguaje, cada una de estas clases se puede ver como una funcin disponible sobre objetos de tipo arreglo. Para contar con una nueva funcin, es suficiente con agregar la implementacin aqu y registrar una instancia en ArrayQueryFactory.

114

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Paquete freelancesoft.codegenerator.configuration Este paquete contiene la implementacin por default de la interfaz Configuration definida en freelancesoft.codegenerator.common.configuration. Paquete freelancesoft.codegenerator.context En este paquete estn todas las implementaciones default de las interfaces definidas en freelancesoft.codegenerator.common.context. Estas clases son las que realmente deciden cual es el alcance de las entidades, como variables, objetos, mtodos accedidas dentro del lenguaje. Adems estn definidos aqu la mayor parte de los mtodos a los cules se les da soporte nativo. Como mtodos sobre tipos Float, Integer, String, Object, JavaArray, JavaClass, JavaConstructor, JavaField, JavaMethod y el tipo nativo array. Paquete freelancesoft.codegenerator.errorhandle Contiene slo la implementacin default de la interfaz Recordable definida en freelancesoft.codegenerator.common.errorhandle. Es la encargada del manejo de warnings, errores y errores irrecuperables. El parser la utilizar para llevar cuenta de los errores producidos durante su ejecucin, luego se la puede consultar para determinar todas las anomalidades producidas. Paquete freelancesoft.codegenerator.parser En este paquete se encuentra la implementacin del parser y todos los nodos que pueden formar parte del rbol generado por el parser. En su mayora son clases generadas por JavaCC y luego modificadas segn las necesidades. Paquete freelancesoft.codegenerator.utils Define utilidades varias utilizadas por el resto de los paquetes en este proyecto como mtodos para manejo de Strings, Reflection, implementacin de URLClassLoader (para poder incluir libreras java de tipo jar desde el lenguaje), etc. Paquete freelancesoft.codegenerator.writer Contiene la implementacin por default de la interfaz Writer definida en freelancesoft.codegenerator.common.writer. Es el encargado de crear los archivos a generar, escribir sobre los mismos y cerrarlos.

CodeGeneratorLibrary
Este proyecto contiene una herramienta que sirve como ayuda durante la implementacin de las libreras del lenguaje que sean wrapper de libreras java y tambin la implementacin de todas nuestras libreras.

115

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Sobre las libreras que son wrappers de clases Java no las documentaremos en su totalidad, slo mencionaremos lo que implementamos sin explicar su uso. Para ms informacin se puede consultar la api de Java sobre el paquete donde se encuentre la clase para la cul est implementado el wrapper. CodeGeneratorLibraryGenerator Aqu hemos implementado una aplicacin de uso interno que sirve para generar una clase que emula el comportamiento de una del lenguaje Java. En general los objetos del lenguaje implementados como libreras cuentan internamente con un objeto Java, al aplicar un mtodo en el lenguaje este delega la tarea en la instancia del objeto Java.

Si ingresamos el nombre de una clase Java en el campo de texto que aparece arriba a la izquierda y presionamos el botn Load, la aplicacin utilizar la herramienta Javadoc para obtener toda la informacin posible sobre la clase cuyo nombre acabamos de ingresar, Incluyendo los comentarios. Una vez cargados los datos, permite modificar casi cualquier aspecto que pueda ser configurado para generar un wrapper escrito en nuestro lenguaje. Una vez hechas las modificaciones deseadas, se puede presionar el botn save y los datos sern persistidos en una base de datos.

116

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Luego, presionando el botn generar se generan una serie de archivos: Un nico archivo del lenguaje que representa la implementacin de la clase Java, esta puede contener campos, campos estticos, mtodos, mtodos estticos y constructor. Todos tomarn los comentarios originales, pero es posible modificarlos. Un archivo de test escrito en el lenguaje Java, con el esqueleto de todos los mtodos para realizar tests unitarios sobre la clase que se est intentando generar. Cada uno de los mtodos en este archivo es slo un esqueleto que luego debe ser modificado por el desarrollador. Un archivo del lenguaje por cada mtodo de test que ser utilizado por el mismo. Este tambin cuenta slo con un esqueleto y debe ser modificado.

Esta herramienta cuenta con diversos aspectos de configuracin, no la documentaremos por completo ya que la consideramos una herramienta de uso interno y como ayuda al 117

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

desarrollador y no es parte del generador de cdigo. Por esta misma razn, tampoco cuenta con tests unitarios sobre la propia herramienta como s lo hacen el resto de los proyectos. Essentials En la librera Essentials hemos incluido. JavaConverter. Clase base para conversores entre elementos del lenguaje Java y de nuestro propio lenguaje y viceversa. JavaWrapper. Clase base para wrappers del lenguaje Java escritos en nuestro lenguaje. JavaArrayConverter. Clase base para conversores de arreglos del lenguaje Java y de nuestro lenguaje y viceversa. FSLibAutoloader. Autoloader que permite incluir archivos de libreras ante el primer uso de una determinada clase. Conoce ubicaciones de clases especiales y como incluirlas. A su vez usa convenciones sobre nombres para incluir otras. File. Wrapper de la clase Java.io.File, es incluido en esta librera porque es utilizado por FSLibAutoloader para verificar la existencia de archivos. Por este motivo es parte de esta librera y no de Java.Io

File La clase File es un wrapper de la clase java java.io.File. Sobre la misma hemos implementado lo siguiente. Clase File, extiende de Object.

Campos estticos
public static String separator public static String pathSeparator

Mtodos estticos
public static array(File) listRoots() public static File createTempFile(String prefix, String suffix, File directory = null)

Mtodos
public String getName() public String getParent() public File getParentFile() public String getPath() public Boolean isAbsolute() public String getAbsolutePath() public File getAbsoluteFile() public String getCanonicalPath() 118

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

public File getCanonicalFile() public wrap_java_net_URL toURL() public wrap_java_net_URI toURI() public Boolean canRead() public Boolean canWrite() public Boolean exists() public Boolean isDirectory() public Boolean isFile() public Boolean isHidden() public Integer lastModified() public Integer length() public Boolean createNewFile() public Boolean delete() public array(String) list() public array(File) listFiles() public Boolean mkdir() public Boolean mkdirs() public Boolean renameTo(File dest) public Boolean setLastModified(Integer time) public Boolean setReadOnly() public Boolean setWritable(Boolean writable, Boolean ownerOnly = null) public Boolean setReadable(Boolean readable, Boolean ownerOnly = null) public Boolean setExecutable(Boolean executable, Boolean ownerOnly = null) public Boolean canExecute() public Integer compareTo(File pathname) public Boolean equals(Object obj) public Integer hashCode() public String toString()

Constructor / mtodo de creacin


public static File create(String pathname) JavaLang Sobre la librera JavaLang hemos implementado las siguientes clases. Boolean La clase Boolean es un wrapper de la clase java java.lang.Boolean. Sobre la misma hemos implementado lo siguiente. Clase Boolean, extiende de Object.

Campos estticos
public static Boolean TRUE public static Boolean FALSE public static java.lang.Class TYPE 119

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Mtodos estticos
public static Boolean parseBoolean(String s) public static Boolean valueOf(String s) public static String toString(Boolean b) Float La clase Float es un wrapper de la clase java java.lang.Float. Sobre la misma hemos implementado lo siguiente. Clase Float, extiende de Object.

Campos estticos
public static Float POSITIVE_INFINITY public static Float NEGATIVE_INFINITY public static Float NaN public static Float MAX_VALUE public static Float MIN_NORMAL public static Float MIN_VALUE public static Integer MAX_EXPONENT public static Integer MIN_EXPONENT public static Integer SIZE public static java.lang.Class TYPE

Mtodos estticos
public static String toString(Float f) public static Float valueOf(String s) public static Float parseFloat(String s) public static Boolean isNaN(Float v) public static Boolean isInfinite(Float v) public static Integer compare(Float f1, Float f2) Integer La clase Integer es un wrapper de la clase java java.lang.Integer. Sobre la misma hemos implementado lo siguiente. Clase Integer, extiende de Object.

Campos estticos
public static Integer MIN_VALUE public static Integer MAX_VALUE public static java.lang.Class TYPE public static Integer SIZE

Mtodos estticos
public static String toString(Integer i, Integer radix = null) 120

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

public static Integer parseInt(String s, Integer radix = null) public static Integer valueOf(String s, Integer radix = null) public static Integer rotateLeft(Integer i, Integer distance) public static Integer rotateRight(Integer i, Integer distance) public static Integer reverse(Integer i) public static Integer signum(Integer i) public static Integer reverseBytes(Integer i) String La clase String es un wrapper de la clase java java.lang.String. Sobre la misma hemos implementado lo siguiente. Clase String, extiende de Object.

Mtodos estticos
public static String format(String format, array(Object) args) JavaNet Sobre la librera JavaNet hemos implementado las siguientes clases. wrap_java_net_URI La clase wrap_java_net_URI es un wrapper de la clase java java.net.URI. Sobre la misma hemos implementado lo siguiente. Clase wrap_java_net_URI, extiende de Object.

Mtodos
public wrap_java_net_URI parseServerAuthority() public wrap_java_net_URI normalize() public wrap_java_net_URI resolve(String str) public wrap_java_net_URI relativize(wrap_java_net_URI uri) public wrap_java_net_URL toURL() public String getScheme() public Boolean isAbsolute() public Boolean isOpaque() public String getRawSchemeSpecificPart() public String getSchemeSpecificPart() public String getRawAuthority() public String getAuthority() public String getRawUserInfo() public String getUserInfo() public String getHost() public Integer getPort() public String getRawPath() public String getPath() 121

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

public String getRawQuery() public String getQuery() public String getRawFragment() public String getFragment() public Boolean equals(Object ob) public Integer hashCode() public Integer compareTo(wrap_java_net_URI that) public String toString() public String toASCIIString()

Constructor / mtodo de creacin


public static wrap_java_net_URI create(String str) wrap_java_net_URL La clase wrap_java_net_URL es un wrapper de la clase java java.net.URL. Sobre la misma hemos implementado lo siguiente. Clase wrap_java_net_URL, extiende de Object.

Mtodos
public String getQuery() public String getPath() public String getUserInfo() public String getAuthority() public Integer getPort() public Integer getDefaultPort() public String getProtocol() public String getHost() public String getFile() public String getRef() public Boolean equals(Object obj) public Integer hashCode() public Boolean sameFile(wrap_java_net_URL other) public String toString() public String toExternalForm() public wrap_java_net_URI toURI()

Constructor / mtodo de creacin


public static wrap_java_net_URL create(String spec) JavaIo Por el momento, no hay clases implementadas en este proyecto, pero contiene los tests para la clase File implementada en la librera Essentials. Esto es porque nos encontramos con la necesidad de contar con la clase File para implementar el Autoloader, por lo que tuvo que formar parte de la librera Essentials. 122

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

En el futuro, podremos agregar ms implementaciones del paquete java.io a esta librera. JavaxXml Sobre la librera JavaxXml hemos implementado las siguientes clases. wrap_javax_xml_parsers_DocumentBuilder La clase wrap_javax_xml_parsers_DocumentBuilder es un wrapper de la clase java javax.xml.parsers.DocumentBuilder. Sobre la misma hemos implementado lo siguiente. Clase wrap_javax_xml_parsers_DocumentBuilder, extiende de Object.

Mtodos
public Boolean isNamespaceAware() public Boolean isValidating() public Boolean isXIncludeAware() public wrap_org_w3c_dom_Document newDocument() public wrap_org_w3c_dom_Document parseUri(String uri) public wrap_org_w3c_dom_Document parseFile(File f) public void reset() wrap_javax_xml_parsers_DocumentBuilderFactory La clase wrap_javax_xml_parsers_DocumentBuilderFactory es un wrapper de la clase java javax.xml.parsers.DocumentBuilderFactory. Sobre la misma hemos implementado lo siguiente. Clase wrap_javax_xml_parsers_DocumentBuilderFactory, extiende de Object.

Mtodos estticos
public static wrap_javax_xml_parsers_DocumentBuilderFactory newInstance()

Mtodos
public Boolean isCoalescing() public Boolean isIgnoringComments() public Boolean isIgnoringElementContentWhitespace() public Boolean isNamespaceAware() public Boolean isValidating() public Boolean isXIncludeAware() public wrap_javax_xml_parsers_DocumentBuilder newDocumentBuilder() public void setCoalescing(Boolean coalescing) public void setIgnoringComments(Boolean ignoreComments) public void setIgnoringElementContentWhitespace(Boolean whitespace) public void setNamespaceAware(Boolean awareness) public void setXIncludeAware(Boolean state)

123

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

wrap_javax_xml_XMLConstants La clase wrap_javax_xml_XMLConstants es un wrapper de la clase javax.xml.XMLConstants. Sobre la misma hemos implementado lo siguiente. Clase wrap_javax_xml_XMLConstants, extiende de Object. java

Campos estticos
public static String DEFAULT_NS_PREFIX public static String FEATURE_SECURE_PROCESSING public static String NULL_NS_URI public static String RELAXNG_NS_URI public static String W3C_XML_SCHEMA_INSTANCE_NS_URI public static String W3C_XML_SCHEMA_NS_URI public static String W3C_XPATH_DATATYPE_NS_URI public static String XMLNS_ATTRIBUTE public static String XMLNS_ATTRIBUTE_NS_URI public static String XML_DTD_NS_URI public static String XML_NS_PREFIX public static String XML_NS_URI wrap_org_w3c_dom_Attr La clase wrap_org_w3c_dom_Attr es un wrapper de la clase java org.w3c.dom.Attr. Sobre la misma hemos implementado lo siguiente. Clase wrap_org_w3c_dom_Attr, extiende de wrap_org_w3c_dom_Node.

Mtodos
public String getName() public wrap_org_w3c_dom_Element getOwnerElement() public wrap_org_w3c_dom_TypeInfo getSchemaTypeInfo() public Boolean getSpecified() public String getValue() public Boolean isId() public void setValue(String value) wrap_org_w3c_dom_CDATASection La clase wrap_org_w3c_dom_CDATASection es un wrapper de la clase java org.w3c.dom.CDATASection. Sobre la misma hemos implementado lo siguiente. Clase wrap_org_w3c_dom_CDATASection, extiende de wrap_org_w3c_dom_Text. wrap_org_w3c_dom_CharacterData La clase wrap_org_w3c_dom_CharacterData es un wrapper de la clase java org.w3c.dom.CharacterData. Sobre la misma hemos implementado lo siguiente.

124

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Clase wrap_org_w3c_dom_CharacterData, extiende de wrap_org_w3c_dom_Node.

Mtodos
public void appendData(String arg) public void deleteData(Integer offset, Integer count) public String getData() public Integer getLength() public void insertData(Integer offset, String arg) public void replaceData(Integer offset, Integer count, String arg) public void setData(String data) public String substringData(Integer offset, Integer count) wrap_org_w3c_dom_Comment La clase wrap_org_w3c_dom_Comment es un wrapper de la org.w3c.dom.Comment. Sobre la misma hemos implementado lo siguiente. Clase wrap_org_w3c_dom_Comment, extiende de wrap_org_w3c_dom_CharacterData. wrap_org_w3c_dom_Document La clase wrap_org_w3c_dom_Document es un wrapper de la org.w3c.dom.Document. Sobre la misma hemos implementado lo siguiente. clase java clase java

Clase wrap_org_w3c_dom_Document, extiende de wrap_org_w3c_dom_Node.

Mtodos
public array(wrap_org_w3c_dom_Node) getElementsByTagName(String tagname) public String getXmlEncoding() public wrap_org_w3c_dom_Node importNode(wrap_org_w3c_dom_Node importedNode, Boolean deep) public wrap_org_w3c_dom_Comment createComment(String data) public wrap_org_w3c_dom_Text createTextNode(String data) public wrap_org_w3c_dom_DocumentFragment createDocumentFragment() public wrap_org_w3c_dom_Element createElement(String tagName) public wrap_org_w3c_dom_Attr createAttribute(String name) public wrap_org_w3c_dom_Element getElementById(String elementId) public void setStrictErrorChecking(Boolean strictErrorChecking) public wrap_org_w3c_dom_CDATASection createCDATASection(String data) public wrap_org_w3c_dom_Element getDocumentElement() public String getInputEncoding() public array(wrap_org_w3c_dom_Node) getElementsByTagNameNS(String namespaceURI, String localName) public Boolean getXmlStandalone() public String getXmlVersion() public void setXmlVersion(String xmlVersion) public void normalizeDocument() 125

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

public Boolean getStrictErrorChecking() public wrap_org_w3c_dom_Node renameNode(wrap_org_w3c_dom_Node n, String namespaceURI, String qualifiedName) public void setXmlStandalone(Boolean xmlStandalone) public wrap_org_w3c_dom_DOMConfiguration getDomConfig() public wrap_org_w3c_dom_Element createElementNS(String namespaceURI, String qualifiedName) public wrap_org_w3c_dom_Node adoptNode(wrap_org_w3c_dom_Node source) public wrap_org_w3c_dom_DocumentType getDoctype() public wrap_org_w3c_dom_Attr createAttributeNS(String namespaceURI, String qualifiedName) public String getDocumentURI() public void setDocumentURI(String documentURI) wrap_org_w3c_dom_DocumentFragment La clase wrap_org_w3c_dom_DocumentFragment es un wrapper de la clase java org.w3c.dom.DocumentFragment. Sobre la misma hemos implementado lo siguiente. Clase wrap_org_w3c_dom_DocumentFragment, extiende de wrap_org_w3c_dom_Node. wrap_org_w3c_dom_DocumentType La clase wrap_org_w3c_dom_DocumentType es un wrapper de la clase java org.w3c.dom.DocumentType. Sobre la misma hemos implementado lo siguiente. Clase wrap_org_w3c_dom_DocumentType, extiende de wrap_org_w3c_dom_Node.

Mtodos
public String getName() wrap_org_w3c_dom_DOMConfiguration La clase wrap_org_w3c_dom_DOMConfiguration es un wrapper de la clase java org.w3c.dom.DOMConfiguration. Sobre la misma hemos implementado lo siguiente. Clase wrap_org_w3c_dom_DOMConfiguration, extiende de Object.

Mtodos
public Boolean canSetParameter(String name, Object value) public Object getParameter(String name) public array(String) getParameterNames() public void setParameter(String name, Object value) wrap_org_w3c_dom_Element La clase wrap_org_w3c_dom_Element es un wrapper de la org.w3c.dom.Element. Sobre la misma hemos implementado lo siguiente. clase java

126

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Clase wrap_org_w3c_dom_Element, extiende de wrap_org_w3c_dom_Node.

Mtodos
public String getAttribute(String name) public String getAttributeNS(String namespaceURI, String localName) public wrap_org_w3c_dom_Attr getAttributeNode(String name) public wrap_org_w3c_dom_Attr getAttributeNodeNS(String namespaceURI, String localName) public array(wrap_org_w3c_dom_Node) getElementsByTagName(String name) public array(wrap_org_w3c_dom_Node) getElementsByTagNameNS(String namespaceURI, String localName) public wrap_org_w3c_dom_TypeInfo getSchemaTypeInfo() public String getTagName() public Boolean hasAttribute(String name) public Boolean hasAttributeNS(String namespaceURI, String localName) public void removeAttribute(String name) public void removeAttributeNS(String namespaceURI, String localName) public wrap_org_w3c_dom_Attr removeAttributeNode(wrap_org_w3c_dom_Attr oldAttr) public void setAttribute(String name, String value) public void setAttributeNS(String namespaceURI, String qualifiedName, String value) public wrap_org_w3c_dom_Attr setAttributeNode(wrap_org_w3c_dom_Attr newAttr) public wrap_org_w3c_dom_Attr setAttributeNodeNS(wrap_org_w3c_dom_Attr newAttr) public void setIdAttribute(String name, Boolean isId) public void setIdAttributeNS(String namespaceURI, String localName, Boolean isId) public void setIdAttributeNode(wrap_org_w3c_dom_Attr idAttr, Boolean isId) wrap_org_w3c_dom_Node La clase wrap_org_w3c_dom_Node es un wrapper de la clase java org.w3c.dom.Node. Sobre la misma hemos implementado lo siguiente. Clase wrap_org_w3c_dom_Node, extiende de Object.

Campos estticos
public static Integer ATTRIBUTE_NODE public static Integer CDATA_SECTION_NODE public static Integer COMMENT_NODE public static Integer DOCUMENT_FRAGMENT_NODE public static Integer DOCUMENT_NODE public static Integer DOCUMENT_POSITION_CONTAINED_BY public static Integer DOCUMENT_POSITION_CONTAINS public static Integer DOCUMENT_POSITION_DISCONNECTED public static Integer DOCUMENT_POSITION_FOLLOWING public static Integer DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC public static Integer DOCUMENT_POSITION_PRECEDING public static Integer DOCUMENT_TYPE_NODE public static Integer ELEMENT_NODE 127

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

public static Integer ENTITY_NODE public static Integer ENTITY_REFERENCE_NODE public static Integer NOTATION_NODE public static Integer PROCESSING_INSTRUCTION_NODE public static Integer TEXT_NODE

Mtodos
public wrap_org_w3c_dom_Node appendChild(wrap_org_w3c_dom_Node newChild) public wrap_org_w3c_dom_Node cloneNode(Boolean deep) public Integer compareDocumentPosition(wrap_org_w3c_dom_Node other) public array(wrap_org_w3c_dom_Node) getAttributes() public String getBaseURI() public array(wrap_org_w3c_dom_Node) getChildNodes() public wrap_org_w3c_dom_Node getFirstChild() public wrap_org_w3c_dom_Node getLastChild() public String getLocalName() public String getNamespaceURI() public wrap_org_w3c_dom_Node getNextSibling() public String getNodeName() public Integer getNodeType() public String getNodeValue() public wrap_org_w3c_dom_Document getOwnerDocument() public wrap_org_w3c_dom_Node getParentNode() public String getPrefix() public wrap_org_w3c_dom_Node getPreviousSibling() public String getTextContent() public Boolean hasAttributes() public Boolean hasChildNodes() public wrap_org_w3c_dom_Node insertBefore(wrap_org_w3c_dom_Node newChild, wrap_org_w3c_dom_Node refChild) public Boolean isDefaultNamespace(String namespaceURI) public Boolean isEqualNode(wrap_org_w3c_dom_Node arg) public Boolean isSameNode(wrap_org_w3c_dom_Node other) public String lookupNamespaceURI(String prefix) public String lookupPrefix(String namespaceURI) public void normalize() public wrap_org_w3c_dom_Node removeChild(wrap_org_w3c_dom_Node oldChild) public wrap_org_w3c_dom_Node replaceChild(wrap_org_w3c_dom_Node newChild, wrap_org_w3c_dom_Node oldChild) public void setNodeValue(String nodeValue) public void setPrefix(String prefix) public void setTextContent(String textContent) wrap_org_w3c_dom_Text La clase wrap_org_w3c_dom_Text es un wrapper de la clase java org.w3c.dom.Text. Sobre la misma hemos implementado lo siguiente. 128

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Clase wrap_org_w3c_dom_Text, extiende de wrap_org_w3c_dom_CharacterData.

Mtodos
public String getWholeText() public Boolean isElementContentWhitespace() public wrap_org_w3c_dom_Text replaceWholeText(String content) public wrap_org_w3c_dom_Text splitText(Integer offset) wrap_org_w3c_dom_TypeInfo La clase wrap_org_w3c_dom_TypeInfo es un wrapper de la org.w3c.dom.TypeInfo. Sobre la misma hemos implementado lo siguiente. Clase wrap_org_w3c_dom_TypeInfo, extiende de Object. clase java

Campos estticos
public static Integer DERIVATION_EXTENSION public static Integer DERIVATION_LIST public static Integer DERIVATION_RESTRICTION public static Integer DERIVATION_UNION

Mtodos
public String getTypeName() public String getTypeNamespace() public Boolean isDerivedFrom(String typeNamespaceArg, String typeNameArg, Integer derivationMethod) FsTemplating En este proyecto hay dos clases que servirn como base para otras clases desarrolladas como templates. Estas clases son fs_templating_Configurable, que servir para configurar un template de manera sencilla y fs_templating_Template que servir como base para las clases principales de templates. fs_templating_Configurable Supongamos que estamos desarrollando un template, si deseamos que este template sea configurable siguiendo las convenciones, el mismo deber configurarse utilizando un archivo en el directorio a tal fin con el nombre del template. Para que esto pueda hacerse de manera automtica, el template debe extender de la clase fs_templating_Configurable. Esta clase cuenta nicamente con un mtodo. configure
protected function void configure(String filePath) Busca en el directorio de configuracin si es que existe un archivo de nombre filePath, si este existe lo incluye para configurar este objeto.

129

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier Parmetros; filePath nombre del archivo de configuracin a buscar

fs_templating_Template Esta clase es una clase que servir como base para los archivos principales de los templates, extiende de fs_templating_Configurable ya que deseamos que todos nuestros templates sean configurables segn los estndares. Cuenta con varios campos y mtodos, algunos de los mtodos deben ser reimplementados al heredar de esta clase. De este modo, simulamos un mtodo abstracto, este tipo de mtodos cuenta con una implementacin que lo nico que hace es disparar un error irrecuperable para informar que debe ser reimplementado. Los campos y mtodos de esta clase son los siguientes. _module
protected String _module Durante la ejecucin de un template, cada archivo xml que se encuentre en el directorio para utilizar como entrada de la ejecucin se considera un mdulo del sistema a implementar. De este modo durante el desarrollo de un sistema real, podemos ir agregando archivos en este directorio a medida que avanza el proyecto y ejecutar el parser slo sobre un conjunto de mdulos. Con lo cual podremos generar cdigo para diferentes etapas del proyecto. Este campo contendr el nombre del mdulo actual para el que se est generando.

_target
protected String _target Este campo contiene el subdirectorio a donde el template agregar archivos, tomando como base el directorio configurado como target, en el caso en el que no se estn utilizando mdulos. Si no es sobrescrito, contiene un string vaco, con lo cual los archivos se generarn directamente sobre el directorio configurado como target.

_targetIfModule
protected String _targetIfModule Este campo contiene el subdirectorio donde el template agregar archivos, tomando como base el directorio configurado como target, en el caso en el que s se estn utilizando mdulos para desarrollar el sistema. El string ser formateado utilizando el nombre del mdulo actual. Si no es sobrescrito, contiene el string /%s, con lo cual los archivos sern alojados en un subdirectorio con el nombre del mdulo actual dentro del directorio configurado como target.

open
protected function void open(String fileName) Este mtodo encapsula un llamado a la funcin Writer.open para un template especifico. Utilizar los valores de los campos internos de este objeto y el nombre de archivo fileName, para crear un archivo dentro de la carpeta correspondiente de nombre fileName. Parmetros: fileName nombre del archivo en el cul se desea escribir

130

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

close
protected function void close() Encapsula al mtodo Writer.close, en realidad lo nico que hace es invocar al mtodo close de la clase Writer. Se agreg para ser consistente con el mtodo open de esta misma clase.

getId
public function String getId() Este mtodo se considera abstracto y debe ser reimplementado, caso contrario se producir un error irrecuperable al ser invocado. Debe retornar un identificador para este template, este identificador debe ser nico con respecto a todos los templates que se utilizen. En general retorna el nombre del template. Por ejemplo, para el template phpEntities, habr un archivo main.fgl con una clase extendiendo de esta, que retornar "php-entities". Retorna: Un identificador nico

setModule
public function void setModule(String moduleName) Asigna el mdulo para el cual se est ejecutando actualmente. Parmetros; moduleName nombre del mdulo actual

setTarget
public function void setTarget(String target) Asigna el subdirectorio que debe ser utilizado dentro del directorio configurado como target para generar archivos. Parmetros: target subdirectorio a ser utilizado por este template

getTarget
public function String getTarget() Obtiene el subdirectorio que debe ser utilizado dentro del directorio configurado como target para generar archivos. Retorna: subdirectorio a ser utilizado para generar archivos en este template

setTargetIfModule
public function void setTargetIfModule(String target) Asigna el subdirectorio que debe ser utilizado dentro del directorio configurado como target para generar archivos. Para el caso en el que se estn utilizando mdulos durante la generacin. Parmetros: target subdirectorio a ser utilizado por este template

getTargetIfModule
public function String getTargetIfModule() Obtiene el subdirectorio que debe ser utilizado dentro del directorio configurado como target para generar

131

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier archivos. Para el caso en el que se estn utilizando mdulos durante la generacin. Retorna: subdirectorio a ser utilizado para generar archivos en este template

initialize
public function void initialize() Este mtodo se considera abstracto y debe ser reimplementado, caso contrario se producir un error irrecuperable al ser invocado. Ser invocado automticamente y est pensado para que el template se inicialice. En el cuerpo de esta funcin podra, por ejemplo, copiar archivos al directorio target que no son dependientes de las entidades para las cules se est generando cdigo. Por ejemplo si el template es encargado de generar una vista web para un conjunto de entidades, dentro de este mtodo podra copiar archivo comunes como hojas de estilo.

run
public function void run(wrap_org_w3c_dom_Document document) Este mtodo se considera abstracto y debe ser reimplementado, caso contrario se producir un error irrecuperable al ser invocado. Ser invocado automticamente y debe generar el cdigo basndose en el archivo xml que se le pasa como argumento. Parmetros: document documento creado a partir de un archivo xml de entrada para la generacin

Dadas estas clases, contamos con una base para la implementacin de templates. De este modo, cada template se encargar de un trabajo especifico para el cul fue pensado y no debe preocuparse por otras cuestiones.

CodeGeneratorTemplates
En este proyecto se pueden encontrar las implementaciones de los templates que hemos desarrollado. De momento slo encontraremos dos (pero la idea es que vaya creciendo), TemplateManager y PhpEntities. TemplateManager La librera TemplateManager contiene un nico archivo, main.fgl. Este ser el archivo principal con el cual el parser comenzar su ejecucin. Este archivo contiene la definicin de una nica clase, tpl_fs_TemplateManager. Esta clase ser la encargada de administrar todos los templates que haya, tomando los archivos de entrada al generador e invocando a los mtodos abstractos initialize y run definidos en fs_templating_Template. tpl_fs_TemplateManager Esta clase administra todos los dems templates, es la responsable de seleccionar, inicializar y correr templates. El archivo main.fgl es el primer archivo incluido por el parser con su configuracin por default. Bsicamente, una instancia de esta clase incluye templates. Luego, inicializa cada uno de 132

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

ellos mediante una invocacin al mtodo initialize. Despus busca por archivos xml de entrada e invoca al mtodo run para cada uno de los templates, pasando como entrada al documento xml parseado. Esta clase implementa el patrn singleton mediante el mtodo instance. Con lo cual obtendremos la nica instancia del administrador de templates mediante la ejecucin de tpl_fs_TemplateManager.instance(). No haremos una explicacin extensiva de los mtodos implementados, pero s explicaremos como debe hacer un template para quedar registrado con el administrador y as correr, tal vez, junto con otros templates. Para quedar registrado, un template debe ejecutar el mtodo register con una instancia de fs_templating_Template, por ejemplo el template PhpEntities se registra con la siguiente lnea.
tpl_fs_TemplateManager.instance().register(new php_entities_Template());

A partir de ese momento, los mtodos que reimplementa sobre la clase fs_templating_Template sern ejecutados de manera automtica por el administrador de templates. Este administrador puede ser configurado incluyendo un archivo de nombre "templatemanager.fgl" dentro del directorio configurado para buscar archivos de configuracin. Algunos de los aspectos que se pueden configurar son los siguientes. Con los mtodos include y exclude, pueden agregarse identificadores de templates para incluir o excluir directamente. Con los mtodos runInclude y runExclude, los templates sern incluidos, pero se puede evitar la ejecucin del mtodo run. Con los mtodos initInclude e initExclude, puede evitarse la ejecucin del mtodo initialize sobre determinados templates. Por default, el administrador intentar utilizar todos los archivos que encuentre en el directorio de archivos xml de entrada. Con los mtodos moduleInclude y moduleExclude puede cambiarse este comportamiento.

Un archivo tpico de configuracin podra contener lneas como las siguientes.


<%% this.setExclude(array("logging-template-1")); this.setInitInclude(array()); this.setRunInclude(array("logging-template-1")); this.setModulesExclude(array("module1")); this.setRunExclude(array("logging-template-2"));

%%>

En todos estos casos, el administrador considerar todos los templates y mdulos disponibles, salvo que se invoque al mtodo correspondiente de inclusin. Si se ha invocado al mtodo de exclusin, esos templates o mdulos sern excluidos de la lista inicial . 133

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

PhpEntities Este template cuenta con un conjunto de clases y templates escritos en nuestro lenguaje para generar entidades (clases) para el lenguaje PHP. La entrada ser un archivo xml que describir una lista de entidades. Por cada entidad se puede describir una lista de atributos. El template generar una clase por cada entidad en el archivo xml con los atributos descriptos y los mtodos de acceso para esos atributos. El contenido del archivo xml es muy variado y permite generar las clases de una manera diferente. Puede contener descripcin que cambiar sobre la clase generada aspectos como: Nombre de la clase generada. Comentario para la clase generada. En el caso de que no se describa se generarn comentarios default. Atributos, tambin con su comentario y tipo o no, en el caso de que no se describan se tomarn valores default para los comentarios. Mtodos de acceso para cada atributo, que pueden ser generados o no. Para cada mtodo de acceso se pueden describir los comentarios o no. en el caso de que no se describan comentarios, se generarn a comentarios por default.

A su vez, hay aspectos ms globales, es decir que no varan para cada entidad generada si no que se pueden configurar colocando el archivo php-entities.fgl dentro del directorio de configuracin. Ah se pueden configurar aspectos como nombre de una clase base a ser utilizada por todas las entidades generadas, modificacin del directorio en donde se generarn los archivos para las clases, posibilidad de usar el nombre de mdulo para el cul se est generando cdigo como prefijo para el nombre de las clases. Un archivo de configuracin tpica podra contener las siguientes lneas.
<%% this.setBaseClass("BaseEntity"); this.setTargetIfModule("/"); this.setUseModuleAsPrefix(true); %%>

En cuanto a los archivos xml de entrada, son sumamente flexibles. Un ejemplo tpico de su contenido es el siguiente.
<?xml version="1.0" encoding="UTF-8"?> <cg:generation xmlns:cg="http://xml.freelance-soft.com/codegenerator" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xml.freelancesoft.com/codegenerator http://devel.freelance-soft.com/xml/schemas/codegenerator/phpentities.xsd"> <entities> <entity name="DefaultEntity"> <attributes> <attribute name="attr1" /> <attribute name="attr2" /> </attributes> </entity>

134

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
</entities> </cg:generation>

Como puede apreciarse en el ejemplo, existe un esquema para los archivos xml de entrada que define todas las posibilidades vlidas para describir las entidades. Este es de gran utilidad, tanto para validar un archivo de entrada como para conocer cules son todas las posibilidades y puede consultarse para mayor informacin. Si ejecutamos el parser nicamente con este template y sin configuracin adicional, utilizando un archivo de entrada con el contenido del ejemplo anterior, encontraremos en el directorio configurado como target un archivo de nombre DefaultEntity.php con el siguiente contenido.
<?php /** * Represents DefaultEntity. * */ class DefaultEntity { /** * @var mixed */ private $attr1; /** * @var mixed */ private $attr2; /** * Sets attr1. * * @param mixed $attr1 the attr1 to set * */ public function setAttr1($attr1) { $this->attr1 = $attr1; } /** * Gets attr1. * * @return mixed the attr1 * */ public function getAttr1() { return $this->attr1; } /** * Sets attr2. * * @param mixed $attr2 the attr2 to set * */ public function setAttr2($attr2) { $this->attr2 = $attr2; } /** * Gets attr2. *

135

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
* @return mixed the attr2 * */ public function getAttr2() { return $this->attr2; } /** * Constructs DefaultEntity. * * @return DefaultEntity Constructed DefaultEntity * */ public function DefaultEntity() { } } ?>

Utilizando archivos de entrada ms complejos, la generacin ser mucho mas interesante y de gran utilidad durante el desarrollo de un proyecto empresarial basado en el lenguaje PHP.

FSSchemas
En este proyecto hay varios archivos xml. En la raz de los recursos encontraremos el archivo fs_checks.xml. Este archivo define las polticas del estilo de programacin que utilizamos durante el desarrollo. Es el archivo utilizado por CheckStyle para verificar estas polticas al compilar nuestros proyectos. Los archivos que se encuentran en el subdirectorio schemas/codegenerator son los esquemas para los archivos xml de entrada al parser. De momento, slo cuenta con dos archivos: entities.xsd y php-entities.xsd. Al indicar en un archivo xml que alguno de estos es su esquema, cualquier IDE como Eclipse o Netbeans validar el xml y de este modo podemos asegurarnos que los templates reciben la entrada que esperan para generar el cdigo correspondiente. Si ejecutamos la fase install sobre este proyecto.
mvn install

Todos estos archivos sern subidos al servidor utilizando maven antrun. Con este plugin se eliminarn del servidor todos los archivos mediante un comando ftp, luego sern subidos al servidor todos los archivos tambin mediante un comando ftp. La configuracin para lograr esto en el archivo pom.xml del proyecto es la siguiente:
<groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <executions> <execution> <id>ftp-xml-install</id> <phase>install</phase> <configuration> <tasks> <ftp action="del" server="${ftp.xml.server}" remotedir="/var/www/html/xml"

136

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
userid="${ftp.xml.user}" password="${ftp.xml.pass}" depends="yes" verbose="yes"> <fileset> <include name="**" /> </fileset> </ftp> <ftp action="rmdir" server="${ftp.xml.server}" remotedir="/var/www/html/xml" userid="${ftp.xml.user}" password="${ftp.xml.pass}" depends="yes" verbose="yes"> <fileset> <include name="**" /> </fileset> </ftp> <ftp action="send" server="${ftp.xml.server}" remotedir="/var/www/html/xml" userid="${ftp.xml.user}" password="${ftp.xml.pass}" depends="yes" verbose="yes"> <fileset dir="${project.build.outputDirectory}"> <include name="**" /> </fileset> </ftp> </tasks> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions>

entities.xsd Este archivo contiene el esquema padre para cualquier archivo xml que servir como entrada para la generacin. En s, contiene la descripcin de un archivo que identificar las entidades que se desean generar y sus atributos.
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://xml.freelance-soft.com/codegenerator" xmlns:cg="http://xml.freelance-soft.com/codegenerator" elementFormDefault="unqualified"> <xsd:element name="generation"> <xsd:annotation> <xsd:documentation>Root node of an xml input file.</xsd:documentation> </xsd:annotation> <xsd:complexType> <xsd:sequence> <xsd:element name="entities"> <xsd:annotation> <xsd:documentation>List of entities that should be generated by freelancesoft generation language.</xsd:documentation> </xsd:annotation> <xsd:complexType> <xsd:sequence> <xsd:element name="entity" type="cg:entityType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:complexType name="entityType"> <xsd:annotation> <xsd:documentation>This node represents a single entity, a list of entities will be passed in to defined templates and then themplates will generate code.</xsd:documentation> </xsd:annotation> <xsd:sequence> <xsd:element name="attributes" minOccurs="0" maxOccurs="unbounded"> <xsd:annotation> <xsd:documentation>List of attributes that belongs to an entity.</xsd:documentation>

137

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
</xsd:annotation> <xsd:complexType> <xsd:sequence> <xsd:element name="attribute" type="cg:attributeType" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:sequence> <xsd:attribute name="name" type="xsd:string" use="required"/> </xsd:complexType> <xsd:complexType name="attributeType"> <xsd:annotation> <xsd:documentation>An attribute of an entity. It has only a name, but each new schema could add their own properties and new attributes to this type.</xsd:documentation> </xsd:annotation> <xsd:attribute name="name" type="xsd:string" use="required"/> </xsd:complexType> </xsd:schema>

php-entities.xsd Este esquema extiende al anterior agregando todos las posibilidades para un documento de entrada para el template php-entities.
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://xml.freelance-soft.com/codegenerator" xmlns:cg="http://xml.freelancesoft.com/codegenerator" elementFormDefault="unqualified"> <xsd:redefine schemaLocation="${schemas.basedir}/codegenerator/entities.xsd"> <xsd:complexType name="attributeType"> <xsd:complexContent> <xsd:extension base="cg:attributeType"> <xsd:sequence> <xsd:element name="comment" minOccurs="0" type="xsd:string"> <xsd:annotation> <xsd:documentation> Custom comment, if it is present this will be the attribute comment. </xsd:documentation> </xsd:annotation> </xsd:element> <xsd:element name="setter" minOccurs="0" type="cg:accessorType"> <xsd:annotation> <xsd:documentation> Setter method for current attribute. </xsd:documentation> </xsd:annotation> </xsd:element> <xsd:element name="getter" minOccurs="0" type="cg:accessorType"> <xsd:annotation> <xsd:documentation> Getter method for current attribute. </xsd:documentation> </xsd:annotation> </xsd:element> </xsd:sequence> <xsd:attribute name="modifier" type="cg:modifierType" default="private" use="optional"> <xsd:annotation> <xsd:documentation> Change modifier used in internal attribute of the class. By default it is private. </xsd:documentation>

138

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
</xsd:annotation> </xsd:attribute> <xsd:attribute name="type" type="xsd:string" default="mixed" use="optional"> <xsd:annotation> <xsd:documentation> This type is used in comments. In this way you can use code assistance. Default is mixed. </xsd:documentation> </xsd:annotation> </xsd:attribute> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="entityType"> <xsd:complexContent> <xsd:extension base="cg:entityType"> <xsd:sequence> <xsd:element name="comment" minOccurs="0" type="xsd:string"> <xsd:annotation> <xsd:documentation> Custom comment, if it is present this will be the class comment. </xsd:documentation> </xsd:annotation> </xsd:element> <xsd:element name="constructor" minOccurs="0"> <xsd:annotation> <xsd:documentation> Constructor of this entity. </xsd:documentation> </xsd:annotation> <xsd:complexType> <xsd:sequence> <xsd:element name="comment" minOccurs="0" type="xsd:string"> <xsd:annotation> <xsd:documentation> Custom comment, if it is present this will be the class comment. </xsd:documentation> </xsd:annotation> </xsd:element> </xsd:sequence> <xsd:attribute name="generate" type="xsd:boolean" default="true" use="optional"> <xsd:annotation> <xsd:documentation> Determines if a constructor should be generated. By defalt it is true. </xsd:documentation> </xsd:annotation> </xsd:attribute> <xsd:attribute name="magic" type="xsd:boolean" default="false" use="optional"> <xsd:annotation> <xsd:documentation> Determines if a should be generated with __construct name. </xsd:documentation> </xsd:annotation> </xsd:attribute> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:redefine> <xsd:complexType name="accessorType" > <xsd:annotation> <xsd:documentation> Describes an accesor, ie a setter or getter method.

139

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
</xsd:documentation> </xsd:annotation> <xsd:sequence> <xsd:element name="comment" minOccurs="0" type="xsd:string"> <xsd:annotation> <xsd:documentation> Custom comment, if it is present this will be the class comment. </xsd:documentation> </xsd:annotation> </xsd:element> </xsd:sequence> <xsd:attribute name="generate" type="xsd:boolean" default="true" use="optional"> <xsd:annotation> <xsd:documentation> Determines if an accessor should be generated. By default it is true. </xsd:documentation> </xsd:annotation> </xsd:attribute> <xsd:attribute name="modifier" type="cg:modifierType" default="public" use="optional"> <xsd:annotation> <xsd:documentation> Change modifier used in accessor, ie setter or getter. Default is public. </xsd:documentation> </xsd:annotation> </xsd:attribute> </xsd:complexType> <xsd:simpleType name="modifierType"> <xsd:annotation> <xsd:documentation>Possible values for a modifier.</xsd:documentation> </xsd:annotation> <xsd:restriction base="xsd:string"> <xsd:enumeration value="private"> <xsd:annotation> <xsd:documentation>private value.</xsd:documentation> </xsd:annotation> </xsd:enumeration> <xsd:enumeration value="protected"> <xsd:annotation> <xsd:documentation>protected value.</xsd:documentation> </xsd:annotation> </xsd:enumeration> <xsd:enumeration value="public"> <xsd:annotation> <xsd:documentation>public value.</xsd:documentation> </xsd:annotation> </xsd:enumeration> <xsd:whiteSpace value="collapse" /> </xsd:restriction> </xsd:simpleType> </xsd:schema>

Futuros templates que se dediquen a generar cdigo para un sistema basado en el lenguaje PHP, podrn extender este esquema con las propiedades que deseen para generar otro tipo de cdigo, como por ejemplo la bloques de cdigo dedicado a persistir las entidades contra una base de datos o a vistas web para administrar las altas, bajas y modificaciones de entidades.

140

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

FscodeGeneratorProjectType (Plugin para Netbeans IDE)


Con el fin de tener una interfaz amigable para utilizar el framework de generacin de cdigo realizamos una extensin de un IDE existente y popular: Netbeans. El IDE Netbeans posee una arquitectura pensada para ser extendida mediante plugins utilizando una API que est organizada en varios mdulos diferentes, cada uno implementando las distintas reas que comprende el desarrollo de un IDE moderno. As mismo el IDE es un proyecto derivado de una estructura an mayor: Netbeans Platform, por lo que tambin se pueden desarrollar aplicaciones para mltiples propsitos utilizando toda la plataforma de Netbeans. En nuestro caso, para nuestra primera versin del plugin debamos extender al mismo de forma tal de proveer soporte para las siguientes funciones: Tipo de proyecto: se debe dar soporte para un nuevo tipo de proyecto, en nuestro caso un proyecto de generacin de cdigo. Tipos de archivo: nuestro framework funciona con archivos de textos, entre los cuales tenemos archivos XML para definir el modelo (ya soportado por Netbeans mediante otros plugins) y el archivo fuente del lenguaje de generacin: FGL, para el cul tuvimos que definir la extensin *.fgl y dar soporte a la misma. Soporte del lenguaje: en este caso el IDE puede extenderse para que el editor de nuestro lenguaje resalte el cdigo fuente, realice chequeos de sintaxis preinterpretacin, sugerencia de cdigo, etc. En la primera versin solo tendr soporte para resaltar el cdigo y mostrar los errores de sintxis o ejecucin una vez que se invoca al intrprete. Acciones del framework: adems de poder editar los archivos fuentes y los XML del modelo, deben proveerse las acciones para crear/eliminar dichos archivos, invocar el intrprete para generar el cdigo resultante, etc. Dichas funciones se incorporan a las acciones del IDE y se insertan en los iconos y elementos del men de forma correspondiente.

El resultado de extender el IDE genera dos tipos de entregables: 1. Distribucin completa (un IDE nuevo) formado por el IDE Netbeans base y el soporte para nuestro framework. 2. Un plugin capaz de ser instalado en una instancia de Netbeans existente. La gran ventaja de este enfoque es que puede ser incorporado al IDE que el desarrollador utiliza a diario (con todos los plugins y soporte de lenguajes con los cuales trabaja) y utilizar el framework de generacin de cdigo en el mismo entorno, teniendo la posibilidad de generar el cdigo resultante en los directorios del proyecto en el que est trabajando.

141

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Uso del parser


Existen dos formas de utilizar el parser: desde lnea de comandos, con la posibilidad de pasar parmetros de configuracin, o como librera para el lenguaje java. Este ltimo enfoque es el utilizado por el plugin desarrollado para la extensin del IDE Netbeans. Veamos en detalle ambas posibilidades:

Uso del parser por lnea de comandos


Para poder utilizar el parser por lnea de comandos se ha creado un sub-proyecto denominado Code Generator Standalone. Este proyecto incluye una instancia del generador de cdigo empaquetada como Jar, las libreras del lenguaje FGL, algunos wrappers de Java bsicos para el desarrollo de templates y una librera java para la ejecucin por lnea de comandos. Para la invocacin se utiliza el Jar CodeGenerator-*.jar, por ejemplo:
$ java -jar CodeGenerator-1.0-SNAPSHOT.jar

Pasando el parmetro --help nos muestra la ayuda completa:


$ java -jar CodeGenerator-1.0-SNAPSHOT.jar --help usage: CodeGenerator.jar [-base <directory>] [-C <key=value>] [-ConfigPath <directory>] [-e] [-FsLibPath <directory>] [-help] [-InputPath <directory>] [-TargetPath <directory>] [-TemplateMainFile <name>] [-TemplatesPath <directory>] -base <directory> A directory to be used as base directory, default values are based on this option. If you don't use this option, all other configuration options (FsLibPath, ConfigPath, TemplatesPath, InputPath, TargetPath) are required. Default value is the current directory. -C <key=value> Set other configuration using freelancesoft.codegenerator.common.configura tion.set method. -ConfigPath <directory> Path in wich the parser should search for configuration files. Default value is "<base>/config" -e Pring excpetion stack trace when an error produced by any exception occrs. -FsLibPath <directory> Path in wich the parser should search for Freelance Soft library classes. Default value is "<base>/lib" -help Print this message. -InputPath <directory> Path in wich the parser should search for input files. Default value is "<base>/input" -TargetPath <directory> Path in wich the parser should put generated files. Default value is "<base>/target" -TemplateMainFile <name> Default name to be used as main class for templates. Default value is "main.fgl" -TemplatesPath <directory> Path in wich the parser should search for template files. Default value is "<base>/tpl"

Con el parmetro -base podemos indicarle el directorio donde se encuentra todo el escenario de trabajo, sin tener que indicar el input, target, etc. Tal directorio debe contar con los siguientes subdirectorios: 142

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

config: Aqu deben estar los archivos de configuracin del generador de cdigo, tal directorio puede estar vaco, en ese caso se utiliza la configuracin por defecto. input: Se encuentra la entrada del generador (archivos *.xml), por ejemplo la representacin de las entidades de negocio de la aplicacin. lib: Incluye las libreras para el lenguaje FGL y los wrappers de Java. tpl: Aqu debe estar todo el cdigo FGL de la plantilla utilizada. target: Este es el directorio por defecto en donde se generar la salida del parser, correspondiente a la entrada incluida en input y la plantilla del directorio tpl. rbol de directorios del ejemplo incluido php-entities:
Ex1/ config input university.xml lib fs templating Configurable.fgl Template.fgl FSLibAutoloader.fgl java wrap java io File.fgl lang Boolean.fgl Float.fgl Integer.fgl String.fgl net URI.fgl URL.fgl JavaArrayConverter.fgl JavaConverter.fgl JavaWrapper.fgl javax xml parsers DocumentBuilderFactory.fgl DocumentBuilder.fgl XMLConstants.fgl org w3c dom Attr.fgl CDATASection.fgl CharacterData.fgl Comment.fgl Converters.fgl Document.fgl DocumentFragment.fgl DocumentType.fgl DOMConfiguration.fgl Element.fgl Node.fgl Text.fgl TypeInfo.fgl target classes university Person.php

143

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
Student.php Teacher.php tpl main.fgl php-entities classes Accessor.fgl AccessorType.fgl Attribute.fgl Autoloader.fgl Constructor.fgl Entity.fgl Mapper.fgl main.fgl tpls attribute.fgl class.fgl constructor.fgl getter.fgl setter.fgl

Uso del parser como librera


Para utilizar la librera desde el lenguaje java lo primero que hay que hacer es crear una instancia de LanguageParser.
// Direccin absoluta del archivo principal sobre el cual se ejecutar el parser, // Si utilizamos los templates desarrollados, apuntar a la locacin del archivo main.fgl // de TemplateManager testFile = ""; // Creacin de la instancia del parser LanguageParser parser = new CodeGeneratorParser(new java.io.FileInputStream(testFile), testFile);

Antes de cada ejecucin, se recomienda ejecutar el mtodo reInit con el cual se reinicializan todos los contextos y configuraciones de ejecuciones anteriores.
// Reinicializar contextos y configuraciones parser.reInit();

Luego se deben asignar todos los valores de configuracin.


// Direccin absoluta donde el parser buscar archivos de librera ConfigurationManager.current().setFsLibPath(getFSLibPath()); // Direccin absoluta donde el parser buscar archivos de entrada ConfigurationManager.current().setInputPath(scenario.getInputPath()); // Direccin absoluta donde sern generados los archivos ConfigurationManager.current().setTargetPath(scenario.getTargetPath()); // Direccin abosoluta donde se buscarn archivos de configuracin para los templates ConfigurationManager.current().setConfigPath(scenario.getConfigPath()); // Direccin absoluta donde se buscarn los templates ConfigurationManager.current().setTemplatesPath(scenario.getTplPath());

Una vez configurado, debemos disparar la ejecucin del parser.


try { // Parsea el primer archivo formando el rbol que luego debe interpretarse parser.parseUnit(); // Interpreta el rbol generado con la sentencia anterior parser.interpret();

144

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
} catch(Throwable ex) { // Hacer algo con el error. // Si el Logger est configurado para disparar excepciones ante errores irrecuperables, // aqu se puede inspeccionar para informar de los errores. }

Una vez finalizada la ejecucin se pueden inspeccionar los logs de error.


// Warnings producidos durante la ejecucin Set<Record> warnings = LogManager.current().getRecords(Record.Type.WARNING); // Errores producidos durante la ejecucin Set<Record> errors = LogManager.current().getRecords(Record.Type.ERROR); // Errores irrecuperables producidos durante la ejecucin, // el Logger puede estar configurado para disparar excepciones ante errores de este tipo Set<Record> irrecuperableErrors = LogManager.current().getRecords(Record.Type.IRRECUPERABLE_ERROR);

Plan de configuracin
Configuracin del servidor
A continuacin se describen los pasos necesarios para configurar el servidor de desarrollo. Las pruebas se han hecho localmente en Ubuntu 10.04, y en CentOs en lo que respecta a un servidor contratado. Se adjunta con la entrega una carpeta con todo el software necesario para lograr configurar el servidor. Host Este paso debe ser aplicado nicamente en el caso de que se desee configurar todo el entorno de manera local. 1. Ejecutar.
$ sudo nano /etc/hosts

2. Agregar la siguiente lnea.


127.0.0.1 devel.freelance-soft.com

3. Verificar que el mapeo se hizo correctamente.


ping devel.freelance-soft.com

Tomcat Tomcat es una implementacin de las tecnologas Java Servlet y JavaServer Pages. Es utilizado como contenedor para varias de la aplicaciones que se utilizan durante el proceso de desarrollo. A continuacin describiremos como instalarlo en el servidor. 145

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

1. Instalar tomcat.
$ sudo apt-get install tomcat6*

2. Agregar usuarios para administrador y manager. Primero ejecutar.


$ sudo chgrp -R tomcat6 /etc/tomcat6 $ sudo chmod -R g+w /etc/tomcat6 $ sudo gedit /etc/tomcat6/tomcat-users.xml

Y agregar las siguientes lneas.


< role rolename = "admin" /> < role rolename = "manager" /> < user username = "admin" password = "admin123" roles = "admin,manager" />

4. El generador de cdigo utiliza esquemas xml (archivos xsd) para definir el formato de los archivos de entrada. A su vez, el plugin checkstyle utiliza un archivo de configuracin en el que se definen las polticas de estilo de programacin que se quieran chequear. Estos archivos deben estar todos en lnea para poder ser utilizados en la generacin o chequeo. Para contar con un directorio en el servidor donde se puedan publicar los archivos debemos ejecutar:
$ $ $ $ mkdir chgrp chmod chmod /var/www/html/xml -R apacche /var/www/html/xml/ -R u=rwx,g=rwx,o=r /var/www/html/xml/ -R g+s /var/www/html/xml/

Los archivos en general se suben por ftp, as que se debe dar permisos a los usuarios que deben subir estos archivos. Por ejemplo, para el usuario user se debera ejecutar.
$ sudo usermod -a -G apache user

Java de Sun 1. Para instalar Java se debe ejecutar.


$ sudo add-apt-repository ppa:ferramroberto/java $ sudo apt-get update $ sudo apt-get install sun-java6-jdk sun-java6-jre sun-java6-plugin sun-java6-fonts

2. Actualizar para que las alternativas no usen la versin libre, el archivo se adjunta con la entrega
$ sudo /home/tesis/Desktop/EntornoCodeGenerator/SunJava/updatealternatives.sh

CVS La herramienta que se utilizado como repositorio y control de versiones para el cdigo es CVS, a continuacin se describen los pasos para instalarlo en el servidor. Se toma como base el sistema operativo Ubuntu y se marcan las diferencias con el sistema operativo CentOS en rojo. 1. Para instalar cvs ejecutar. 146

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
$ sudo apt-get install cvs

2. Luego es necesario instalar el demonio, para que est constantemente escuchando por solicitudes, para lo cual hay que ejecutar.
$ sudo apt-get install xinetd $ sudo gedit /etc/xinetd.d/cvspserver

Y agregar.
service cvspserver { port = 2401 socket_type = stream protocol = tcp user = root wait = no type = UNLISTED server = /usr/bin/cvs server_args = -f --allow-root /var/lib/cvs pserver disable = no }

Despus reiniciar el servicio xinetd.


$ sudo /etc/init.d/xinetd restart

3. Para ver si el servicio est corriendo correctamente se puede ejecutar.


$ sudo netstat -tap | grep cvs

4. Hay que crear un usuario administrador y darle todos los permisos necesarios sobre el directorio cvsroot.
$ sudo adduser -system cvsadmin $ sudo adduser -system cvsadmin $ sudo passwd cvsadmin cvsadmin123 $ sudo addgroup cvs $ groupadd cvs $ sudo usermod -g cvs cvsadmin $ sudo mkdir /var/lib/cvs $ sudo mkdir /var/lib/cvs/CVSROOT $ sudo chown -R cvsadmin:cvs /var/lib/cvs $ sudo chmod -R u=rwx,g=rwx,o= /var/lib/cvs

As definido el grupo de un archivo sobre el cual se hace commit ser el grupo principal del usuario que ejecut dicho commit. Para mantener el grupo cvs se debe ejecutar el siguiente comando.
$ sudo chmod -R g+s /var/lib/cvs/

5. Cada vez que se sume un desarrollador, se le deben dar los permisos para que pueda modificar el cdigo. Para ello, asumiendo que el nombre de usuario es user, se debe ejecutar.
$ sudo usermod -a -G cvs martin

6. Hay que generar .cvspass en /home/<usuario>/.cvspass. Asumiendo que el usuario 147

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

es cvsadmin y el pass cvsadmin123.


$ cvs -d :pserver:cvsadmin:cvsadmin123@localhost:2401/var/lib/cvs login $ cp /home/tesis/.cvspass /home/tesis/.cvspasstomcat $ sudo chown tomcat6 /home/tesis/.cvspasstomcat $ su tomcat $ cvs -d :pserver:cvsadmin:MacuServerFS321@localhost:2401/var/lib/cvs login En este caso, se genera en /usr/share/tomcat6/ por lo que hay que copiarlo desde all.

7. Aadir los proyectos desde el IDE preferido o lnea de comandos. Nota: El siguiente comando puede ser til si necesitamos desvincular a CVS archivos para subirlos a un nuevo server.
$ find . -name CVS -print0 | xargs -0 rm -rf

Archiva Archiva es el software seleccionado como repositorio maven. A continuacin se describen los pasos para instalar este software en el servidor. Primero, aclaremos que tomamos como base el sistema operativo Ubuntu. Las principales diferencias con el sistema CentOS son: Es conveniente crear symlink en /var/lib/tomcat6 a conf. De este modo se minimizan las diferencias. La variable ${catalina.base} est ubicada en /usr/share/tomcat6/, ah debe ser creada la carpeta carpeta archiva y no en /var/lib/tomcat6/archiva.

1. Descargar la ltima versin disponible del archivo war desde el sitio oficial de apache: http://archiva.apache.org/ 2. Si se desea tener la posibilidad de subir archivos de gran tamao, se debe cambiar el tamao mximo de archivo en el war /WEB-INF/classes/struts.properties antes de continuar. 3. Para instalar archiva.
$ sudo mkdir /var/lib/tomcat6/archiva $ sudo cp /home/tesis/Desktop/EntornoCodeGenerator/Archiva/apache-archiva-1.3.5.war /var/lib/tomcat6/archiva/ $ sudo mkdir /var/lib/tomcat6/archiva/database $ sudo mkdir /var/lib/tomcat6/archiva/repositories $ sudo mkdir /var/lib/tomcat6/archiva/repositories/internal $ sudo cp -R /home/tesis/Desktop/EntornoCodeGenerator/Archiva/internal/* /var/lib/tomcat6/archiva/repositories/internal/ $ sudo chown -R tomcat6:tomcat6 /var/lib/tomcat6/archiva/database/ /var/lib/tomcat6/archiva/repositories/ $ sudo cp -R /home/tesis/Desktop/EntornoCodeGenerator/Archiva/lib/* /usr/share/tomcat6/lib $ sudo gedit /var/lib/tomcat6/conf/Catalina/localhost/archiva.xml

Y agregar el siguiente contenido.


< Context path = " /archiva" docBase="${catalina.base}/archiva/apache-archiva 1.3.5.war">

148

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
< Resource name = "jdbc/users" auth = "Container" type = "javax.sql.DataSource" username = "sa" password = "" driverClassName = "org.apache.derby.jdbc.EmbeddedDriver" url = "jdbc:derby:${catalina.base}/archiva/database/users;create=true" /> < Resource name = "jdbc/archiva" auth = "Container" type = "javax.sql.DataSource" username = "sa" password = "" driverClassName = "org.apache.derby.jdbc.EmbeddedDriver" url = "jdbc:derby:${catalina.base}/archiva/database/archiva;create=true" /> < Resource name = "mail/Session" auth = "Container" type = "javax.mail.Session" mail.smtp.host = "localhost" /> </ Context >

Luego ejecutar.
$ sudo gedit /var/lib/tomcat6/conf/catalina.properties

Y agregar.
# Archiva appserver.home=${catalina.home} appserver.base=${catalina.base}

Para que tome los cambios se debe reiniciar el servicio. 4. Una vez instalado archiva, ingresaremos al sitio y crearemos un usuario administrador.

5. Agregar el repositorio para extensiones NetBeans.

149

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

6. Y luego el conector para el repositorio.

7. En la solapa de repositorios actualizar a.


/var/lib/tomcat6/archiva/repositories/internal

150

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier
/var/lib/tomcat6/archiva/repositories/snapshots

y reescanear los repositorios, para que tome las libreras que copiamos. 8. Actualizar las bases de datos para que tomen las libreras copiadas en el repositorio internal.

Para seguridad archiva usa Redback, para evitar que los passwords expiren ejecutar.
nano /usr/share/tomcat6/.m2/security.properties

Y agregar la siguiente lnea.


security.policy.password.expiration.enabled=false

Para mayor informacin sobre la configuracin se seguridad referirse al archivo default de propiedades de Redback: http://svn.codehaus.org/redback/redback/trunk/redbackconfiguration/src/main/resources/org/codehaus/plexus/redback/config-defaults.properties 151

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Maven A continuacin, se describe como instalar la herramienta Maven en el servidor. Se toma como base el sistema operativo Ubuntu y se marcan en rojo las diferencias con el sistema operativo CentOS. 1. Instalar Maven.
$ sudo apt-get install maven2

En CentOS es un poco ms complejo, ya que no se cuenta con la versin requerida de maven en los repositorios. Por lo que debemos ejecutar.
wget http://apache.xmundo.com.ar//maven/binaries/apache-maven-2.2.1-bin.tar.gz tar -xzvf apache-maven-2.2.1-bin.tar.gz mv apache-maven-2.2.1 /usr/local/apache-maven-2.2.1 cd /usr/local/ ln -s apache-maven-2.2.1/ maven nano /etc/bashrc

Y agregar las siguientes lneas.


MAVEN_HOME=/usr/local/maven export MAVEN_HOME PATH=$PATH:$MAVEN_HOME/bin JAVA_HOME=/usr/java/default export JAVA_HOME

2. Luego debemos crear un repositorio local, para lo cual debemos ejecutar.


$ sudo mkdir /usr/share/tomcat6/.m2 $ sudo chown -R tomcat6:tomcat6 /usr/share/tomcat6/.m2/ $ sudo chmod -R u=rwx,g=rwx,o= /usr/share/tomcat6/.m2/

3. Y tenemos que configurar maven para que utilice nicamente a archiva como repositorio. De lo contrario ir a buscar paquetes a los repositorios oficiales. De este modo mantenemos en el server una cach con todos los paquetes que usemos.
$ sudo gedit /etc/maven2/settings.xml $ nano /usr/local/maven/conf/settings.xml

Agregar como repositorio local.


< localRepository >/usr/share/tomcat6/.m2</ localRepository >

Agregar como mirrors.


< mirror > < id > archiva.default </ id > < url > http://localhost:8080/archiva/repository/internal/ </ url > < mirrorOf > * </ mirrorOf > </ mirror > < mirror > < id > archiva.apache.snapshots </ id > < url > http://localhost :8080/archiva/repository/snapshots/ </ url > < mirrorOf > apache.snapshots </ mirrorOf > </ mirror >

152

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Suponiendo que el usuario administrador ser admin y su pass admin123. Agregar los servers.
< server > < id > internal </ id > < username > admin </ username > < password > admin123 </ password > </ server > < server > < id > snapshots </ id > < username > admin </ username > < password > admin123 </ password > </ server >

4. En entorno empresarial, no deseamos que cualquier persona pueda ver y descargar nuestros paquetes. Para esto, debemos quitarle los permisos de lectura al usuario guest. Si se hace esto, debemos indicarle a maven con qu usuario autenticarse con archiva agregando las siguientes lneas.
< server > < id > archiva.default </ id > < username > admin </ username > < password > ******* </ password > </ server > < server > < id > archiva.apache.snapshots </ id > < username > admin </ username > < password > MacuServerFS321 </ password > </ server >

Jenkins (o Hudson) Esta herramienta la hemos probado ampliamente de manera local. De momento est desactivada en el servidor ya que requiere de una cantidad de memoria considerable para ejecutar builds. Los pasos para instalarla son los siguientes. 1. Descargar el archivo de tipo war desde el sitio oficial http://jenkins-ci.org/. 2. Renombrarlo a jenkins.war. 3. Desplegarlo en http://devel.freelance-soft.com:8080/manager/html. (copiarlo en /var/lib/tomcat6/webapps/ y reiniciar tomcat es quivalente).

153

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

4. Agregar usuario para jenkins, para ello hay que ejecutar:


$ sudo chgrp -R tomcat6 /usr/share/tomcat6 $ sudo chmod -R g+w /usr/share/tomcat6/ $ sudo gedit /etc/tomcat6/tomcat-users.xml

Y agregar:
< user username = "hudson-admin" password = "secret" roles = "admin" />

Luego reiniciar tomcat:


$ sudo service tomcat6 restart

5. Ingresar a http://devel.freelance-soft.com:8080/jenkins. Con esto se crea e inicializa automticamente el sitio. 6. Para un entorno en un servidor pblico sera conveniente activar seguridad. De momento este paso no se describir porque no tenemos la posibilidad de utilizarlo de este modo actualmente. 7. Aadir maven a jenkins:

8. Aadir CVS a jenkins:

154

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

9. Configurar Java en jenkins:

10. Agregar los jobs, Asumiendo que tenemos los jobs definidos copiados en /home/tesis/Desktop/EntornoCodeGenerator/hudson/, debemos ejecutar:
$ sudo cp -R /home/tesis/Desktop/EntornoCodeGenerator/hudson/jobs/* /usr/share/tomcat6/.jenkins/jobs/ $ sudo chown -R tomcat6:tomcat6 /usr/share/tomcat6/.jenkins/jobs/ $ sudo chmod -R g+w /usr/share/tomcat6/.jenkins/jobs/ $ sudo service tomcat6 restart

11. Una vez instalado y configurado jenkins, deberamos correr el build nocturno para asegurarnos de que todos los pasos se han ejecutado correctamente.

Configuracin del cliente


A continuacin se describen los pasos necesarios para configurar el cliente de desarrollo, es decir una mquina para que un desarrollador pueda trabajar en el proyecto. Las pruebas se han hecho localmente en Ubuntu 10.04 y en Windows XP. Java de Sun Se deben seguir los mismos pasos que la seccin para la configuracin del servidor. JavaCC 1. Para instalar JavaCC en Ubuntu simplemente debemos ejecutar:
$ sudo apt-get install javacc

Maven 1. Para instalar maven, seguir las instrucciones de la instalacin en el servidor. La 155

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

nica diferencia es que debemos apuntar los repositorios de archiva a devel.freelance-soft.com. 2. Si el desarrollador debe contar con la posibilidad de correr los builds que suben esquemas o archivo de configuracin para chequeo de estilos, entonces debe ejecutar:
$ sudo gedit /etc/maven2/settings.xml

Y, suponiendo que el nombre de usuario es user, agregar el siguiente contenido:


< profile > < id > fs-default </ id > < activation > < activeByDefault > true </ activeByDefault > </ activation > < properties > < f tp.xml.user > user </ ftp.xml.user > < ftp.xml.pass > ***** </ ftp.xml.pass > </ properties > </ profile >

Por supuesto, este usuario debe contar con los permisos necesarios para subir archivos por ftp al directorio. NetBeans Como IDE hemos seleccionado NetBeans. La instalacin es muy sencilla, basndonos en una distro Ubuntu: 1. Descargar el instalador para linux desde http://netbeans.org/downloads/index.html. 2. Marcar el archivo como ejectuable. 3. Ejecutar el archivo. 4. Simplemente seguir las instrucciones. 5. Para lograr que el plugin de maven busque las dependencias desde nuestro servidor hay que configurarlo. Lo primero es configurar el repositorio internal apuntando a http://devel.freelance-soft.com:8080/archiva/repository/internal.

156

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

6. Repetir el paso 5 para el repositorio de snapshots, que es donde se publicarn las libreras en desarrollo. 7. Estos ltimos dos pasos son slo para buscar dependencias, maven terminar usando archiva como mirror por configuracin. 8. Para que utilice nuestra instalacin de maven en lugar de la que viene incorporada con NetBeans debe ser configurado.

Configuracin de un cliente windows


A continuacin, explicaremos la configuracin de un cliente windows, slo hasta llegar a contar con las herramientas necesarias para llegar a ejecutar maven sobre todos los proyectos. Se asume que no hay grandes diferencias para el resto de las herramientas. Para algunas incluso es ms sencillo y es suficiente con ejecutar un wizard de instalacin, se remite a las pginas de descarga de las herramientas para mayor detalle. Para la descripcin de los pasos se asume el sistema operativo Windows XP de 32 bits. En muchos caso es necesario agregar o modificar variables de entorno, para esto se debe: 1. Ir a las propiedades del sistema. 2. Hacer click sobre la pestaa Opciones avanzadas. 3. Hacer click sobre el botn Variables de entorno.

157

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

CVS Para instalar CVS en windows seguir los siguientes pasos: 1. Descargar cvs desde http://ftp.gnu.org/non-gnu/cvs/binary/stable/x86-woe/ . 2. Descomprimir en C:\Archivos de programa\CVS. 3. Agregar la ruta a la variable de entorno Path. 4. Luego debemos descargar los proyectos, para lo cual debemos ejecutar.
cd c:\ mkdir CodeGeneratorProjects cd CodeGeneratorProjects cvs -d :pserver:{user}:{pass}@devel.freelance-soft.com:2401/var/lib/cvs/ login cvs -d :pserver:@devel.freelance-soft.com:2401/var/lib/cvs/ checkout CodeGeneratorPoms cvs -d :pserver:@devel.freelance-soft.com:2401/var/lib/cvs/ checkout CodeGeneratorModules cvs -d :pserver:@devel.freelance-soft.com:2401/var/lib/cvs/ checkout CodeGeneratorLibrary cvs -d :pserver:@devel.freelance-soft.com:2401/var/lib/cvs/ checkout CodeGeneratorTemplates cvs -d :pserver:@devel.freelance-soft.com:2401/var/lib/cvs/ checkout fs-schemas

Java de Sun 1. Descargar la jdk de http://www.oracle.com/technetwork/java/javase/downloads/. 2. Instalar segn instrucciones. 158

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

3. Agregar las siguientes variables de entorno.


JAVA_HOME = C:\Archivos de programa\Java\jdk1.7.0_01

Maven 1. Descargar desde http://www.apache.org/dyn/closer.cgi/maven/binaries/apachemaven-2.2.1-bin.zip. 2. Descomprimir el archivo en C:\Archivos de programa\Apache Software Foundation. 3. Agregar las siguientes variables de entorno.
M2_HOME = C:\Archivos de programa\Apache Software Foundation\apache-maven-2.2.1 M2 = %M2_HOME%\bin Path += ;%M2%

4. Configurar el archivo C:\Archivos de programa\Apache Software Foundation\apache-maven-2.2.1\conf\settings.xml segn la seccin maven de este documento para clientes linux. 5. Probar ejecutando.
mvn version

PHP PHP es utilizado como lenguaje de scripting para builds locales. Para instalarlo simplemente seguir los siguientes pasos: 1. Descargar de http://windows.php.net/download/ . 2. Seguir instrucciones. Una vez instaladas las herramientas, podemos ejecutar un build completo local:
cd c:\ cd CodeGeneratorProjects\CodeGeneratorPoms php deployall.php

Compilar en windows desde linux


Para asegurar que nuestro software es cross platform, es decir que funciona tanto en windows como en linux, debemos ser capaces de correr los builds en ambas plataformas. Reiniciar el ordenador para cambiar de sistema operativo sera demasiado tedioso. As que es de gran utilidad utilizar una mquina virtual para compilar en diferentes entornos. Hemos evaluado VMWare y VirtualBox para dar soporte a una mquina windows en la cual corran los builds. Seleccionamos VirtualBox por ser totalmente gratuito y de fcil instalacin. A continuacin describimos los pasos necesarios para crear una mquina con windows xp, capaz de correr los builds utilizando el comando virtualboxdeployall que se encuentra en el proyecto CodeGeneratorPoms. 159

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

1. Para instalar VirtualBox ejecutar.


$ deb http://download.virtualbox.org/virtualbox/debian lucid contrib non-free $ sudo apt-key add oracle_vbox.asc $ wget -q http://download.virtualbox.org/virtualbox/debian/oracle_vbox.asc -O- | sudo apt-key add $ sudo apt-get update $ sudo apt-get install virtualbox-4.1

2. Abrir la aplicacin de gestin de mquinas virtuales en Aplicaciones Herramientas de Sistema Oracle VM VirtualBox. 3. Crear una mquina virtual con el nombre TesisXP. La configuracin default para el sistema operativo Windows XP es suficiente. 4. Instalar el sistema operativo Windows XP en la mquina virtual. 5. Sobre la mquina virtual instalar algn servidor SSH. Hemos probado con OpenSSH sin problemas, pero cualquier server estara bien. 6. Agregar excepcin sobre el puerto 22 en el firewall de windows para poder conectarnos por consola.

160

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

7. Seguir los pasos de la seccin Configuracin de un cliente windows, de este modo contaremos con todo el software necesario para poder ejecutar builds sobre nuestra mquina virtual. 8. Los pasos que siguen deben ejecutarse sobre la mquina host, es decir la mquina con linux. Primero instalaremos sshpass, este es usado por vboxdeployall para lograr que no se haga prompt del password cada vez que nos conectamos por ssh. Para eso ejecutar.
$ sudo apt-get install sshpass

9. Hacer forward de los puertos, con esto al conectarnos por ssh al puerto 2222 si la mquina virtual est encendida las peticiones sern redireccionadas a la mquina con Windows al puerto 22.
$ VBoxManage modifyvm "TesisXP" --natpf1 "guestssh,tcp,,2222,,22"

Con esto, ya podemos ejecutar builds en el sistema operativo Windows XP sin necesidad 161

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

de contar con otra mquina fsica o reiniciar el ordenador.

Utilizando el Framework de Generacin de Cdigo


Ya hemos visto como utilizar el parser generado, ya sea como una librera para otra aplicacin o directamente mediante la lnea de comandos. Para brindar ms soporte al desarrollador se ha extendido el IDE Netbeans mediante el proyecto FscodeGeneratorProjectType (descripto anteriormente en Proyectos Desarrollados), esto facilita la utilizacin del framework y aporta nuevas posibilidades para extenderlo en el futuro, por ejemplo para poder importar el modelo desde Bases de Datos. La primera versin estable de dicho plugin est an en desarrollo, la siguiente es una screenshot del IDE Netbeans con un proyecto abierto:

Por ltimo hemos desarrollado un paquete para dar soporte del lenguaje FGL al editor de texto del proyecto Gnome: Gedit. Que si bien est desarrollado para sistemas Linux/Gnome es posible ejecutarlo en otros entornos de escritorio de Linux y adems 162

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

cuenta con una versin para sistemas Windows por lo que podra utilizarse en el futuro tambin en ese ambiente de desarrollo. El paquete incluye el siguiente soporte para sistemas Linux/Gnome: Versin del generador de cdigo para ejecutar desde consola. Tipo mime *.fgl para gnome, asociando estos archivos a la aplicacin Gedit. Soporte para el editor de texto Gedit: Resaltado del cdigo FGL. Plantilla de colores (theme): FGL Style Instalacin de herramienta externa para invocar al parser del generador de cdigo, para utilizarla debe activar el plugin "External Tools" en Gedit. Screenshot de la ejecucin de Gedit 3 con un archivo fuente FGL y la ejecucin del parser:

Contenido del entregable


Esta documentacin se acompaa de un DVD que contiene: Todo el cdigo fuente de los proyectos implementados. Una instancia binaria del generador de cdigo para ser utilizada por consola.

163

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Un paquete para Linux/Gnome para instalar el tipo mime de los archivos *.fgl y dar soporte del lenguaje al editor de texto Gedit 3. Ejemplos de plantillas implementadas: php-entities, mysql5, web-backend. Plugin de netbeans: FScodeGeneratorProjectType-1.0-SNAPSHOT.nbm

Map road
Pensamos continuar con el desarrollo de los proyectos que aqu se describen. En esta entrega hemos acotado el desarrollo hasta donde menciona la documentacin, pero tenemos pensado agregar aspectos como los siguientes: Agregar configuracin a los archivos pom para que el sitio maven generado sea ms rico, es decir que contenga informacin sobre desarrolladores, links a repositorio de cdigo fuente, etc. Recuperacin de errores en el lenguaje ms robusta. El archivo de la gramtica del lenguaje puede ser modificado de modo que JavaCC genere un parser con la posibilidad de recuperarse de errores y de ese modo, continuar ante un error y luego informar sobre todos los errores producidos. Agregar ms libreras al proyecto CodeGeneratorLibrary. Algunas de las libreras que pensamos podran ser de gran utilidad son: Una librera que defina convenciones de nombres, que sea configurable y que utilicen los templates para nombres de atributos, mtodos, etc. Un wrapper de la clase Xpath de Java, facilitara el procesamiento de los archivos xml de entrada. Etc. Tambin queremos agregar ms templates al proyecto CodeGeneratorTemplates. Algunos podran ser. Todos los necesarios para lograr un sitio completo basado en el lenguaje PHP. Desde la persistencia hasta la administracin (alta, baja y modificaciones) de entidades mediante una interfaz web. Un template para generar entidades para el lenguaje C#. Un template para generar entidades para el lenguaje Java. Ampliar las funciones de primer y segundo orden que pueden aplicarse sobre una variable de tipo arreglo del lenguaje. Una vez logrados los templates necesarios para generar un sitio completo basado en el lenguaje PHP, deseamos agregar tests de integracin. Por ejemplo se puede ejecutar el parser con todos estos templates y utilizar la herramienta Selenium para abrir una instancia de un browser y verificar el correcto funcionamiento de la 164

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

aplicacin generada en su totalidad. Posibilidad de ejecutar builds maven en entornos windows usando plugin de jenkins y virtualbox. De este modo, en el build nocturno podramos asegurar que todos nuestros proyectos corren tanto en entornos windows como linux. Configurar ms plugins de reportes para lograr sitios de proyecto ms interesantes generados con maven. Extender TemplateManager para lograr comunicacin entre diferentes templates registrados. Seguramente se dar el caso de que un template genera diferente cdigo dependiendo de si se est ejecutando otro o no. Etc.

Conclusiones
Luego de haber trabajado durante mucho tiempo en el desarrollo de este Framework hemos observado la gran utilidad que provee la generacin de cdigo en diversas etapas del proceso de desarrollo de un producto de software, no solo en la optimizacin del tiempo sino tambin en la seguridad de un cdigo libre de errores una vez que se han testeado y corregido las plantillas utilizadas. Si bien la idea principal de este trabajo est enfocado en la generacin de cdigo para lenguajes de programacin, cabe destacar que puede ser utilizado para generar otro tipo de salida como puede ser la documentacin tcnica en diversos formatos: html, pdf, odt, etc. o cualquier otro uso donde exista la posibilidad de parametrizar la salida esperada. A la fecha no hemos encontrado trabajos similares, al menos en lo que se refiere a la genericidad y flexibilidad, que creemos, es el gran potencial de nuestro trabajo. Este Framework fue pensado para poder ser extendido y adaptado a los diversos usos y lenguajes de programacin, sin restringir el tipo de salida generado. Por ltimo creemos que la generacin de cdigo es cada vez ms tenida en cuenta en entornos empresariales que ven la necesidad de optimizar sus costos y tiempos de desarrollo. Si bien muchos IDEs modernos ya cuentan con caractersticas de generacin de cdigo, el hecho de utilizar en todo el proceso la misma herramienta brinda consistencia e integracin, adems de brindar la capacidad de poder extenderse y adaptarse al modelo de trabajo de la empresa. Tenemos intenciones de continuar evolucionando este proyecto ms all de esta entrega, para ms informacin dirigirse al sitio web: http://www.freelance-soft.com/codegenerator

Referencias
Prueba unitaria: http://es.wikipedia.org/wiki/Prueba_unitaria The Art of Unit Testing: http://artofunittesting.com/ (Web y libro) Mock Object: http://en.wikipedia.org/wiki/Mock_object 165

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Continuous Integration: http://martinfowler.com/articles/continuousIntegration.html (Art. de Martin Fowler) http://en.wikipedia.org/wiki/Continuous_integration

NetBeans: http://netbeans.org/ Eclipse: http://eclipse.org/ JavaCC: http://javacc.java.net/ ANTLR: http://antlr.org/ CUP: http://www.cs.princeton.edu/~appel/modern/java/CUP/ Jlex: http://www.cs.princeton.edu/~appel/modern/java/JLex/ Jflex: http://jflex.de/ Comparacin entre generadores de parsers: http://en.wikipedia.org/wiki/Comparison_of_parser_generators Generadores de parsers cdigo abierto: http://java-source.net/open-source/parser-generators (Artculo) MySQL: http://www.mysql.com/ Hibernate: http://www.hibernate.org/ JavaDoc-Tools: http://www.oracle.com/technetwork/java/javase/documentation/index-jsp135444.html Junit: http://www.junit.org/home http://junit.sourceforge.net/ (Documentacin y Getting started)

Junit y TestNG: http://www.ibm.com/developerworks/java/library/j-cq08296/ (Comparativa) TestNG: http://testng.org/doc/index.html Java Mock Frameworks Comparision: http://www.sizovpoint.com/2009/03/java-mock-frameworks-comparison.html Jmock: http://www.jmock.org/ EasyMock: http://easymock.org/ Mockito: http://code.google.com/p/mockito Comparison of revision control software: 166

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

http://en.wikipedia.org/wiki/Comparison_of_revision_control_software (Amplia comparacin de diferentes sistemas de control de versiones, Wikipedia) CVS: http://cvs.nongnu.org/ Subversion: http://subversion.apache.org/ Mercurial: http://mercurial.selenic.com/ Git: http://git-scm.com/ Maven: http://maven.apache.org/ http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html http://maven.apache.org/plugins/index.html (Plugins soportados oficialmente) Maven Plugins: Clean: http://maven.apache.org/plugins/maven-clean-plugin/ Properties: http://mojo.codehaus.org/properties-maven-plugin/plugin-info.html Surefire: http://maven.apache.org/plugins/maven-surefire-report-plugin/ Assembly: http://maven.apache.org/plugins/maven-assembly-plugin/ Dependency: http://maven.apache.org/plugins/maven-dependency-plugin/ CheckStyle: http://maven.apache.org/plugins/maven-checkstyle-plugin/ http://checkstyle.sourceforge.net/ Pmd: http://maven.apache.org/plugins/maven-pmd-plugin/ http://pmd.sourceforge.net/ FindBugs: http://mojo.codehaus.org/findbugs-maven-plugin/ http://findbugs.sourceforge.net/ Cobertura: http://mojo.codehaus.org/cobertura-maven-plugin/ http://cobertura.sourceforge.net/ Emma: http://mojo.codehaus.org/emma-maven-plugin/ http://emma.sourceforge.net/ AntRun: http://maven.apache.org/plugins/maven-antrun-plugin/ (Maven Plugin) Wagon ftp: http://maven.apache.org/wagon/wagon-providers/wagon-ftp / 167

Generacin de cdigo basado en modelos Bascal, Martn Pablo Hernndez, Fernando Javier

Ant: http://ant.apache.org/ Java Code Coverage: http://www.copperykeenclaws.com/notes-on-cobertura-vs-emma-vs-clover/ (Cobertura vs. Emma vs Clover) Cobertura vs EMMA: http://niftybits.wordpress.com/2007/04/21/cobertura-vs-emma/ (Post comparativo) Apache Tomcat: http://tomcat.apache.org/ Glassfish: http://glassfish.java.net/ Gassfish vs Tomcat: http://www.ninthavenue.com.au/blog/glassfish-vs-tomcat (Comparativa) Archiva: http://archiva.apache.org/ Artifactory: http://www.jfrog.com/products.php Nexus: http://nexus.sonatype.org/ Jenkins: http://jenkins-ci.org/ Hudson: http://hudson-ci.org/ Jenkins Vs Hudson: http://stackoverflow.com/questions/4973981/how-to-choosebetween-hudson-and-jenkins (Discusin sobre Jenkins y Hudson, se brinda una serie de links para comprender la separacin) Ubuntu: http://www.ubuntu.com/ http://help.ubuntu.com/ (Documentacin) http://www.ubuntu.com/support/community/webforums (Foros)

CentOS: http://www.centos.org/ http://wiki.centos.org/ (Wiki) http://www.centos.org/modules/newbb/ (Foros)

VMWare: http://www.vmware.com/ VirtualBox: http://www.virtualbox.org/

168

También podría gustarte