PyEmofUC

Metamodelo EmofUC

J.M. Drake, P. López Martínez y C. Cuevas

Grupo de Ingeniería Software y Tiempo Real (ISTR) - Universidad de Cantabria

Tabla de Contenidos

Metametamodelo EmofUC

El metametamodelo EmofUC es una extensión del metametamodelo EMOF 2.4 de OMG, en el que se han introducido ligeras modificaciones para simplificar su implementación en el entorno PyEmofUC:

En el siguiente diagrama de clases se muestran las clases de EmofUC organizadas por contención y herencia.
La descripción detallada de las clases (atributos y asociaciones) puede encontrarse en la especificación EMOF 2.4.


Implementación Python de las clases EMOF

La implementación de las clases Python que se asocian a los elementos del metametamodelo se generan dinámicamente en tiempo de ejecución, con las siguientes características:

Extensiones proporcionadas por EmofUC

Al metametamodelo EmofUC se han incorporado un conjunto de extensiones, utilizando para ello el mecanismo basado en asociar etiquetas (instancias de la clase Tag) a los elementos de los metamodelos, previstos en EMOF.
Las extensiones incorporadas a EmofUC son las siguientes:

Declaración de tipos primitivos nativos

EMOF (e igualmente EmofUC) permite declarar tipos primitivos con un nombre asociado. Sin embargo EMOF, no ofrece mecanismos para especificar las características del tipo de dato, ni la dependencia por herencia entre ellos.
En EmofUC, se han declarado 5 tipos de datos básicos en base a los tipos de datos nativos de Python:

Al estar asociadas las características de estos tipos de datos a los correspondientes del lenguaje Python, su características quedan perfectamente especificadas. Es interesante notar que estos tipos coinciden con los propuestos en la extensión base que propone OMG para UML. La única diferencia cualitativa es que OMG propone UnlimitedNatural de enteros sin signo en vez de PyUnlimitedInteger como se propone en PyEmofUC que son enteros con signo.



Declaración de tipos primitivos específicos

Se ha considerado de interés introducir en EmofUC un conjunto de tipos específicos que son derivados de los tipos primitivos nativos, que permiten incrementar el detalle en la formalización de la información, y sobre todo, poder verificar la consistencia de los modelos de forma previa a su instanciación en el entorno.

Los tipos que se han definido en PyEmofUC, son los que se muestran en la figura previa:

Cualificación de los tipos primitivos

Se han reservado cuatro nombres  de etiquetas para la formulación de aspectos relativos a los tipos que se definen en un metamodelo:

<ownedType  name="URI" xmi:id="emof.URI" xsi:type="emof:PrimitiveType">

      <tag name="PT" xmi:id="emof.URI.PT" xsi:type="emof:Tag"

             value="emof#emof.PyString"/>

      <tag name="RE" xmi:id="emof.URI.RE" xsi:type="emof:Tag"

             value="((http://)|(file:///)|(platform:))([a-z]|[A-Z])([a-z]|[A-Z]|[0-9]|/|[.]|_)*"/>

</ownedType>

En la siguiente tabla se define el tipo de dato Percentage como un tipo de dato real que admite valores entre 0.0 y 100.0 (ambos incluidos).

<ownedType  name="Percentage" xmi:id="mast2.Percentage" xsi:type="emof:PrimitiveType">

      <tag name="PT" xmi:id="mast2.Percentage.PT" xsi:type="emof:Tag" value="emof#emof.PyReal"/>

      <tag name="MAX" xmi:id="mast2.URI.MAX" xsi:type="emof:Tag" value="100.0"/>

      <tag name="MIN" xmi:id="mast2.URI.MIN" xsi:type="emof:Tag" value="0.0"/>

</ownedType>

Declaración de atributos derivados

Una propiedad derivada es aquella que tiene un valor que se evalua en base a otros atributos disponibles en la clase en que está declarado. Una propiedad derivada no se implementa con un atributo Python en la instancia, sino como una propiedad Python en la que el método de lectura ejecuta un método específico en el ámbito de la instancia.
En PyEmofUC se reserva la etiqueta “DPE” para definir el código Python que implementa el método que evalúa el valor de la propiedad derivada. En la tabla se muestra como ejemplo la propiedad derivada isRoot que EMOF define para los elementos emof.Package. Así mismo, en la siguiente figura se muestra el código que el entorno PyEmofUC incorpora en la clase Python que implementa el entorno PyEmofUC a partir de la información del tag “DPE”.

<ownedType name="Package" xsi:type="emof:Class" xmi:id="emof.Package" superclass="#emof.NamedElement">

      <ownedAttribute name="nestingPackage" xmi:id="emof.Package.nestingPackage" xsi:type="emof:Property"

              theType="#emof.Package" opposite="#emof.Package.nestedPackage"/>

……..

      <ownedAttribute name="isRoot" xmi:id="emof.Package.isRoot" xsi:type="emof:Property"

                          theType="#emof.PyBoolean" isDerived="True" >

             <tag name="DPE" xmi:id="emof.Package.isRoot.DPE" xsi:type="emof:Tag"

                               value="return self.nestingPackage==None"/>

      </ownedAttribute>

</ownedType>


Esta descripción da lugar a que el entorno cree el siguiente código Python en tiempo de ejecución de la clase en que está declarada.

     def getisRoot(self):
           return self.nestingPackage==None
      isRoot=property(getisRoot)

Obsérvese que el sangrado que requiere la sintaxis Python lo introduce de forma automática el entorno PyEmofUC, pero el sangrado relativo al código que se introduzca debe ser introducido con la etiqueta.

Implementación de operaciones de las clases

EMOF prevee asociar a los elementos del modelo operaciones que describen aspectos de su comportamiento. EMOF sólo describe los aspectos de especificación de las cabeceras de los métodos, esto es, nombre y descripción de los parámetros  y del valor que retorna. Su función es meramente describir la interfaz pública de los objetos del modelo.

Haciendo uso de tag con nombre reservado “OPE”, en PyEmofUC se permite asociar a las operaciones el código Python que las implementa y que el entorno las genera automáticamente. El método es útil para incorporar el código de pequeñas operaciones de gestión de los objetos del modelo. Para operaciones de negocio mas complejas, se prevee mecanismos de herencia y/o composición que permita asociar a los objetos del modelo código elaborado (y probado) externamente (TODO).

Los tags de nombre “OPE” se asocian en el metamodelo a los elementos de tipo emof.Operation, y contienen en su atributo value el código Python que implementa la funcionalidad de la operación. El entorno introduce el sangrado base que requiere la sintaxis de invocación del código, pero en el código que se incluye en el tag debe estar el sangrado relativos entre las sentencia del código introducido.

En la figura se muestra como ejemplo la operación ficha de la clase Familia en el ejemplo FamiliaEmpresa que se describe en este documento.

<ownedType name="Familia" xmi:id="fam.Familia" xsi:type="emof:Class" superclass="#fam.Elemento">

                                                                               

      <ownedAttribute name="miembro" xmi:id="fam.Familia.miembro" xsi:type="emof:Property"

                theType="#fam.Persona" isComposite="True" upper="*" opposite="#fam.Persona.familia"/>

      <ownedAttribute name="padre" xmi:id="fam.Familia.padre" xsi:type="emof:Property"

                theType="#fam.Adulto" lower="0"/>

      <ownedAttribute name="madre" xmi:id="fam.Familia.madre" xsi:type="emof:Property"

                theType="#fam.Adulto" lower="0"/>

      <ownedOperation name="hijo" xmi:id="fam.Familia.hijo" xsi:type="emof:Operation"

                theType="#fam.Persona" lower="0" upper="*"> 

             <tag name="OPE" xmi:id="fam.Familia.hijo.OPE" xsi:type="emof:Tag"

                    value="hijos=list(self.miembros);hijos.remove(self.padre)if self.padre else None;hijos.remove(self.madre) if self.madre else None; return hijos"/>

      </ownedOperation>

</ownedType>       


El siguiente código es el que el entorno incorpora a la clase en que está definida la operación.

     def hijo(self):
          hijos=list(self.miembros);hijos.remove(self.padre) if self.padre else None; hijos.remove(self.madre) if self.madre else None; return hijos


Incorporación de documentación

A fin de que se pueda generar automáticamente documentación de los modelos se ha reservado los tags con nombre “DOC” para introducir etiquetas con documentación en cada elemento de un modelo.

<ownedType name="Elemento" xmi:id="fam.Elemento" xsi:type="emof:Class"

            superclass="emof#emof.Object" isAbstract="True">

      <tag name="DOC" xmi:id="fam.Elemento.DOC" xsi:type="emof:Tag"

                value="Elemento abstracto raiz de otros tipos de elemento de la familia"/>

</ownedType>

Documentos

Enlaces de interés