General
Core Concepts
The fundamental modeling construct is the Entity, representing a concept similarly to classes in OOP.
Entities may contain:
- Slots, which describe features or properties of the concept (similar to class fields).
A slot may optionally have a value, which can be either a primitive value (e.g., a Boolean literal) or a reference to another Entity.
- Operations, which define behavior (similar to methods).
- Annotations, which customize or influence behavior/handling of the container entity.
Notably, Slots, Operations, and Annotations are themselves modeled as Entities, ensuring a uniform representation across all elements.
Annotations can be added to Entities, Slots and Operations but not the Annotations.
Classification and Refinement
Each Entity has a unique Classifier, which serves as a template defining its structural elements (slots, operations, annotations). The relationship between an Entity and its Classifier is called Refinement. A sequence of such relationships forms the refinement chain, which may be of arbitrary length.
During refinement: - The Entity must conform to the structural constraints defined by its Classifier. - It may further concretize the concept, as long as it does not violate the constraints along the refinement chain.
Every Entity is a direct or indirect refinement of the built-in Base Entity, which is self-defined (i.e., Base is its own Classifier).
Loops are not allowed in the refinement chain, with the only exception being the built-in Base Entity, since it serves as its own Classifier.
Slots, Operations and Annotations of an Entity can themselves be refined, when refining the container Entity.
Slots
In entity definitions, slots are only explicitly declared when they are modified or specialized.
Inherited slots that remain unchanged are implicit: they are not listed in the definition but remain fully accessible and referenceable.
Slots accessible through the refinement chain can be further refined at any point, even skipping one or more intermediate refinement steps.
No Entity may have two slots with the same name accessible at any level, including implicit slots inherited from its Classifier.
If a slot has an assigned value, that value may be overridden during refinement.
An Entity may mark its slots as omitted using the Omit annotation.
Omitted slots become inaccessible and cannot be referenced further down the refinement chain.
During refinement, a slot may be split into multiple slots to represent distinct aspects or fragments of the original feature.
For example, a general wheel slot may be refined into frontWheel and rearWheel.
When dividing a slot into multiple slots:
- The new keyword must be applied consistently to all resulting slots to preserve the original slot.
- Otherwise, the original slot is implicitly omitted.
Slot division can also be used to rename a slot by creating a new slot from the original and omitting the original one.
New slots are introduced by dividing the special Base.Fields slot.
Therefore, adding new slots is only possible as long as Base.Fields has not been omitted.
Type System
The type system distinguishes between primitive values and modeled entities.
Primitive Types
The following primitive types are supported: - Boolean – true/false values - Integer – whole numbers - Real – decimal numbers - String – text
Modeled Entities
Modeled entities can be either:
- Static – these entities are included in the modeling space
- Dynamic – these entities exist only at runtime.
Dynamic entities allow modeling their structure and executing Operations on them, but are not added to the modeling space. As a result, static entities cannot reference dynamic entities, but dynamic entities can reference static entities. This also means that all slots and annotations of dynamic entities must also be dynamic. Dynamic entities are useful in scenarios such as passing structured parameters or reporting validation errors.
Validation
Every Entity has a Validate operation, which is used to check the correctness of its refinement.
Validation returns a collection of errors, or an empty list if the validation succeeds.
Validation checks are applied automatically by the framework, but they can also be called manually.
During refinement, the Validate operation can be overridden; however, all Validate operations along the entire refinement chain are always checked, so validation cannot be relaxed—only strengthened.
Validation may be influenced by Constraints. Constraints are Annotations with a special operation called Check. Similar to Validate, Check returns a list of errors. Constraints applied to entities are automatically checked whenever the entity is validated.
The validation rules defined within an Entity apply only to its refinements, not to the Entity itself. However, checks associated with constraints on the Entity are active at the annotated level. For example, if a type annotation is added to a Slot and a value is also assigned, the validation immediately verifies the value at that level.
Annotations
Omit
The Omit annotation can be applied to a Slot. It indicates that the annotated slot cannot be referenced further down the refinement chain. Omit is used implicitly by the framework when a slot is defined without the new keyword (in this case the origin slot is omitted).
Type Constraint
The Type constraint specifies the type of a slot's value. The type can be either a primitive or a modeled type.
In the case of a modeled type, type compatibility is checked along the refinement chain.
Cardinality Constraint
The Cardinality constraint defines the cardinality of a slot: how many fragments it can be divided into or how many values it can hold. Cardinality has a minimum and a maximum value. The maximum can be set to -1, which means that there is no upper limit for the multiplicity.
Final Constraint
The Final constraint indicates that the annotated Entity or Slot represents a real-world object, and therefore cannot be further instantiated. When applied to an Entity: - Slots that are optional and have no assigned value are accepted, and are treated as if they were implicitly omitted. - If a slot has a value assigned, regardless of whether it is optional or required, that value must be final (a primitive value, or a reference to a final entity)
Contract Constraint
The Contract constraint enables partial validation, similarly to interfaces, by requiring an entity to satisfy a set of structural constraints. A contract defines a set of slots, which may be annotated with ContractSlot. When a contract is applied to an Entity: - The entity must implicitly or explicitly contain a corresponding slot for each contract slot, matched by name. - The entity’s slots must carry all constraints and annotations defined on the corresponding contract slots (or their refinements) and the constraints must also be satisfied by the entity’s slots.
For example, if a contract slot specifies a type constraint, the corresponding slot in the entity must also define a compatible type constraint.