PyEmofUCEmofUC
meta-models
|
The EmofUC meta-meta-model is an extension of the OMG EMOF 2.4 meta-meta-model, in which minor modifications have been introduced in order to simplify its Python implementation in the PyEmofUC environment:
The class diagram below shows the EmofUC
classes organized by containment and inheritance.
Their detailed description (attributes and associations) can
be found in the EMOF
2.4 specification.
The Python classes associated to the
meta-meta-model elements are dynamically generated at runtime.
The implementation has the following features:
The methods in the EMOF Python implementation may have parameters as defined in EMOF (regarding name, type, cardinality and default value).
The EmofUC
meta-meta-model incorporates a number of extensions which
are specified associating a tag (with predefined key
names) to the meta-models elements.
The extensions defined are:
Declaration of native primitive types
EMOF (as well as EmofUC) allows to
declare new primitive types. However, EMOF does not provide
mechanisms for specifying nor characteristics of the newly
defined data types neither inheritance relations among them.
EmofUC declares 5 primitive data types based on the
Python native data types:
Their definition is complete because they
correspond to well-defined Python types. The types also match
those defined in the UML Annex. The only difference is that
UML suggests the UnlimitedNatural
unsigned type whereas PyEmofUC proposes the PyUnlimitedInteger type, which
corresponds to a signed integer.
Declaration of specific primitive types
EmofUC introduces a number of types
derived from native primitive types. They increase the detail
level when formalizing meta-models, hence allowing model
verification before installing the models in the environment.
The types defined by PyEmofUC are shown in the previous figure:
Four tags with predefined and reserved names have been specified in order to declare features of the primitive types defined in a meta-model:Qualification of primitive types
<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> |
<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> |
Declaration of derived attributes
A derived
property has a value that is evaluated based on other
attributes in the same class. A derived property is not
implemented by means of a Python attribute, but through a
Python property in which the getter method calls another
specific method.
PyEmofUC uses the "DE" tag for declaring the Python
code implementing the method that evaluates the value of a
derived property.
The table below shows a chunk of code declaring a derived
property named isRoot in the emof.Package
class.
<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> |
The code below shows the Python code for the class implemented by the PyEmofUC environment, based on the information provided by the "DPE" tag.
def getisRoot(self):
Please, note that the
tag value attribute must strictly respect the
indentation required by the Python syntax.
Operations implementation
The EMOF specification allows to associate operations to meta-model classes in order to describe the instances behaviour, but it only describes the methods signature, i. e., the operation name, the parameters name and type, and the return type. Its only goal is to describe the public interface of model elements.
PyEmofUC
allows to associate the Python code implementing operations
by means of "OPE" tags. This mechanism is only useful if the
operation code is simple, because it presents dificulties if
trying to verify its correctness.
For operations with more complex code, it should be
associated using inheritance and extension strategies. (TODO).
The "OPE" tags may be aggregated to emof.Operation elements and the value attribute contains the Python code implementing the operation behaviour. The environment introduces the basic syntax indentation required by the invocation code, but in the code included in the tag, it must be included in the indentation between the code sentences.
The table below
shows an example of code operation assignment.
<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> |
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
"DOC" tags are used in order to add documentation into models:Documentation introduction
<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> |