Metamodels

A metamodel defines the structural properties of the concepts to work with.

For this task Essential provides Essential.Meta: an object-oriented Domain Specific Language (DSL) to create metamodels.

A brief introduction to its syntax follows:

Quick Sample

namespace Sample.Metamodel
{
   class Project : Plan
   {
      string  Name;
      string? Description;
      List<Milestone> 0..* Milestones;
   }
   class Milestone
   {
      string  Name;
      string? Date;
   }
}

Basic primitives

The primitives of the Essential metamodeling language are described here:

Namespace

A namespace defines a naming scope where definitions like classes and enumerations can be contained for further references. Namespaces like UML packages, helps to organize the concepts when them increase in numbers.

Class

A class defines a concept in your modeling language for further instanciation in models. Each class contains properties and can participate in relations with others classes. Sample:

class Customer
{
    string Name;
    string Surname;
    string? Email;
    List<Order> Orders;
}

Inheritance

Allows the extension of types based in other definitions. Avoid circular inheritance, please.

class Person
{
    string Name;
    string Surname;
    string? Email;
}
class Customer : Person
{
    List<Order> Orders;
}

Multiple inheritance is under consideration.

Enumerations

Enumerations are also allowed in the metalanguage having the usual semantics. Example:

enum WeekDays
{
    Sunday, Monday, Tuesday, Wendsday, Thursday, Friday, Saturday
}

Attribute

Attributes or properties are defined inside a class scope. Properties has a type and an optional cardinalty expression.  Example:

class House
{
    string? Direction;
    string City;
    Person? Owner;
    List<Person> Inhabitants;
    List<Room> 2..* Rooms;
}

Primitives types

The inbuilt primitive types are the following ones:

Primitive typeSemantics
stringUnrestricted text.
boolLogic value: true or false.
intInteger.
longLong integer.
decimalDecimal value. Useful for money and when discrete numeric precission is a must.
charCharacter.
dateConstains a date in the W3C format (locale independent): #yyyy-MM-dd#
timeContains a time expression given the W3C format: #hh:mm:ss(((+|-)hh:mm)|Z)?#
datetimeConstains a datetime value in the W3C format (locale independent): #yyyy-MM-ddThh:mm:ss(TZ)?#

Cardinality operators

Traditional cardinality operators are supported with their standard meaning:

OperatorCardinality Semantics
(nothing)(1..1) Compulsory univaluated for simple types and (0..*) for Lists.
?(0..1) Optional. Element can be present or ausent.
+(1..*) Compulsory and multivaluated.
*(0..*) Optional and multivaluated.
0..*(0..*) Same as previous.
n..m(n..m) Multivaluated with a minimun of (n) and a maximus of (m).

Default cardinality for simple primitives (univaluated) is 1..1. The optional operator ? can be used if needed. E.g. string? Label;

Default cardinality for lists types is 0..*.  E.g. List<Milestone> Milestones;

Composition keyword

Multivaluated properties can be marked as compositions using the reserved keyword composition. E.g.

class House
{
    composition List<Room> Rooms;
}

Partial definitions

Namespaces can be splitted and defines in multiple files.

Classes will be allowed to be defined partially. Having each part on different files. The model compiler will joint the partial definitions to create a unique definition after parsing and before the validation stage.

This feature promotes Separation of Concerns and an easy extension mechanims without rewriting core metamodels.

Opposite roles

When defining relations between classes, it is possible to name the other's end role name and also fix the opposite cardinality. E.g.:

class House
{
    composition List<Room> 2..10 Rooms opposite House;
}

class Room
{
    string Name;
}