Registro de Conectores para el servicio de persistencia 76 Implementación del servicio provisto por diferentes conectores
COMPILADOR 5 FASES DEL COMPILADOR
CLASES FUNDAMENTALES QUE DEFINEN AL COMPILADOR
Definí algunas clases fundamentales que están encargadas de resolver los problemas anteriormente descriptos. Algunas de ellas son abstractas y tienen múltiples clases que heredan de ella, por lo general, me limitaré a describir los objetivos de cada una y no los detalles de su implementación.
PSDLCOMPILER
Esta clase modela al compilador en sí mismo, es la cara visible. Toma como entrada un archivo fuente que será compilado y da como resultado los archivos fuentes generados. El archivo fuente es procesado por el parser, el cual genera el árbol que describe el archivo fuente original. Este árbol será procesado por esta clase mediante el patrón Visitor descripto anteriormente, dado que PSDLCompiler implementa la interfase PSDLParserVisitor.
PSDLPARSER
Esta clase es la encargada de procesar el archivo de entrada generando el árbol que lo represente. El compilador tiene una instancia de esta clase como atributo.
NODEPROCESSOR
Algunos nodos del árbol requieren de varios niveles del mismo para completar una definición, por lo general, para cada nodo del árbol de este tipo que el compilador visite, éste creará una instancia del procesador de nodo que es responsable de tomar acciones con la rama del árbol que se esté visitando.
Estas clases implementan la interfase NodeProcessor. Cuando se termine de procesar este nodo, el compilador se lo hará saber al procesador con un mensaje de tipo ‘finalizarProceso’.
COMPILEPROCESS
El compilador creará un CompileProcess inicial para procesar el árbol. Esta clase modela el proceso de compilación de un archivo. El proceso tiene como objetivo recolectar las definiciones declaradas en el árbol. Estas definiciones serán instancias de FullTypeDefinition. Existirá una instancia de CompileProcess por cada archivo procesado, es decir, si se incluye un archivo en el archivo fuente original, esto resultará en la creación en otro proceso de compilación para dicho archivo. Adicionalmente, el proceso mantiene información de estado del procesamiento del árbol, que es muy importante para realizar las validaciones.
FULLTYPEDEFINITION
Es una superclase que modela una construcción en el lenguaje Java. Existen dos clases concretas que heredan de ella una es InterfaceDefinition, y la otra ClassDefinition. La primera modela una interfase y la segunda una clase. Esta clase consta de los atributos básicos que puede tener un objeto Java, tales como: definición de métodos y atributos.
Estas definiciones serán construidas a medida que se procese el árbol por objetos de tipo BaseStorageElementBuilder. Los builders serán notificados de los atributos de las definiciones a medida que el árbol sea procesado.
BASESTORAGEELEMENTBUILDER
Builder (constructor en inglés) es un patrón de diseño que permite encapsular la construcción de un objeto complejo permitiéndole al objeto que lo utiliza deslindarse de la responsabilidad de cómo construir dicho objeto [Gamma01].
Existen diferentes subclases de BaseStorageElementBuilder, una para cada tipo de construcción: objetos almacenados abstractos que generan interfases Java, objetos almacenados concretos que generan clases Java, almacenes abstractos que generan interfases y almacenes concretos que generan clases.
Dichos builders tratan con el problema de la generación de definiciones que se correspondan con la implementación del servicio de persistencia, para ello utilizan otra clase muy importante llamada TargetCompiler.
TARGETCOMPILER
TargetCompiler es una interfase que define las operaciones requeridas para generar definiciones concretas (clases Java) que dependen de la implementación del servicio. Por ejemplo, de cual clase debe heredar una clase que represente un objeto almacenado concreto que deba ser utilizado por una implementación del servicio de persistencia que se basa en archivos.
IDENTIFIERPROCESSOR
Cada proceso de compilación necesita de un objeto que será el encargado de procesar los nodos que representen un identificador en el árbol. Esta clase es necesaria debido que los identificadores pueden ser definidos tanto en forma absoluta como relativa. Cuando están en forma relativa, “qué identifican”, estará dado por el módulo que el proceso esté navegando.
Cada proceso tiene un procesador de identificadores que lleva la cuenta de los identificadores que no fueron procesados realmente, es decir, si este objeto tiene que procesar un nodo de identificador es porque se produjo un error interno en el compilador, y alguna definición no fue contemplada o fue mal procesada. Cuando el compilador visite un nodo que defina una entidad, el objeto que procese ese nodo
será responsable de indicarle al proceso cual es el objeto que procesará el siguiente nodo de identificador en el árbol.
De esta forma cada vez que se visite un nodo que represente un identificador, el procesador que esté definido en el proceso será notificado de ello.
ABSTRACTIDENTIFIERPROCESSOR
Existen múltiples nodos del árbol que dependen de un identificador para concretar una definición válida. Esta clase base permite tomar del proceso el identificador para luego hacer con él lo que corresponda al tipo de nodo.
MODULEIDENTIFIERPROCESSOR
Esta clase es una subclase de AbstractIdentifierProcessor y además implementa la interfase NodeProcessor, cuando un nodo que identifique un módulo sea visitado, el compilador le indicará al proceso que el procesador de identificadores a utilizar será una instancia de esta clase. Cuando esta clase procese un identificador le indicará al proceso que el paquete de Java que se está procesando en ese momento, es el anterior más el nuevo identificador. Cuando se termine de procesar el nodo que define al módulo, se restaura en el proceso el paquete que se estaba procesando anteriormente.
HOLDERGENERATOR Y HELPERGENERATOR
Según la especificación, las interfases generadas deben generar sus respectivas clases Helper y Holder acordes con la especificación de CORBA [IDL2Java]. Todas las definiciones abstractas del servicio requieren de sus respectivas clases Holder y Helper. HolderGenerator y HelperGenerator se encargan, en base a una instancia de FullTypeDefinition, de generar las clases Helper y Holder respectivamente. Una clase holder se utiliza como objeto que permite pasar parámetros a métodos IDL, tanto de entrada como de salida. Dicha clase almacena un objeto del tipo que transporta. Soporta operaciones para leer o escribir el objeto que almacena en un stream de bytes (una secuencia de bytes que pueden definir un conjunto de objetos en su representación binaria). Las clases Helper, se utilizan para interactuar con el objeto genérico Any de CORBA. Any es un contenedor de cualquier objeto definido en IDL. Se necesita de una clase Helper, para insertar y sacar un objeto de un tipo específico del contenedor.
COMPILERDEFINITIONWRITER
Esta clase es la responsable de plasmar en archivos fuente Java, las definiciones generadas por el proceso de compilación. El compilador tiene un atributo de este tipo que será invocado una vez por cada definición recolectada por el proceso al finalizar el proceso de compilación. Para generar el archivo fuente, esta clase creará una instancia de un objeto de tipo FileBuilder, que procesará la definición a construir interrogándola sobre cada uno de sus atributos.
PRIMERA FASE –PROCESAMIENTO
El objetivo de esta fase es generar un CompileProcess, que contendrá todas las definiciones que tendrán que ser generadas en código fuente en la tercera fase, junto con otras que son necesarias para generar y/o validar las definiciones. Para ello se parte del árbol generado por el parser, cuya raíz, en el caso de mi definición del lenguaje, será siempre de tipo ‘Nodepsdl_specification’.
class ClassDefinitions
parser::SimpleNode
+ childrenAccept(PSDLParserVisitor, Object) : Object + dum p(String) : void
+ getFirst() : T oken + getLast() : T oken
+ jjtAddChild(Node, int) : void + jjtClose() : void
+ jjtGetChild(int) : Node + jjtGetNum Children() : int + jjtGetParent() : Node + jjtOpen() : void + jjtSetParent(Node) : void + setFirst(T oken) : void + setLast(T oken) : void + Sim pleNode(PSDLParser, int) + toString() : String
+ toString(String) : String
parser::Nodepsdl_specification + jjtAccept(PSDLParserVisitor, Object) : Object + Nodepsdl_specification(PSDLParser, int)