Skip to content

4. Layer 1 — Metamodel

Contents of DISL 0.1

The metamodel defines the abstract syntax of the language: the kinds of elements that can exist, their attributes, how they nest, how they connect, and which ports they expose. It says nothing about appearance.

4.1 Overview

{
  "metamodel": {
    "diagram": { "attributes": { "title": { "type": "string" } } },
    "dataTypes": { "Email": { "base": "string", "format": "email" } },
    "enums": { "Priority": { "values": { "low": {}, "normal": {}, "high": {} }, "ordered": true } },
    "types": { "Task": { "attributes": { "title": { "type": "string", "required": true } } } },
    "relations": { "DependsOn": { "source": "Task", "target": "Task" } }
  }
}
Property Type Description
diagram {attributes, doc} Attributes of the diagram root element (title, author, version, settings).
dataTypes map → DataType Named value types with facets, or structs (4.4).
enums map → Enum Enumerations (4.5).
types map → NodeType Node types — everything that is drawn as a node, including containers, lanes and annotations (4.6).
relations map → RelationType Relation types — everything that is drawn as an edge (4.9).
doc Doc Documentation of the metamodel.

4.2 Primitive types

Type CEL type JSON representation Facets
string string string minLength, maxLength, pattern, format
text string string (multi-line) as string, plus markup: "plain" | "markdown"
int int integer min, max, step, unit
number double number min, max, exclusiveMin, exclusiveMax, step, precision, unit
bool bool boolean –
date timestamp "YYYY-MM-DD" min, max (as dates)
datetime timestamp RFC 3339 string min, max, timezone (stored zone policy: "utc", "preserve", IANA name)
time duration since midnight "HH:MM[:SS]" min, max, step
duration duration ISO 8601 duration min, max, calendar (allow P1M/P1Y)
color string CSS color string palette (list of allowed colors), alpha (bool)
uri string URI string schemes (allowed schemes)
expression string CEL source context (name of the CEL context it will be evaluated in), resultType
json dyn any JSON schema (inline JSON Schema)
binary bytes base64 string mediaTypes, maxBytes

Unit facets (unit) are informational strings ("h", "kg", "EUR"); runtimes SHOULD show them as field suffixes.

4.3 Attributes

An attribute describes one named value on a node, relation, port or the diagram.

Property Type Description
type TypeName Primitive, enum, data type, or node/relation type (a reference, 4.8). Required.
label LocalizedText Display name.
doc Doc Shown as field help.
required bool Must have a non-empty value. Enforced as a built-in constraint with severity error (section 8.7). Default false.
default literal or {cel} Initial value on creation. A CEL default is evaluated in the create context (12.3).
many bool The attribute holds a list. Default false.
minItems, maxItems, uniqueItems int, int, bool List facets when many.
readOnly bool Not editable by users (may still be set by behavior).
derived Expression Computed, never stored; evaluated in the element context. Implies readOnly.
transient bool Editable but not persisted (for example UI-only flags).
unique "diagram", "parent", "type" Value must be unique within the scope. Enforced as a built-in constraint.
key bool Part of the element's natural key (used for natural ids, 11.5, and for display).
secret bool Masked in forms and excluded from exports and logs.
facets object Primitive facets from 4.2 (min, max, pattern, …); may also be written directly on the attribute.
group string Default form section when a form is generated.
order int Default position in generated forms.
x-* any Extensions.
{
  "attributes": {
    "name":      { "type": "string", "required": true, "maxLength": 80, "unique": "parent",
                   "doc": "Unique within the enclosing region." },
    "priority":  { "type": "Priority", "default": "normal" },
    "effort":    { "type": "number", "min": 0, "step": 0.5, "unit": "h" },
    "tags":      { "type": "string", "many": true, "uniqueItems": true },
    "slug":      { "type": "string", "derived": "self.name.lowerAscii().replace(' ', '-')" },
    "owner":     { "type": "Person", "doc": "Reference to a person node in the same diagram." },
    "createdAt": { "type": "datetime", "readOnly": true, "default": { "cel": "env.now" } }
  }
}

Unset values. Reading an attribute that has no stored value yields its default when one is declared, otherwise the zero value of its CEL type ('', 0, 0.0, false, [], {}, null for references, the Unix epoch for timestamps, 0s for durations). The CEL macro has(self.attr) tests whether a value is explicitly stored. Persistence omits unset values (11.8).

4.4 Data types

A data type is either a constrained primitive or a struct.

{
  "dataTypes": {
    "Percentage": { "base": "number", "min": 0, "max": 100, "unit": "%", "doc": "0–100 %" },
    "Iso4217":    { "base": "string", "pattern": "^[A-Z]{3}$", "doc": "Currency code" },
    "Money": {
      "fields": {
        "amount":   { "type": "number", "required": true },
        "currency": { "type": "Iso4217", "default": "EUR" }
      },
      "display": { "cel": "string(value.amount) + ' ' + value.currency" }
    }
  }
}
Property Type Description
base primitive For constrained primitives.
facets Facets of the base primitive.
fields map → Attribute For structs; fields may themselves be structs, lists or references.
display Bindable<string> How a value is summarised in labels and list cells (value is the struct).
label, doc

Struct values are CEL maps; fields are accessed as self.budget.amount.

4.5 Enumerations

{
  "enums": {
    "Priority": {
      "ordered": true,
      "values": {
        "low":    { "label": "Low",    "color": "#639922", "icon": "arrow-down" },
        "normal": { "label": "Normal" },
        "high":   { "label": "High",   "color": "#E24B4A", "icon": "arrow-up",
                    "doc": "Must be scheduled in the current iteration." }
      }
    }
  }
}
Property Type Description
values map → EnumValue (ordered) Value ids are simple identifiers and are what is stored. Map order is the display order.
ordered bool Values have a meaningful order; enables <, > comparison via ordinal(value, 'Priority').
extensible bool Users may enter values not listed (combobox).
label, doc

EnumValue: label, doc, color, icon, deprecated. The optional color and icon are hints that notations may use ({ "cel": "enumColor('Priority', self.priority)" }).

4.6 Node types

A node type describes a kind of element that is drawn as a node.

Property Type Description
label, doc, icon Display name, documentation, default icon.
abstract bool Cannot be instantiated; exists for inheritance and type references.
extends TypeRef or TypeRef[] Supertypes (4.7).
attributes map → Attribute Own attributes.
ports map → PortType Connection points (4.10).
children Containment What may be nested inside (4.8).
multiplicity {min, max} Number of instances allowed per diagram (for example exactly one Start). Enforced as a built-in constraint.
viewOnly bool The element has no model meaning and lives only in a view: notes, free text, frames, images, annotations. View-only elements are stored in view data (11.6) and are excluded from diagram.nodes unless includeViewOnly is used (12.4).
labelAttribute attribute name The attribute used as the element's name in lists, problem messages, reference pickers and default labels. Default: the first key attribute, else the first required string attribute, else the first string attribute.
tags string[] Free classification, usable in CEL as self.isTagged('x').
x-* Extensions.

4.7 Inheritance

A type inherits all attributes, ports, containment rules and tags from its supertypes, and is accepted wherever a supertype is expected (in relation ends, containment, references, constraint scopes, notation lookups).

  • Multiple inheritance is allowed. The set of supertypes MUST form a directed acyclic graph.
  • A subtype MAY redeclare an inherited attribute to narrow it: tighten facets, change default, label or doc, set required: true, or narrow a reference type to a subtype. It MUST NOT change the base type or relax facets. Conflicting inherited declarations of the same attribute from two supertypes are a specification error unless the subtype redeclares it.
  • Notation, forms and constraints are looked up along the linearised supertype chain (C3 linearisation, as in Python): the most specific declaration wins, and a node type without its own notation uses its nearest supertype's notation.
  • Relation types inherit from relation types only; node types from node types only.

4.8 Containment and references

Containment makes nodes nest: a pool contains lanes, a lane contains tasks, a table contains columns. A contained node has exactly one parent; deleting the parent deletes its contents (unless behavior says otherwise, 9.5).

{
  "Lane": {
    "attributes": { "name": { "type": "string" } },
    "children": {
      "allowed": ["Task", "Event", "Gateway"],
      "min": 0,
      "max": null,
      "ordered": true,
      "slots": {
        "header":  { "allowed": ["LaneHeader"], "max": 1 },
        "content": { "allowed": ["Task", "Event", "Gateway"] }
      }
    }
  }
}
Property Type Description
allowed TypeRef[] Types that may be direct children.
min, max int / null Child count bounds (null = unbounded).
perType map TypeRef → {min, max} Per-type bounds.
ordered bool Child order is meaningful and persisted (for example stacked compartments, table columns).
slots map → {allowed, min, max, doc} Named sub-containers when a node has several distinct regions; each child records its slot. Notation maps slots to compartments or regions.
acrossViews bool Whether a child may be shown outside its parent in other viewpoints. Default false.

A node type without children cannot contain other nodes. Top-level nodes have the diagram as parent (parent == null in CEL, self.owner == diagram).

References are attributes whose type is a node or relation type. They store the target's id, are resolved to elements in CEL, and are not containment: deleting the target sets the reference to null (or deletes the referencing element when behavior declares onDelete: cascade-references, 9.5). References are drawn as edges only if a notation says so (6.10, edges for reference attributes).

4.9 Relation types

A relation type describes a kind of connection, drawn as an edge.

{
  "relations": {
    "Transition": {
      "doc": "A change from one state to another, fired by a trigger.",
      "source": { "types": ["State"], "max": null },
      "target": { "types": ["State"], "exclude": ["InitialState"] },
      "directed": true,
      "allowSelfLoops": true,
      "allowParallel": true,
      "attributes": {
        "trigger": { "type": "string" },
        "guard":   { "type": "expression", "context": "x-guard" }
      }
    }
  }
}
Property Type Description
label, doc, icon
abstract, extends As for node types.
source, target TypeRef, TypeRef[] or RelationEnd Allowed endpoints. Required.
directed bool Default true. Undirected relations treat source/target as unordered for allowParallel and cycle checks.
allowSelfLoops bool Source and target may be the same element. Default false.
allowParallel bool More than one relation of this type between the same pair. Default true.
acyclic bool Shorthand for a built-in constraint forbidding cycles over this relation type.
attributes map → Attribute Relation attributes.
connectsRelations bool Endpoints may be relations, not only nodes (for example UML association classes, annotations pointing at edges). Default false.
derived Expression Derived relations are computed (list of {source, target} maps) and drawn read-only.
viewOnly bool As for node types — connectors between notes, for instance.

RelationEnd

Property Type Description
types TypeRef[] Allowed element types.
exclude TypeRef[] Subtypes excluded from types.
ports string[] Port types the end must attach to (4.10). If set, the end MUST be a port of that type.
min, max int / null How many relations of this type an element may have at this end (outgoing for source, incoming for target).
role string Role name, usable in CEL and labels (for example "parent" / "child").
doc Doc

Connectivity rules that depend on attributes or on the pair of endpoints are written as connect constraints (8.4).

4.10 Ports

Ports are named connection points on nodes: pins of a circuit component, input/output handles of a data-flow block, the sockets of a UML component.

{
  "Block": {
    "attributes": { "name": { "type": "string" } },
    "ports": {
      "in":  { "direction": "in",  "multiplicity": { "min": 1, "max": 8 }, "dynamic": true,
               "attributes": { "name": { "type": "string" }, "dataType": { "type": "string" } } },
      "out": { "direction": "out", "multiplicity": { "min": 1, "max": 1 } }
    }
  }  
}
Property Type Description
label, doc
direction "in", "out", "inout" Allowed edge direction at this port. Default "inout".
multiplicity {min, max} Number of port instances of this type per node. Default {min: 1, max: 1} (one fixed port).
dynamic bool Users may add and remove instances (within multiplicity).
maxConnections int / null Edges per port instance.
accepts TypeRef[] Relation types that may attach. Default: all whose ends allow this node type.
attributes map → Attribute Attributes of each port instance.

Port instances are elements with kind == "port", an id, a type of the form Block.in, and an owner (the node). They are persisted with their owner (11.4).

Illustrated by

Referenced from