This chapter aims to help you to have a quick overview of most of the features of Kermeta. Then, it gives the pointers to the detailed sections in the reference chapter. It also gives some small examples that should help you to understand the basis of the concepts without having to jump to the corresponding detailed section.
Kermeta is a metamodeling language which allows describing both the structure and the behavior of models. It has been designed to be compliant with the OMG metamodeling language EMOF (part of the MOF 2.0 specification) and Ecore (from Eclipse). It provides an action language for specifying the behavior of models.
Kermeta is intended to be used as the core language of a model oriented platform. It has been designed to be a common basis to implement Metadata languages, action languages, constraint languages or transformation language.
In a nutshell, Kermeta is :
MOF compliant (EMOF compliant to be precise)
Model oriented
Imperative
Object-Oriented
Aspect-Oriented
Statically Typed (100% typesafe)
In addition to these characteristics, it includes some typically model-oriented concepts like associations, multiplicities or object containment management.
This chapter presents the main features of the Kermeta language. Section 2 presents the general syntax of the language, sections 3 & 4 give details about the object-oriented and model-oriented features of the language and finally section 4 provides information about some extra concepts in Kermeta (including aspect orientation).
With its workbench, it's goal is to provide a support for all Language Driven Engineering activities. It will be typically used to build tools useful to build software. This includes (but is not restricted to): model checkers, simulators, model transformations (any kind of transformations including model weavers or compilers).
Kermeta is an imperative language for modeling, with a basic syntax inspired from Eiffel. Code is statically type checked, and execution is made by an interpreter (a compiler is on the way, for exhausted performances).
Even if it is not very useful in our context, since it doesn't show the really interresting structures of the language, here is the traditional " Hello world " example you can find in every programming book.
@mainClass "helloworld::HelloworldExample" @mainOperation "sayHello" package helloworld; require kermeta using kermeta::standard class HelloworldExample { operation sayHello() is do stdio.writeln("Hello world, ...") end }
Kermeta language includes usual statements like blocks and loops, comments, etc
do // a loop for getting a text from an user var s : kermeta::standard::String from var found : kermeta::standard::Boolean init false until found loop s := stdio.read("Enter a text:\n --> ") if s.size > 0 then found := true else stdio.writeln("ERROR - Empty text!") end end stdio.writeln("\n You entered: " + s) end
All these "classic" imperative features and their syntaxes are described in Chapter 2, Reference. More precisely in
Users of modern programming languages, like Java, would feel easy with object-oriented features in Kermeta: classes, inheritance, exceptions, and even genericity.
require "truc" // persons who write documents class Writer { attribute name : kermeta::standard::String } // generic concept for every document abstract class Document { reference author : Writer attribute text : kermeta::standard::String } // a "Document" from the real world class Book inherits Document {} // a specialized "Book" class ChildBook inherits Book { attribute minimalAge : kermeta::standard::Integer }
Such classes can be used for verifications:
// a specialized Exception class AgeException inherits kermeta::exceptions::Exception {} abstract class Reader { operation read(book : ChildBook) : Void is abstract } class Child inherits Reader { attribute age : kermeta::standard::Integer operation initialize(age : kermeta::standard::Integer) : Child is do self.age := age result := self // return self so we can chain this call directly after a new end // an action which triggers an Exception operation read(book : ChildBook) : Void is do if age < book.minimalAge then raise AgeException.new end end }
You can get more informations about Kermeta object-oriented features in Chapter 2, Reference. More precisely in
As explained in the Preface and in Architecture, Kermeta extends the MOF. It provides useful means to manipulate models. The support of model introduces the main difference with "more" traditional programming languages.
Association is one of the key concepts when using and defining models. It is obviously part of Kermeta.
MOF defines the concept of "Property" which generalizes the notions of attributes, and associations (composite or not) that you can find in UML. Kermeta syntax also distinguishes these two notions as introduced in Section 2.15, “Class properties”.
As a reminder, the attribute
keyword defines
a link with containment (a composite association) whereas the
reference
keyword just defines an association. As
you can see, property declarations are very close to variable
declarations introduced in Section 2.6, “Using
Variables”).
Each reference may be explicitly linked to another reference (it is
the opposite
concept in MOF terminology – see also
section Section 2.15.1, “Attributes
(attribute), references
(reference) ”).
class Library { attribute books : set Book[0..*] } class Book { attribute title : String attribute subtitle : String reference authors : oset Author[1..*]#works } class Author { attribute name : String attribute lastName : String reference works : set Book[0..*]#authors }
If we represent our Kermeta model in a graphical syntax we obtain the following class diagram (Figure 1.2, “A concrete example : a library”).
Using Eclipse Modeling Framework (EMF), Kermeta can load and save models done with other EMF tools.
/* Initialize the EMF repository */ var repository : EMFRepository init EMFRepository.new /* Create an EMF Resource, given model and metamodel URIs as String */ var resource : Resource init repository.createResource(myModelURI, itsMetamodelURI) /* Load the resource */ resource.load // get elements from the resource // in this sample, you know that your root element is always a Library, // so you can directly get the first one var aLibrary : Libray aLibrary ?= resource.one // note the conditional assignment using the ?=, if not a Library you'll get Void
In the same way, you can serialize a model, or load, change and save an existing model.
Caution | |
---|---|
Your model URI MUST be of the form "platform:/resource/myProject/myModel" or "platform:/plugin/myProject/myModel". Your metamodel URI MUST be of the form "platform:/resource/myProject/myModel" or "platform:/plugin/myProject/myModel" or an URI registered in the EMF registry. |
Caution | |
---|---|
Be aware that you CANNOT load kermeta text files (*.kmt). Only xmi files are allowed to be loaded. Parsing and obtaining a model from a textual syntax is not part of Kermeta. This is the role of other tools (like sintaks). Technically, it is possible to create some Kermeta operation that will hide this step, however, this is not the goal of this manual to explain this procedure. |
Actually, navigating in a model is as simple as using objects in an object-oriented program. However, several features have been added in order to ease this activity.
For example, thanks to the lambda expressions, the collections of the language are easily manipulated using lexical closure (select, collect, each, etc). This applies to all the collections of the language, the one you may define directly but also the one which are used when an Attribute or Reference has a multiplicity greater than 1.
Example (based on the library sample of Section 1.4.1, “Associations : toward a first concrete example of a Kermeta model”):
var smithBooks : Set<Book> init Set<Book>.new smithBooks.addAll( lib.books.select{aLibraryBook | aLibraryBook.authors.exists{aBookAuthor | aBookAuthor.lastName == "Smith"}})
In the example above, lib is an instance of Library. It searchs in the books, select the books where the author last name is "Smith".
In order to improve reuse of existing code between metamodel variants, the language introduces the notion of ModelType. It is based on the notion of conformance between two metamodels. This allows to write behavior that is valid for a given metamodel and that will also work for any conformant metamodel.
TODO write a small illustrative example of a simple printer based on a ModelType : a subset of class diagram of UML
Kermeta has been developed, using MDE principles so it also provides its own metamodel (reflectiveley available). Details of Kermeta metamodel is available in Chapter 3, Kermeta Metamodel
You can get more informations about all Kermeta model-oriented features in the Chapter 2, Reference. More precisely in
Since Kermeta is an extension of MOF, a MOF meta-model can conversely be seen as a valid Kermeta program that just declares packages, classes and so on but does nothing. Kermeta can then be used to breath life into this meta-model by incrementally introducing aspects for handling concerns of static semantics, dynamic semantics, or model transformations.
One of the key features of Kermeta is the static composition operator require
allows extending an existing meta-model with new elements
such as properties, operations, constraints or classes. This operator allows defining these various
aspects in separate units and integrating them automatically into the meta-model. The composition
is done statically and the composed model is typed-checked to ensure the safe integration of all units.
This mechanism makes it easy to reuse existing meta-models or to split meta-models into reusable pieces.
It can be compared to the open class paradigm. Consequently a meta-class that identifies a domain concept
can be extended without editing the meta-model directly. Open classes in Kermeta are used to organize
cross-cutting
concerns separately from the meta-model to which they belong, a key
feature of aspect-oriented programming. With this mechanism, Kermeta can support the addition of new
meta-class, new subclasses, new methods, new properties, new contracts to existing meta-model. The
require mechanism also provides flexibility. For example, several operational semantics could be
defined in separate units for a single meta-model and then alternatively composed depending on
particular needs. This is the case for instance in the UML meta-model when several semantics
variation points are defined.
Thank to this composition operator, Kermeta can remain a kernel platform to safely integrate all the concerns around a meta-model. This feature has proved to be extreemly useful in the context of metamodel engineering.
You'll find more details in the Reference chapter, more precisely in: Section 2.20, “Weaving Kermeta code”
Kermeta implements several "less common" or advanced features that helps in many situations.
Typically, lambda expressions/functions is a well known concept, very useful in almost all kermeta code. Even, if you will probably not write your own function, you'll certainly use the existing one defined on collections.
In order to implement and statically type check OCL-like iterators, Kermeta includes some limited functional features by implementing lambda expressions.
This is typically used on Collection
which
provides functions like : each
,
select
, forAll
,
detect
, ...
Example 1: the following code will build a collection of names of the operations that start with "test".
var names : Collection<String> names := self.getMetaClass.classDefinition.ownedOperation .select{ op | op.name.indexOf("test") == 0} .collect{ op | op.name }
Example 2: Providing a time function on Integer
operation times(body : <Integer->Object>) : Void is do from var i : Integer init 0 until i == self loop body(i) i := i + 1 end end
this allows to write code like :
var res : Integer 10.times { i | stdio.writeln(i.toString + ": Hello") } // Say 10 times Hello
See sections "Lambda Expressions and functions" and Lambda Expression for detailed informations.
Kermeta most recent versions embed advanced concepts like Lambda Expressions and functions, Dynamic evaluation of Kermeta expressions, Design by contract (pre, post, inv contraints) or Weaving Kermeta code.
As Kermeta language is implemented upon Eclipse and Java, you can call Java code inside Kermeta code.(see Section 2.22, “Using existing java code in Kermeta”)
There is some special behavior regarding object comparison or cloning.