• No se han encontrado resultados

4. InCense Extendido

4.3. Arquitectura extendida

4.3.2. Generar código fuente con Java Emitter Templates (JET)

A nivel de código fuente, un componente está distribuido en cinco clases y el usuario solamente proporciona una fracción del código necesario por lo que se requiere generar de manera automática el resto del código fuente.

Hasta donde se tiene conocimiento, solo existe una tecnología para Java y soportada por eclipse que permita generar código fuente en tiempo de ejecución. Esta tecnología se llama Java Emitter Templates (JET) y forma parte de un proyecto más grande orientado a crear herramientas para el modelado de software que se integren con el ambiente de desarrollo Eclipse (“JET Tutorial,” 2012).

JET es una tecnología que permite generar código fuente a partir de plantillas definidas por el programador. Primero el programador define la estructura del documento a través de las plantillas con las secciones de contenido dinámico. El compilador JET traduce estas plantillas a funciones de código fuente que dados ciertos parámetros regresan una cadena de texto representando el documentos generado.

El primer paso para utilizar JET es analizar las clases (Java) que se generarían en tiempo de ejecución. En una clase de Java existen secciones que son fijas y otras cuyo contenido es

dinámico. Una vez que se identificaron estas secciones en las diferentes clases involucradas en un componente, se generó un template para cada una de ellas. La Figura 30 muestra una sección de un template, específicamente el que corresponde al procesamiento de los datos y los transmite al siguiente componente en un proyecto de sensado: <Nombre>ProcessData.Java. Nombre corresponde al nombre designado para el componente.

Figura 30. Segmento de una plantilla.

JET agrega un compilador al proyecto de desarrollo (JET Builder). Este compilador traduce el template a una clase Java que finalmente sirve para generar código fuente. Este compilador funciona en tiempo de desarrollo.

En el código de la Figura 30 se observan los caracteres <% y %>, estos sirven para marcar el inicio y fin de etiquetas. Las etiquetas enmarcan sentencias que son ejecutadas por el

1 <%@ jet package="edu.incense.manager.java.emitters" imports="java.util.*" class="DataComponentEmitter"%>

2 <%ComponentStructure componentStructure = (ComponentStructure) argument;%> 3 <%byte i = 0;%>

4 <%Date date = new Date();%> 5 /**

6 * New Component <%=componentStructure.getComponentName()%> generated automatically <%=date.toString()%>

7 */

8 package edu.incense.android.datatask.filter; 9 import edu.incense.android.datatask.data.*;

10 public class <%=componentStructure.getComponentName()%>ProcessData extends DataFilter {

11 /*Section to declare configuration variables*/

12 <%for (i = 0; i<componentStructure.getConfigurationVariables().length; i++) {%> 13 private <%=componentStructure.getConfigurationVariables()[i][0]%>

14 <%=componentStructure.getConfigurationVariables()[i][1]%>; 15 <%}%>

16

17 /*Section to declare and initialize operation variables*/

18 <%for (i = 0; i<componentStructure.getOperationVariables().length; i++) {%> 19 private <%=componentStructure.getOperationVariables()[i][0]%>

20 <%=componentStructure.getOperationVariables()[i][1]%> = <%=componentStructure.getOperationVariables()[i][2]%>;

compilador de JET. Las instrucciones válidas para utilizar en los templates son las mismas que se usan en JSP.

Al inicio del código (línea 1) en la Figura 30 se puede identificar el encabezado que deben llevar todos los templates, en esta línea se declara el nombre de la clase que servirá para generar código fuente en tiempo de ejecución además del paquete donde deberá ser creada en el proyecto, de esta manera está disponible en tiempo de ejecución (véase Figura 31).

Figura 31. Template en su forma de clase de Java (después de JET Builder).

La estructura de la clase que corresponde al componente se puede apreciar hasta la línea 10 de código en la Figura 30. Las líneas 8 y 9 corresponden a elementos fijos (se encuentran en todos los componentes). A partir de ahí el template comienza a mostrar contenido dinámico (diferente para cada componente), por ejemplo, la línea 10 corresponde al nombre del componente, mientras que las líneas 12-20 sirven para declarar variables.

La función principal de un template traducido se llama generate (después de JET Builder) y recibe como argumento un objeto (Java.lang.Object) que por defecto se llama argument.

Como se sabe, en el API de Java Object es el padre del resto de las clases de Java, por eso es que argument se puede invocar (cast) como cualquier otro tipo de objeto que se desee. En la solución propuesta para generar código fuente esto se aprovecha para combinar el template con los atributos del componente que se desee crear. Como se mencionó anteriormente se realizó una conceptualización de un componente que tiene tres elementos: nombre del componente, código para procesar datos y variables. Para aprovechar el componente genérico y combinarlo con un template traducido se realizó la implementación del mismo en Java (véase Figura 32). El nombre para la clase resultante fue: ComponentStructure. Se puede observar en la Figura 30 (línea 2) como se toma argument que contiene las características del componente y se realiza una invocación a ComponentStructure.

Figura 32. Implementación del componente genérico.

La Figura 32 muestra la clase ComponentStructure como se mostraría en un diagrama de clases, en la mitad superior de la Figura se encuentra el nombre de la clase junto con las variables que almacenan los atributos de la misma. En este caso se tiene el nombre del componente y las estructuras que guardan el código para procesar datos y las variables definidas por el usuario. En la mitad inferior se encuentran los métodos para acceder a esos atributos de manera indirecta (getters y setters).

Se crearon 5 templates, uno por cada clase involucrada en la creación de componentes, en cada template se envía ComponentStructure como argumento para generar el código fuente complemento, necesario para automatizar el proceso de creación de componentes. La mayor ventaja de usar JET y templates en conjunto con el componente genérico es que el usuario no necesita familiarizarse con el código fuente de InCense ya que este

class InCense_ClassDiagram

ComponentStructure - componentName: String

+ CONF_VARIABLES: int = 1 {readOnly}

- confi gurati onVariables: ArrayList <String[]> = new ArrayLi st <... - dataLiterals: ArrayList <String[]> = new ArrayList <... + LITERALS: int = 4 {readOnly}

+ OP_VARIABLES: int = 2 {readOnly}

- operationVariables: ArrayList <String[]> = new ArrayList <... - outputName: String

+ OUTPUTS: int = 3 {readOnly}

- outputs: ArrayLi st <String[]> = new ArrayList <... - outputType: String

- processDataCode: String + VAR_NAME: i nt = 1 {readOnly} + VAR_TYPE: int = 0 {readOnly} + VAR_VALUE: int = 2 {readOnly}

+ ComponentStructure(String, ArrayList<String[]>, ArrayLi st<String[]>, String, String, String, ArrayList<String[]>, ArrayLi st<String[]>) + ComponentStructure()

+ getComponentName() : String + getConfigurationVariables() : String[] + getDataLi terals() : String[]

+ getOperati onVariables() : Stri ng[] + getOutputName() : String + getOutputs() : String[] + getOutputType() : String + getProcessDataCode() : String + setComponentName(String) : void

+ setConfi gurati onVariabl es(ArrayList<String[]>) : void + setDataLiteral s(ArrayList<String[]>) : void

+ setOperationVariables(ArrayList<String[]>) : void + setOutputName(Stri ng) : voi d

+ setOutputs(ArrayList<String[]>) : voi d + setOutputType(Stri ng) : voi d + setProcessDataCode(String) : void

conocimiento está implícito en la creación de los templates. Considerando la utilidad del componente genérico en combinación con JET y el hecho de que esta combinación de tecnologías coadyuva a reducir la intervención del usuario en la creación de componentes se podría decir que son las tecnologías habilitadoras que hacen posible facilitar el proceso de creación de componentes.

Si bien es cierto que el componente genérico en combinación con JET son las tecnologías que hacen posible facilitar el proceso de creación de componentes, todavía se puede facilitar aún más el proceso de creación de componentes. El código fuente generado en tiempo de ejecución debe almacenarse en un destino, por ejemplo en la Aplicación Móvil. Además, se puede vincular OntoInCense con la Aplicación Móvil para llevar la contabilidad de los componentes registrados en OntoInCense y los implementados en la Aplicación Móvil. Si el editor incluido en Protégé reemplaza al Editor InCense de la arquitectura original, todavía es necesario crear un archivo de configuración para la Aplicación Móvil a partir de las campañas de sensado que se registren en OntoInCense. En otras palabras, se requiere de una herramienta de administración de componentes y campañas de sensado; que además sirva como vínculo entre Protégé y la Aplicación Móvil. Para este propósito se propone utilizar InCense Manager, cuya funcionalidad se detalla en la siguiente sección.