This document specifies the data modelling facilities of the Multi-Modal Modelling Language (MMEL), as defined in MN113 . MMEL data modelling provides UML-style data structure definitions integrated with process flows, compliance tracking, and quantitative monitoring.
The data modelling subsystem of MMEL encompasses:
MMEL data modelling is a superset of UML class diagram concepts. The following table maps UML class diagram concepts to their MMEL equivalents:
| UML Concept | MMEL Equivalent | Notes |
|---|---|---|
| Class | class Name#data { ... }
|
Fields, types, references, cardinality |
| Enumeration | enum Name { ... }
|
Named enumeration with definitions |
| Association/Aggregation | reference(Target#data)
|
With cardinality
[0..*]
,
[1..*] |
| Multiplicity | [0..*]
,
[1..*]
,
[1..1]
|
On references and nested types |
| Composition | Nested type fields | e.g.
meta: DocMeta |
| Attribute | Class field | Typed or untyped (implicitly string) |
| Data Store (UML object) | data_registry
|
Persistent store backed by a data class |
| Constraint | satisfy { }
block |
Validation constraint categories on fields |
| Stereotype | #data
suffix |
Distinguishes data classes from helper classes |
MMEL data modelling connects data structures to process flows and compliance requirements through data registers.
class#data ──data_class──> data_registry <──output── process
<──reference_data── process
│
v
Stored documents (.sws)
A data class defines the schema of records. A data register is the persistent
store for those records. Processes write to registers via
output { }
and read
from them via
reference_data_registry { }
.
The full data flow from class definition to runtime storage is:
class definition (schema)
│
└── data_registry declaration (named store)
│
├── process.output { RegistryID } (writes records)
│
├── process.reference_data_registry { RegistryID } (reads records)
│
└── .sws file (runtime data state)
Classes define data structures in MMEL. There are two kinds of classes:
class <ClassName>#data {
<fieldName>: <type> {
definition "Field description"
modality SHALL
reference {
<ReferenceID>
}
satisfy {
<constraint-category>
}
}
<fieldName> {
definition "Field description"
modality SHOULD
}
}
class <ClassName> {
<fieldName> {
definition "Field description"
modality SHALL
}
<fieldName>: <type> {
definition "Field description"
}
}
Helper classes follow the same syntax as data classes but without the
#data
suffix. They cannot be linked directly to data registers.
Fields may be declared with or without an explicit type:
class Scope#data {
name: string {
definition "Name/Title"
}
scope {
definition "Scope"
}
review: datetime {
definition "Last Reviewed"
}
}
Each class field may contain the following properties:
| Property | Required | Description |
|---|---|---|
definition
|
no | Human-readable description of the field's purpose |
modality
|
no | RFC 2119 keyword indicating obligation level for this field |
reference
|
no | List of reference IDs linking this field to normative sources |
satisfy
|
no | Validation constraint category for tooling |
The
modality
property on a class field indicates the obligation level for that
field within the data structure:
class RiskPlan#data {
scope {
definition "Scope"
modality SHALL
reference {
ISO14971-doc-ref3-4
}
}
Criteria {
definition "Criteria for risk acceptability"
modality SHALL
}
}
Fields can link to normative references, providing traceability from data structure elements to their source standards:
class RiskManagementFile#data {
plan: reference(RiskPlan) {
definition "Risk Management Plan"
modality SHALL
reference {
ISO14971-doc-ref3-4
}
}
hazards: reference(Hazards) {
definition "Known and foreseeable hazards"
modality SHALL
}
}
Data classes are the primary data structure definitions in MMEL. The
#data
suffix marks a class as a data class, enabling it to be linked to a data
register.
The following data class, from a medical device risk management model, defines a record that aggregates references to multiple subsidiary data classes:
class RiskManagementFile#data {
plan: reference(RiskPlan) {
definition "Risk Management Plan"
modality SHALL
reference {
ISO14971-doc-ref3-4
}
}
change: reference(ChangeRecord) {
definition "Record of changes"
modality SHALL
reference {
ISO14971-doc-ref3-4
}
}
analysis: reference(RiskAnalysisRecord) {
definition "Risk analysis"
modality SHALL
reference {
ISO14971-doc-ref4-1
}
}
device: reference(MedicalDevice) {
definition "characteristics related to the safety of the medical device"
modality SHALL
reference {
ISO14971-doc-ref4-2
}
}
hazards: reference(Hazards) {
definition "Known and foreseeable hazards associated with the medical device"
modality SHALL
}
evaluation: reference(RiskEvaluationResult) {
definition "Risk evaluation results"
modality SHALL
reference {
ISO14971-doc-ref5
}
}
control: reference(RiskControlRecord) {
definition "Risk control records"
modality SHALL
reference {
ISO14971-doc-ref6-2
}
}
}
This example demonstrates:
The following data class, from an ISO HLS (High-Level Structure) model, uses a mix of primitive types and references:
class Scope#data {
name: string {
definition "Name/Title"
}
scope: string {
definition "Scope"
}
aspect: reference(Aspects#data) {
definition "Performance Aspect"
}
review: datetime {
definition "Last Reviewed"
}
}
This example demonstrates:
Helper classes (also called non-data classes) define reusable complex types that
can be embedded as fields within data classes. They are identified by the absence
of the
#data
suffix and cannot be directly linked to data registers.
The following helper class, from a standardization management system model, defines a reusable metadata structure:
class DocMeta {
identification {
definition "Identification"
modality SHALL
}
description {
definition "Description"
modality SHALL
}
format {
definition "Format"
modality SHALL
}
media {
definition "Media"
modality SHALL
}
review {
definition "Review for suitability and adequacy"
modality SHALL
}
approval {
definition "Approval for suitability and adequacy"
modality SHALL
}
title {
definition "Title"
modality MAY
satisfy {
description
}
}
refno {
definition "Reference number"
modality MAY
satisfy {
identification
}
}
}
This helper class is then used as a field type in multiple data classes:
class IssueData {
meta: DocMeta {
definition "General documented information"
modality SHALL
}
issue {
definition "Issue"
modality SHALL
}
type: IssueType {
definition "Type"
modality SHALL
}
}
class NonapplicableJustification {
requirement {
definition "Requirement that the organization determines is not applicable"
modality SHALL
}
justification {
definition "Justification"
modality SHALL
}
}
Used within a data class with cardinality:
class NonapplicableProductData {
meta: DocMeta {
definition "General documented information"
modality SHALL
}
type {
definition "Type of products and services covered in the SMS scope"
modality SHALL
}
nonApplication: NonapplicableJustification[0..*] {
definition "Non-applicable requirements and justifications"
modality SHALL
}
}
A class may be declared with no fields. This serves as a placeholder or marker type:
class RiskControlMeasureReview#data {
}
class Policy#data {
}
Empty data classes can still be linked to data registers and used as reference targets.
Enumerations define a set of named values with human-readable definitions. They are used as field types within class definitions to constrain a field to a predefined set of values.
enum <EnumName> {
<Value1> {
definition "Description of value 1"
}
<Value2> {
definition "Description of value 2"
}
}
Each enumeration value is an identifier followed by a block containing a
definition
property.
The following enumeration, from a medical device risk management model, defines three categories of hazard:
enum HazardType {
Physical {
definition "Physical"
}
Chemical {
definition "Chemical"
}
Biological {
definition "Biological"
}
}
An enumeration is used as a field type by naming the enumeration in the field declaration:
class Hazards#data {
hazard {
definition "Known hazards"
}
hazard2 {
definition "Foreseeable hazards"
}
type: HazardType {
definition "Hazard type"
}
}
The following enumeration, from a supply chain management model, defines a supplier rating scale:
enum SRating {
distinctive {
definition "Distinctive"
}
good {
definition "Good"
}
basic {
definition "Basic"
}
}
Used in a data class:
class SupplierRating#data {
supplier: reference(SupplierCapacity#data) {
definition "Supplier's response"
}
rating: SRating {
definition "Rating"
}
}
Data registries define named, persistent data stores. Each registry is backed by a data class and represents a collection of records that processes can read from or write to. Data registries are the runtime containers that hold the actual document records produced during process execution.
data_registry <RegistryName> {
title "Human-readable title"
data_class <ClassName>#data
}
A data class defines the schema (structure) of records, while a data registry defines the store (container) for those records. They are distinct concepts:
| Concept | Description |
|---|---|
Data class (
class Name#data { ... }
) |
Defines the fields and types of a record; the schema |
Data registry (
data_registry Name { ... }
) |
Defines the named, persistent store for records conforming to that schema |
The
data_class
property of a registry points to the data class that defines
its schema. The registry name and the data class name may be the same or
different.
class RiskPlan#data {
scope {
definition "Scope"
modality SHALL
}
}
data_registry RiskPlan {
title "Risk management plan"
data_class RiskPlan#data
}
Processes interact with data registries through two binding mechanisms:
The
output { }
property of a process specifies which data registries the
process writes to:
process RiskManagementFile1 {
name "Manage Risk management file"
actor Org
validate_provision {
Provision1
}
output {
RiskManagementFile
}
}
The
reference_data_registry { }
property specifies which data registries the
process reads from:
process MonitorIssue {
name "Monitor issues"
modality SHALL
reference_data_registry {
IssueRegistry
}
validate_provision {
MonitorIssue
}
}
The following example, from an ISO HLS model, demonstrates a model with multiple data registries, each backed by a data class:
class Aspects#data {
name: string {
definition "Name/Title"
}
bib: reference(BibItem#data)[0..*] {
definition "Relevant bibliographic item"
}
}
class BibItem#data {
id: string {
definition "BibItem ID"
}
item: string {
definition "Item"
}
}
data_registry Aspects {
title "Performance Aspects"
data_class Aspects#data
}
data_registry BibItem {
title "Bibliographic items"
data_class BibItem#data
}
data_registry Scope {
title "Scope"
data_class Scope#data
}
data_registry Objective {
title "Objectives"
data_class Objective#data
}
data_registry Role {
title "Roles"
data_class Role#data
}
The registry identifier is used in:
The
title
property provides a human-readable display name, which may differ
from the identifier.
A model may define any number of data registries. Each registry SHALL reference exactly one data class. Multiple registries MAY reference the same data class, though this is uncommon.
A process MAY output to multiple registries and read from multiple registries:
process DeterminePartyandReq {
name "Determine interested parties and their requirements"
modality SHALL
validate_provision {
DetermineParty
DeterminePartyReq
}
output {
PartyRequirementRegistry
PartyRegistry
}
}
Class fields in MMEL may be declared with explicit types or left untyped (implicitly string). This clause specifies all available field types.
| Type | Notation | Description |
|---|---|---|
| String | string
|
Text value |
| Boolean | boolean
|
True/false value |
| Datetime | datetime
|
Date and/or time value |
| Role | role
|
Reference to a system role |
| Reference | reference(Target#data)
|
Reference to another data class |
| Enumeration | <EnumName>
|
An enumeration type (e.g.
HazardType
) |
| Helper class | <ClassName>
|
A nested complex type (class without
#data
) |
| Untyped | (none) | Defaults to string |
The
string
type represents textual data:
class TotalCostOfOwnership#data {
price: string {
definition "Purchase Price"
}
deliverCost: string {
definition "Delivery cost"
}
installation: string {
definition "Installation Cost"
}
}
The
boolean
type represents a true/false value:
class auditchecklist {
bibitem: reference(BibItem#data) {
definition "Bibitem"
}
clause: string {
definition "Clause number"
}
evidence: string {
definition "Evidence"
}
compliance: boolean {
definition "Compliance"
}
}
The
datetime
type represents a date and/or time value:
class audit#data {
name: string {
definition "Name/Title"
}
date: datetime {
definition "Date/Time"
}
}
The
role
type references a system role defined in the model:
class Role#data {
name: string {
definition "Name/Title"
}
People: string {
definition "People"
}
role: role {
definition "System role"
}
responsibilities: string {
definition "General responsibilities"
}
}
Reference types create links between data classes, enabling relational data structures. A reference field points to a record in another data class.
<fieldName>: reference(<TargetClassName>#data) {
definition "Description"
}
The target class name may include the
#data
suffix or omit it, depending on
whether the target is a data class or helper class.
A reference without cardinality denotes exactly one related record:
class Scope#data {
name: string {
definition "Name/Title"
}
aspect: reference(Aspects#data) {
definition "Performance Aspect"
}
}
References may include cardinality to indicate collections:
class audit#data {
persons: reference(Role#data)[0..*] {
definition "Responsible persons"
}
bibitem: reference(BibItem#data)[0..*] {
definition "Relevant bibliographic items"
}
standard: reference(Standards#data)[0..*] {
definition "Relevant standards"
}
}
References typically point to data classes (with
#data
suffix), but can also
reference helper classes when used as nested types:
class PartyRequirementData {
party: reference(PartyData)[0..*] {
definition "Requirement of interested parties"
modality SHALL
}
}
An enumeration type constrains a field to a predefined set of values:
class Hazards#data {
type: HazardType {
definition "Hazard type"
}
}
enum HazardType {
Physical {
definition "Physical"
}
Chemical {
definition "Chemical"
}
Biological {
definition "Biological"
}
}
A helper class (without
#data
suffix) can be used as a field type to embed a
nested structure:
class IssueData {
meta: DocMeta {
definition "General documented information"
modality SHALL
}
issue {
definition "Issue"
modality SHALL
}
pfactor[0..*] {
definition "Positive factor or condition"
modality CAN
}
}
Helper class fields may also include cardinality:
class NonapplicableProductData {
meta: DocMeta {
definition "General documented information"
modality SHALL
}
nonApplication: NonapplicableJustification[0..*] {
definition "Non-applicable requirements and justifications"
modality SHALL
}
}
When a field declaration omits the type (
:
and type name), it defaults to
string:
class RiskPlan#data {
scope {
definition "Scope"
modality SHALL
reference {
ISO14971-doc-ref3-4
}
}
Assignment {
definition "Responsibilities and authorities"
modality SHALL
}
}
Cardinality (multiplicity) notation specifies how many values a field may hold. Cardinality applies to reference types and helper class types.
| Notation | Meaning | Example |
|---|---|---|
[0..*]
|
Zero or more (optional collection) | reference(Role#data)[0..*] |
[1..*]
|
One or more (required collection) | reference(BibItem#data)[1..*] |
[0..1]
|
Zero or one (optional single) | reference(Traceability)[0..1] |
| (none) | Exactly one (default) | reference(RiskPlan) |
Cardinality is specified immediately after the type name, before the field property block:
<fieldName>: <type>[<lower>..<upper>] {
definition "Description"
}
Where
<lower>
is an integer and
<upper>
is either an integer or
*
(meaning unbounded).
The
[0..*]
notation indicates that a field may have zero or more values:
class audit#data {
name: string {
definition "Name/Title"
}
persons: reference(Role#data)[0..*] {
definition "Responsible persons"
}
bibitem: reference(BibItem#data)[0..*] {
definition "Relevant bibliographic items"
}
checklist: auditchecklist[0..*] {
definition "Audit Checklist"
}
}
The
[1..*]
notation indicates that a field must have at least one value:
class Procedure#data {
name: string {
definition "Name/Title"
}
policy: reference(policy#data)[1..*] {
definition "Relevant Policy"
}
bibiitem: reference(BibItem#data)[1..*] {
definition "relevant bibliographic items"
}
}
The
[0..1]
notation indicates that a field may have zero or one value:
class SMSProcessInteractionData {
meta: DocMeta {
definition "General documented information"
modality SHALL
}
process: reference(SMSProcessData)[1..*] {
definition "Process"
modality SHALL
}
sequence[0..1] {
definition "Sequence of the processes"
modality SHALL
}
interaction[0..1] {
definition "Interaction of the processes"
modality SHALL
}
}
When no cardinality is specified, the field holds exactly one value:
class Scope#data {
name: string {
definition "Name/Title"
}
aspect: reference(Aspects#data) {
definition "Performance Aspect"
}
review: datetime {
definition "Last Reviewed"
}
}
When a field has both cardinality and modality, the modality applies to the field as a whole. For example:
class PartyRequirementData {
party: reference(PartyData)[0..*] {
definition "Requirement of interested parties"
modality SHALL
}
}
A
satisfy
block on a class field specifies a validation constraint category.
It is used by validation tooling to determine which fields fulfil which aspects
of a document or data requirement.
<fieldName> {
definition "Field description"
modality MAY
satisfy {
<constraint-category>
}
}
The
satisfy
block contains a single identifier naming the constraint category
that this field satisfies.
Constraint categories are user-defined identifiers that name the type of constraint or requirement aspect that a field addresses. Commonly used categories include:
| Category | Description |
|---|---|
description
|
The field provides descriptive content about the data element |
identification
|
The field provides identifying information (e.g. reference numbers, codes) |
format
|
The field specifies the format or representation of the data |
media
|
The field specifies the storage or transmission medium |
These categories are not predefined by MMEL; model authors may define any constraint categories appropriate to their domain.
The following helper class, from a standardization management system model (BS 202000), defines document metadata fields with satisfy blocks:
class DocMeta {
identification {
definition "Identification"
modality SHALL
}
description {
definition "Description"
modality SHALL
}
format {
definition "Format"
modality SHALL
}
media {
definition "Media"
modality SHALL
}
review {
definition "Review for suitability and adequacy"
modality SHALL
}
approval {
definition "Approval for suitability and adequacy"
modality SHALL
}
title {
definition "Title"
modality MAY
satisfy {
description
}
}
author {
definition "Author"
modality MAY
satisfy {
description
}
}
date {
definition "Date"
modality MAY
satisfy {
description
}
}
refno {
definition "Reference number"
modality MAY
satisfy {
identification
}
}
language {
definition "Language"
modality MAY
satisfy {
format
}
}
software {
definition "Software version"
modality MAY
satisfy {
format
}
}
graphics {
definition "Graphics"
modality MAY
satisfy {
format
}
}
paper {
definition "Paper"
modality MAY
satisfy {
media
}
}
electronic {
definition "Electronic"
modality MAY
satisfy {
media
}
}
}
The
satisfy
block can also appear on fields within data classes:
class IssueData {
meta: DocMeta {
definition "General documented information"
modality SHALL
}
issue {
definition "Issue"
modality SHALL
}
type: IssueType {
definition "Type"
modality SHALL
}
pfactor[0..*] {
definition "Positive factor or condition"
modality CAN
satisfy {
issue
}
}
nfactor[0..*] {
definition "Negative factor or condition"
modality CAN
satisfy {
issue
}
}
}
The
satisfy
block provides metadata for validation and compliance-checking
tools. When a standard requires that a document have certain properties (e.g.
"description", "identification", "format"), the satisfy blocks allow tooling to
verify that the data class includes fields that cover each required constraint
category.
The typical validation workflow is:
Multiple fields MAY satisfy the same constraint category. For example, in the
DocMeta
class above, both
title
,
author
, and
date
satisfy
description
.
MMEL supports cross-model references using the
Namespace#ElementID
notation.
This enables data classes and references to refer to elements defined in other
MMEL models, supporting model alignment and implementation traceability.
Cross-model references use the format
Namespace#ElementID
, where:
This notation is used in several contexts within data modelling:
Reference declarations may use cross-model notation to declare references that originate from another model:
reference BS20400#Ref35 {
document "BS20400:2017 Sustainable procurement -- Guidance"
clause "7.2.3"
}
reference BS20400#Ref44 {
document "BS20400:2017 Sustainable procurement -- Guidance"
clause "7.4.1"
}
In this example, the reference identifiers use the
BS20400#
prefix to indicate
that these references originate from the model with namespace
BS20400
.
When an implementation model references provisions from the standard it implements, cross-model notation is used:
provision BS20400#Provision180 {
condition "LCC is a method that could be used to analyse the costs"
reference {
BS20400#Ref35
}
}
provision BS20400#Provision181 {
condition "When assessing the costs using an LCC approach, the organization should indicate in the procurement documents the data to be provided by the tenderers"
reference {
BS20400#Ref35
}
}
These provisions are then referenced by processes in the implementation model:
process BS20400#LCC {
name "Life Cycle Costing"
validate_provision {
BS20400#Provision180
BS20400#Provision181
}
subprocess BS20400#Page19
}
The following excerpt from
BS20400impl(mapped).mmel
demonstrates an
implementation model that references elements from the
BS20400
standard model:
// Cross-model start events
start_event BS20400#Start20 {
}
start_event BS20400#Start14 {
}
// Cross-model subprocess
subprocess BS20400#Page19 {
elements {
BS20400#Start20 {
x -20
y -20
}
totalCostOfOwnership {
x -70
y 120
}
BS20400#MonetizedExternalities {
x -70
y 230
}
}
process_flow {
BS20400#Edge87 {
from BS20400#Start20
to totalCostOfOwnership
}
}
data {
TotalCostOfOwnership {
x -240
y 280
}
ExternalCost {
x -240
y 400
}
}
}
This example demonstrates:
Data classes may reference other data classes across models using the cross-model notation in reference fields:
class ManagementReviewData {
meta: DocMeta {
definition "General documented information"
modality SHALL
}
changes: reference(IssueData)[0..*] {
definition "Changes in external and internal issues"
modality SHALL
}
objectives: reference(ObjectiveData)[0..*] {
definition "The extent to which standardization objectives have been met"
modality SHALL
}
process: reference(SMSProcessData)[0..*] {
definition "Process performance and conformity"
modality SHALL
}
}
When a tool encounters a
Namespace#ElementID
reference, it:
If the referenced model is not available, the tool SHOULD report a resolution error but MAY continue processing with an unresolved reference placeholder.
This clause provides a simplified EBNF grammar for the data modelling constructs of MMEL. The grammar covers classes, enumerations, data registries, field properties, cardinality, and satisfy blocks.
(* Data modelling declarations *)
ClassDecl ::= 'class' IDENTIFIER ('#data')? '{' ClassField* '}'
ClassField ::= FieldName (':' FieldType)? Cardinality?
'{' FieldProperty* '}'
FieldName ::= IDENTIFIER
FieldType ::= PrimitiveType
| ReferenceType
| IDENTIFIER
PrimitiveType ::= 'string' | 'boolean' | 'datetime' | 'role'
ReferenceType ::= 'reference' '(' IDENTIFIER ('#data')? ')'
Cardinality ::= '[' INT '..' ( '*' | INT ) ']'
FieldProperty ::= 'definition' STRING
| 'modality' MODALITY
| 'reference' '{' IDENTIFIER* '}'
| 'satisfy' '{' IDENTIFIER '}'
EnumDecl ::= 'enum' IDENTIFIER '{' EnumValue* '}'
EnumValue ::= IDENTIFIER '{' 'definition' STRING '}'
DataRegistryDecl ::= 'data_registry' IDENTIFIER '{'
'title' STRING
'data_class' IDENTIFIER ('#data')? '}'
(* Shared terminals *)
MODALITY ::= 'SHALL' | 'SHOULD' | 'MAY' | 'CAN' | 'MUST'
STRING ::= '"' ... '"'
IDENTIFIER ::= [a-zA-Z_][a-zA-Z0-9_'-]*
INT ::= [0-9]+