AutomaticTranslationofOCLMeta-Level ConstraintsintoJavaMeta-programs
AutomaticTranslationofOCLMeta-Level ConstraintsintoJavaMeta-programs
Sahar Kallel, Chouki Tibermacine, Bastien Tramoni, Christophe Dony and Ahmed
Hadj Kacem
Abstract In order to make explicit and tangible their design choices, software de-
velopers integrate, in their applications’ models, constraints that their models and
their implemetations should satisfy. Various environments enable constraint check-
ing during the modeling stage, but in most cases they do not generate code that
would enable the checking of these constraints during the implementation stage.
It turns out that this is possible in a number of cases. Environments that provide
this functionality only offer it for functional constraints (related to the states of
objects in applications) and not for architectural ones (related to the structure of
applications). Considering this limitation, we describe in this paper a system that
generates metaprograms starting from architecture constraints, written in OCL at
the metamodel level, and associated to a specific UML model of an application.
These metaprograms enable the checking of these constraints at runtime.
Keywords: Software Architecture, Architecture Constraint, Object Constraint
Language, Java Reflect
Sahar Kallel
Lirmm, Montpellier University, France, e-mail: [email protected]
Chouki Tibermacine
Lirmm, Montpellier University, Farance e-mail: [email protected]
Bastien Tramoni
Lirmm, Montpellier University, France e-mail: [email protected]
Christophe Dony
Lirmm, Montpellier University, France e-mail: [email protected]
Ahmed Hadj Kacem
ReDCAD, Sfax University, Tunisie e-mail: [email protected]
1
2 Kallel, Tibermacine, Tramoni, Dony and HadjKacem
1 Introduction
2 Illustrative Example
classes stereotyped Model must not have dependencies with the classes stereotyped
Controller. This makes it possible to have several possible controllers for the model.
Using OCL and the UML metamodel (Fig. 1), we obtain the following constraint:
1 context Class inv :
2 s e l f . package . p r o f i l e A p p l i c a t i o n . a p p l i e d P r o f i l e
3 . o w n e d S t e r e o t y p e −> e x i s t s ( s : S t e r e o t y p e | s . name= ’ Model ’ )
4 implies
5 s e l f . s u p p l i e r D e p e n d e n c y . c l i e n t −>f o r A l l ( t : Type |
6 not ( t . oclAsType ( C l a s s ) . package . p r o f i l e A p p l i c a t i o n
7 . a p p l i e d P r o f i l e . o w n e d S t e r e o t y p e −>e x i s t s ( s : S t e r e o t y p e |
8 s . name= ’ View ’ or s . name= ’ C o n t r o l l e r ’ ) ) )
The first line in the Listing 1 declares the context of the constraint. It indicates
that the constraint applies to each class of the application ; the meta-class Class
is then the starting point for all navigations in the rest of the constraint. Lines 2
to 3 serve to collect the set of classes representing the model (having the stereotype
Model) by using the navigation package.profileApplication.appliedProfile. owned-
Stereotype. UML metamodel allows us to get an applied stereotype only starting
from the package that contains the modeling element (a class, in our case) and not
from the element itself. The problem is resolved in some tools like RSA-IBM where
the UML metamodel has been extended with an operation named getAppliedStereo-
types(), which is inherited by the Class metaclass. In Line 5 we obtain the set of
classes which have a direct dependency with the context of the constraint. The re-
maining of the Listing allows to iterate over the set of class instances and test if it
contains classes stereotyped with View or Controller.
Our goal is to obtain automatically a metaprogram generated from an OCL/UML
architecture constraint. The result would be expressed in Java as follows:
1 p u b l i c b o o l e a n i n v a r i a n t ( C l a s s <?> a C l a s s ) {
2 i f ( a C l a s s . i s A n n o t a t i o n P r e s e n t ( Model . c l a s s ) ) {
3 Field [] f i e l d s = aClass . getDeclaredFields () ;
4 for ( Field aField : f i e l d s ){
5 C l a s s <?> f i e l d T y p e = a F i e l d . g e t T y p e ( ) ;
6 i f ( f i e l d T y p e . i s A n n o t a t i o n P r e s e n t ( View . c l a s s )
7 || fieldType . isAnnotationPresent ( Controller . class ) )
8 return false ;
9 }
10 }
11 return true ;
12 }
Listing 2 MVC pattern constraint in Java
the declaration of at least one field in the first class having as a type the second class.
In addition, we assume that the equivalent of stereotypes in UML are annotations
in Java. The method invariant (..) uses the Java reflect library by invoking, for ex-
ample, getDeclaredFields() in Line 3 to collect fields, and isAnnotationPresent(..) in
Lines 6 and 7 to check if a given type has been marked with a particular annotation.
3 General Approach
We propose a three-step process for generating executable Java code from architec-
ture constraints. We note the presence of two metamodels the first one is the UML
metamodel and the second is the Java metamodel that are presented in the following
sections. Fig. 2 depicts the process of metaprogram generation. If the OCL con-
straint needs a refinement, the first step consists in rewriting the OCL constraint in
order to make it more accurate and concrete. For example, if the constraint has a
navigation to Dependency metaclass (in UML metamodel) then we need to refine
this constraint by specifying the different levels of dependencies. Else, the step of
transforming OCL constraints from UML metamodel to Java metamodel is estab-
lished in order to go forward in the process, to the Java code generation. These steps
are detailed in the following sections. We did not perform a direct translation from
OCL/UML to Java because this translation includes at the same time several trans-
formations: shifting to a new metamodel, changing the syntax of constraints, etc.
In fact, our approach requires first a mapping from abstractions of design level to
abstractions of implementation level (mapping abstractions from UML metamodel
to the Java metamodel) and subsequently a translation of the syntax.
In the literature, there are many languages enabling the specification of architec-
ture constraints (see [23] for a survey). The choice of OCL and UML is motivated
by the fact that UML is the de facto standard modeling language, and that OCL is
its original constraint language. Even if a recent study [20] pointed that UML is not
widely used by developers, we all agree that it is a general-purpose modeling lan-
guage known by a lot of developers. We have intuitively chosen to make constraints
programmable in the implementation level in Java because it is a main-stream lan-
guage in object-oriented programming, which provides introspection capabilities.
4 Constraint Refinement
The refinement mechanism is used whenever some abstractions in the UML meta-
model do not have an equivalence in the JAVA language. For example, in the spec-
ification of the OCL constraint expressed on the UML metamodel, we have col-
lected all types (Classes) which have dependencies with a specific type by using
supplierDependency.client. This expression has not a direct equivalence
6 Kallel, Tibermacine, Tramoni, Dony and HadjKacem
in Java. As a result, we refine the constraint in the UML metamodel to express the
different levels of dependencies.
Often, a dependency between two classes is translated as: i) the declaration in
the first class of at least one attribute having as type the second class, ii) some
parameters in operations of the first class, have as type the second class, or iii) some
operations of the first class, have as a return type the second class.
The previous constraint (Listing 1) is refined as follows:
1 context Class inv :
2 s e l f . package . p r o f i l e A p p l i c a t i o n . a p p l i e d P r o f i l e
3 . o w n e d S t e r e o t y p e −> e x i s t s ( s : S t e r e o t y p e | s . name= ’ Model ’ )
4 implies
5 s e l f . o w n e d A t t r i b u t e . t y p e −>f o r A l l ( t : Type |
6 not ( t . oclAsType ( C l a s s ) . package . p r o f i l e A p p l i c a t i o n
7 . a p p l i e d P r o f i l e . o w n e d S t e r e o t y p e −>e x i s t s ( s : S t e r e o t y p e |
8 s . name= ’ View ’ or s . name= ’ C o n t r o l l e r ’ ) ) )
9 and
10 s e l f . o w n e d O p e r a t i o n . r e t u r n V a l u e t y p e −>f o r A l l ( t : Type |
11 not ( t . oclAsType ( C l a s s ) . package . p r o f i l e A p p l i c a t i o n
12 . a p p l i e d P r o f i l e . o w n e d S t e r e o t y p e −>e x i s t s ( s : S t e r e o t y p e |
13 s . name= ’ View ’ or s . name= ’ C o n t r o l l e r ’ ) ) )
14 and
15 s e l f . o w n e d O p e r a t i o n . o w n e d P a r a m e t e r . t y p e −>f o r A l l ( t : Type |
16 not ( t . oclAsType ( C l a s s ) . package . p r o f i l e A p p l i c a t i o n
17 . a p p l i e d P r o f i l e . o w n e d S t e r e o t y p e −>e x i s t s ( s : S t e r e o t y p e |
Automatic Translation of OCL Meta-Level Constraints into Java Meta-programs 7
5 Constraint transformation
Before generating code, we transform in this step the OCL constraint specified on
the UML metamodel into an OCL constraint specified on the Java metamodel. This
simplifies the translation into Java code, since the mapping of abstractions from
UML to Java is performed in this step. In order to perform constraint transformation
we used a Java metamodel. Unfortunately, none of the metamodels found in the
literature and practice satisfied our needs. We relied on Java Reflect library to create
a new simplified Java metamodel. In fact, we can define our metamodel relying on
Java specification but we deliberately chose Java Reflect because it gives us access
to the meta-level of the language and also because it reflects exactly what we can do
in the generated Java code. In this metamodel, we limited ourselves to the elements
necessary for architecture constraint specification. Fig 3 depicts the Java metamodel
that we have defined1 .
The goal of constraint transformation is to replace in an architecture constraint
the UML metamodel vocabulary by Java metamodel vocabulary. It had to establish a
mapping between UML terms and Java terms that are classified in three categories:
metaclasses, roles and navigations.
Table 1 presents for each UML metaclass, role and navigation its equivalent in
Java.
We opted for the specification of these mappings in xml, and we have written
an ad-hoc program for implementing the transformation instead of using an exist-
ing model transformation language like Acceleo [3], Kermeta [2] or ATL [16]. In
fact, architecture constraints are not models. We might have generated models from
1 We assume in this paper that the reader is familiar with UML and Java languages. This is the
reason why the two metamodels are not detailed. They are depicted only for accompanying OCL
constraints in order to see how navigations in the metamodels are established.
8 Kallel, Tibermacine, Tramoni, Dony and HadjKacem
UML Java
Metaclass Class Class
Role ownedAttribute field
ownedOperation method
superClass superClass
nestedType declaringClass
interfaceRealization interface
package package
Navigation package.profileApplication
.appliedProfile.ownedStereotype annotation
Metaclass Property Field
Role type type
declaringTypeattribute declaringClass
Metaclass Operation Method
Role returnValuetype returnType
declaringTypeoperation declaringClass
ownedParameter parameterType
raisedException exceptionType
Metaclass Stereotype Annotation
Metaclass Package Package
We apply the table presented before (Table 1) on the generated AST in order to
obtain a constraint expressed in Java metamodel. For applying mappings, we start
by navigations, then the roles and finally the metaclasses. The following Listing 4
presents our constraint example after applying the transformation method:
1 context Class inv :
2 s e l f . a n n o t a t i o n −> e x i s t s ( s : A n n o t a t i o n | s . name= ’ Model ’ )
3 implies
4 s e l f . f i e l d . t y p e −>f o r A l l ( t : Type |
5 n o t ( t . o c l A s T y p e ( C l a s s ) . a n n o t a t i o n −>e x i s t s ( s : A n n o t a t i o n |
6 s . name= ’ View ’ or s . name= ’ C o n t r o l l e r ’ ) ) )
7 and
8 s e l f . method . r e t u r n T y p e −>f o r A l l ( t : Type |
9 n o t ( t . o c l A s T y p e ( C l a s s ) . a n n o t a t i o n −>e x i s t s ( s : A n n o t a t i o n |
10 s . name= ’ View ’ or s . name= ’ C o n t r o l l e r ’ ) ) )
11 and
12 s e l f . method . P a r a m e t e r T y p e −>f o r A l l ( t : Type |
13 n o t ( t . o c l A s T y p e ( C l a s s ) . a n n o t a t i o n −>e x i s t s ( s : A n n o t a t i o n |
14 s . name= ’ View ’ or s . name= ’ C o n t r o l l e r ’ ) ) )
ocl exists(ex:OclExpression):Boolean
ocl select(ex:OclExpression):Sequence
2 We use getDeclaredField() instead of getFields() to retrieve all attributes (private and public). For
those we inherit, we must specify them in the OCL constraint using the role superClass.
Automatic Translation of OCL Meta-Level Constraints into Java Meta-programs 11
first one (parameters of method that correspond to the first quantifier) in order to
pass them among the parameters of the method corresponding to the second one.
6. Concerning the logic operators (and, not..), we defined also methods equivalent
for each one. These methods are implemented in a class called LogicalOperator.
If the constraint contains a logic operator, This class will be declared as a super
class of the generated class that contains the invariant method.
7. The arithmetic operations (>, <, =, ...) and the types (Integer, Real, String, ...)
are the same in the generated metaprogram.
In order to better explain the code generation process, Table 3 presents an exam-
ple of a metaprogram which is generated from our MVC constraint presented in 2.
For simplicity reasons, we consider for the dependency between two classes that the
first class has at least one method return type having as type the second class.
We have presented in Table 3, for each part of constraint, its equivalent Java
code by respecting the rules that was explained previously. The generated code uses
the introspection of Java in order to examine the application structure at runtime
(getAnnotations(), getMethods()). This code should be called before and
after each method and affectation implemented in the application.
It is worth noting that this code is syntactically different from the optimal code
presented at the beginning of the paper (see Listing 2) but they are semantically
equivalent. It is evident that the automatic translation does not allow to obtain a
code having an optimal complexity. However, it is a valuable tool for developers
who will rather focus on implementing the business logic of their application.
7 Related Work
In this section we present works related to OCL constraint transformation and OCL
code generation. Hassam et al. [13] proposed a method for transforming OCL
constraints during UML model refactoring using model transformations. Their ap-
proach uses first an annotation method for marking the initial UML model, in order
to obtain an annotated target model. Then, a mapping table is created from these two
annotations in order to transform OCL constraints of the initial model into OCL con-
straints of the target one. Their solution of constraint transformations is difficult to
establish and it needs some knowledge about model transformation languages and
tools. In our work, constraint transformation is simple. It is performed in an ad-
hoc way without using additional modeling and transformation languages. In [10],
the authors propose an approach to generate (instantiate) models from metamod-
els taking into account OCL constraints, using CSP (Constraint Satisfaction Prob-
lem). They defined some mathematical rules to transform models and constraints
associated to them. Cabot et al. [7] worked also on UML/OCL transformation into
CSP in order to check quality properties of models. These approaches are similar to
our transformation process because they use an OCL compiler (DresdenOCL [8])
to transform constraints. But in our approach, we consider source code generation
from these constraints, in order to make them executable with application’s code.
12 Kallel, Tibermacine, Tramoni, Dony and HadjKacem
In contrast to CSP, this does not require an external tool for the interpretation of
constraints.
In the practice of model-driven engineering, there exist several tools like Eclipse
OCL [1], Octopus [18], and DresdenOCL [8, 14, 17] which aim to translate OCL
constraints in Java source code. They however transform constraints which are func-
tional and not architectural. These tools translate this kind of constraints into object-
oriented programs which do not use the introspection mechanism. The generated
code by Dresden OCL is difficult to understand. Indeed, it is true that Dresden OCL
is the first tool implemented in this domain, but it extensively uses a vocabulary pro-
posed only by its APIs. This code is normally intended to developers who master,
and will continue to use, Dresden OCL, contrary to our work, where code is intended
to be used by any Java developer. Besides, with these tools, we need to create before-
hand the classes of the model before generating constraints. Other works like Briand
et al. in [6] and Hamie et al. in [12] proposed a tool to transform functional (and not
architectural) constraints respectively into Java using aspect-oriented programming
and JML contracts.
8 Conclusion
It has been demonstrated that architecture constraints bring a valuable help for
preserving architecture styles, patterns or general design principles in a given ap-
plication after having evolved its architecture description [24]. These architecture
constraints are checked at design time. But what if the architecture evolves in the
implementation artifacts (the application’s programs)? Or, what if the architecture
evolves at runtime (through dynamic adaptation, for example)? To be able to check
these constraints in that development stage and at runtime, architecture constraints
should be translated into an appropriate format: meta-programs.
We have presented in this paper a process for generating Java code starting from
OCL architecture constraint specifications expressed in the UML metamodel. This
Java code uses the introspection mechanism provided by the programming lan-
guage. Our process is composed of three steps. The first optional one consists in
refining the constraints. The second step allows to transform them into OCL con-
straints expressed in Java metamodel. The last step generates Java source code re-
lying on specific code generation rules. The reflection (instrospection) mechanism
used in our approach is a standard mechanism in Java. Otherwise, we can use static
analysis libraries like JDT [15] or ByteCode libraries like BCEL [5] but our goal was
to use what is standard in Java and not resort to external libraries. In addition, with
reflection, architecture constraints can be checked at runtime (by invoking the invari-
ant method in all the methods of the application where the architecture is changed:
new objects are created, references to objects are assigned to fields, etc.).
In our proposal, OCL coverage is not complete. We have implemented a proto-
type called MOJaRT: Meta-OCL to JAva Reflect Translator. It is available for down-
load here: https://github.com/saharkallel/mojart.git/. which does
14 Kallel, Tibermacine, Tramoni, Dony and HadjKacem
not take into consideration some OCL constructions, like some collection operations
(union, for example). But this does not have any impact on the work proposed in
this paper.
As a future work, we plan to generalize the proposed approach, by specifying
architecture constraints in a language-independent way: using predicates on graphs
and operations on them and then making automatic transformations towards a par-
ticular object-oriented programming language.
References
19. OMG: Object constraint language, version 2.3.1, document formal/2012-01-01. http:
//www.omg.org/spec/OCL/2.3.1/PDF/. URL http://www.omg.org/spec/
OCL/2.3.1/PDF/
20. Petre, M.: Uml in practice. In: Proceedings of the 35th International Conference on Software
Engineering (ICSE 2013), pp. 722–731. IEEE Press (2013)
21. Reenskaug, T.: Thing-model-view editor an example from a planning system, xerox parc tech-
nical note (may 1979)
22. Shaw, M., Garlan, D.: Software Architecture: Perspectives on an Emerging Discipline. Pren-
tice Hall (1996)
23. Tibermacine, C.: Software Architecture 2, chap. Software Architecture: Architecture Con-
straints. John Wiley and Sons, New York, USA (2014)
24. Tibermacine, C., Fleurquin, R., Sadou, S.: On-demand quality-oriented assistance in
component-based software evolution. In: Proceedings of the 9th ACM SIGSOFT International
Symposium on Component-Based Software Engineering (CBSE’06), pp. 294–309. Springer
LNCS, Vasteras, Sweden (2006)
25. Zdun, U., Avgeriou, P.: A catalog of architectural primitives for modeling architectural pat-
terns. Information and Software Technology 50(9), 1003–1034 (2008)