openEHR logo

Basic Meta-Model (BMM)

Issuer: openEHR Specification Program

Release: LANG latest

Status: DEVELOPMENT

Revision: [latest_issue]

Date: [latest_issue_date]

Keywords: reflection, meta-model, UML, BMM

openEHR components
© 2016 - 2022 The openEHR Foundation

The openEHR Foundation is an independent, non-profit foundation, facilitating the sharing of health records by consumers and clinicians via open specifications, clinical models and open platform implementations.

Licence

image Creative Commons Attribution-NoDerivs 3.0 Unported. https://creativecommons.org/licenses/by-nd/3.0/

Support

Issues: Problem Reports
Web: specifications.openEHR.org

Amendment Record

Issue Details Raiser Completed

LANG Release 1.1.0 (unreleased)

4.0.1

SPECLANG-8. Classify EL_DECISION_TABLE under EL_TERMINAL;
Add read-only and writable meta-types for variables and properties;
Add routine, function and property signature meta-types.

T Beale

29 Apr 2022

4.0.0

SPECLANG-8. Simplify meta-model of features to single inheritance;
change BMM_PROCEDURE to return a special type similar to Haskell, Kotlin. Revert some 3.1.0 changes.

T Beale

09 Jun 2021

LANG Release 1.0.0

3.1.0

SPECLANG-2. Add Basic Meta-Model (BMM) spec to LANG component.

openEHR SEC

11 May 2020

Add EL_SIMPLE to distinguish complex expressions from terminals and operator expressions; Adjust BMM_CONSTANT to support computed constants;
Add EL_DECISION_TABLE, BMM_ACTION_TABLE classes and descendants;
Add BMM_INTERVAL_VALUE;
Add BMM_FEATURE_GROUP and BMM_VISIBILITY classes;
Rename BMM_SCHEMA.bmm_schema to bmm_model;
Remove unintended inheritance from BMM_SCHEMA to P_BMM_PACKAGE_CONTAINER;
Improve documentation in Section 4.

T Beale

12 Oct 2020

Rename EL_ASSERTION to EL_BOOLEAN_EXPRESSION;
Extend literal meta-types to directly support container literals;
Add basic statement types to BMM;
Add external routine support;
Added note on multiple inheritance in Class Features section.

T Beale

25 Jun 2020

Remove inheritance to BMM_DEFINITIONS (assume static access);
Remove BMM_ENTITY class and 'Entities' section of document.

B Verhees,
T Beale

01 Jun 2020

Rename BMM_DEFINED_TYPE to BMM_EFFECTIVE_TYPE;
Rename BMM_ENTITY_TYPE to BMM_MODEL_TYPE;
Significant improvements to meta-type part of model;
Add Expression language meta-model;
Add abstract syntax examples to text;
Add description of default Any class and type;
Add BMM_MODEL.used_models;
Add creators and converters;
Add ROUTINE.body hook;
Add BMM_RESULT, EL_SCOPED_REF, EL_TYPE_REF;
Add BMM_MODULE.

T Beale

22 Apr 2020

Rename BMM_MODEL_ELEMENT to BMM_DECLARATION;
Rename BMM_VALUED to BMM_TYPED;
Rename BMM_REFERENCEABLE to BMM_FEATURE;
Introduce dual taxonomy for features based on scoped declarations and typing;
Add meta-model for functional entities. Re-structure packages. Modify BMM_FEATURE.signature to new meta-type, BMM_SIGNATURE.

T Beale

11 Nov 2019

Improve meta-model of Features: rename BMM_FORMAL_ELEMENT to BMM_REFERENCEABLE; move BMM_VALUE_RETURNING.type to BMM_EVALUABLE;
Add BMM_INDEXED_CONTAINER_TYPE, BMM_INDEXED_CONTAINER_PROPERTY, to support indexed containers like Hash<K, V>.

T Beale

10 Mar 2019

Improve meta-model of Enumerated types to include types restricted to a terminology or value set (may be used for terminology constraints);
Improve explanation and diagrams to do with types and classes.

T Beale

22 Feb 2019

Add feature elements BMM_ROUTINE, BMM_VALUED and descendants;
Change BMM_PROPERTY.is_mandatory to BMM_MUTABLE.is_nullable (reversed Boolean sense);
Made BMM_PACKAGE_CONTAINER abstract;
Moved name to BMM_MODEL_ELEMENT, replacing name in BMM_CLASS, BMM_PACKAGE, BMM_PROPERTY, and model_name in BMM_MODEL;
Marked BMM_PROPERTY.is_computed as obsolete (to be phased out);
Add BMM_PROPERTY.is_composition to distinguish part/whole from associations.

T Beale

15 Sep 2018

3.0.0

SPECLANG-2. Add Basic Meta-Model (BMM) spec to LANG component;
Separate P_BMM model and syntax to BMM Persistence specification;
refactor / tighten class model:
rename BMM_GENERIC_PARAMETER to BMM_PARAMETER_TYPE;
remove BMM_OPEN_TYPE; remove BMM_TYPE_ELEMENT;
add new type BMM_DEFINED_TYPE as parent of BMM_SIMPLE_TYPE and BMM_GENERIC_TYPE;
add new type BMM_UNITARY_TYPE as parent of BMM_DEFINED_TYPE and BMM_PARAMETER_TYPE;
redefine BMM_CLASS.ancestors to be of type BMM_DEFINED_TYPE;
redefine BMM_PARAMETER_TYPE.conforms_to to type_constraint of type BMM_DEFINED_TYPE;
correct BMM_CLASS.immediate_descendants to be of type List<BMM_CLASS>;
rename BMM_CLASSIFIER to BMM_ENTITY;
Support generic types as class ancestors;
Remove archetype-related meta-data.

T Beale

12 May 2018

2.2.2

Improve and update introductory text in the Overview section.

E Sundvall,
T Beale

03 Nov 2017

2.2.1

Remove BMM_CLASSIFIER.conformance_type_name;
Constrain BMM_GENERIC_PARAMETER.name to one character and upper case.

C Nanjo,
T Beale

02 Mar 2017

2.2.0

Rename BMM_CLASSIFIER.as_type_string to type_name and as_conformance_type_string to conformance_type_name.
Move and rename BMM_TYPE.as_display_type_string to BMM_CLASSIFIER.type_signature. Add redefinitions in relevant descendant classes.
Rename BMM_SIMPLE_TYPE_OPEN to BMM_OPEN_TYPE.
Add new class BMM_TYPE_ELEMENT in preparation for BMM 3 refactoring.
Rename BMM_SCHEMA to BMM_MODEL.

T Beale

20 Jun 2016

2.1.0

Initial writing based on ADL Workbench implementation.

T Beale

08 Feb 2016

Acknowledgements

Primary Author

  • Thomas Beale, Ars Semantica; openEHR Foundation Management Board.

Contributors

This specification has benefited from formal and informal input from the openEHR and wider health informatics community. The openEHR Foundation would like to recognise the following people for their contributions.

  • Matija Kejžar, Senior Engineer, Better, Slovenia

  • Patrick Langford, NeuronSong LLC, Utah, USA

  • Claude Nanjo MA African Studies, M Public Health, Cognitive Medical Systems Inc., California, USA

  • Harold Solbrig, Mayo Clinic, Rochester, USA

  • Erik Sundvall PhD, Linkoping University, Sweden

  • Bert Verhees, ROSA Software, The Netherlands.

Trademarks

  • 'openEHR' is a registered trademark of the openEHR Foundation;

  • 'Java' is a registered trademark of Oracle Corporation;

  • 'C#' is a registered trademark of Microsoft;

  • 'OMG' and 'UML' are registered trademarks of the Object Management Group;

  • 'MagicDraw' is a registered trademark of NoMagic Inc;

  • 'Rational Software Architect' is a registered trademark of IBM Corporation.

1. Preface

1.1. Purpose

This document describes the Basic Meta-Model (BMM), a model of object models. It may be considered as an approximate replacement for the UML XMI. It is human-readable and writable, and supports generic types (open and closed), container types, and multiple inheritance. The related BMM Persistence specification defines an object model for a serialised schema form. The latter enables serialisation of a BMM into a concrete syntax such as JSON, ODIN or XML.

1.2. Status

This specification is in the DEVELOPMENT state. The development version of this document can be found at https://specifications.openehr.org/releases/LANG/latest/bmm.html.

Known omissions or questions are indicated in the text with a 'to be determined' paragraph, as follows:

TBD: (example To Be Determined paragraph)

Note
Other than for working with particular tools designed to use BMM, BMM is not a required formalism for implementing openEHR, and other methods of accessing models computably may be used, including UML and software implementations of the openEHR Reference Model.

1.3. Feedback

Feedback may be provided on the openEHR languages specifications forum.

Issues may be raised on the specifications Problem Report tracker.

To see changes made due to previously reported issues, see the LANG component Change Request tracker.

1.4. Conformance

Conformance of a data or software artifact to an openEHR specification is determined by a formal test of that artifact against the relevant openEHR Implementation Technology Specification(s) (ITSs), such as an IDL interface or an XML-schema. Since ITSs are formal derivations from underlying models, ITS conformance indicates model conformance.

1.5. Previous Versions

1.5.1. Version 3.0.0

This version made major changes to the BMM_TYPE hierarchy and semantics, enabling generic inheritance by generic and non-generic classes to be represented.

1.5.2. Version 3.1.0

This version adds meta-classes for computational elements to BMM, including:

  • routines, variables, constants;

  • expressions (including assertions);

  • statements.

It makes various adjustments to the existing model attributes and classes. The BMM remains compatible with P_BMM 2.x, i.e. any existing .bmm file can be parsed to create a v 3.1.0 BMM instance.

1.6. A Note on Language

The elements of meta-models are sometimes named confusingly in the literature and within various programming language technologies. In this specification, we use the following terms:

class

generally refers to a class defined in a model expressed in BMM, i.e. an instance of a BMM meta-class;

meta-class

refers to a class in the BMM itself, such as BMM_CLASS, in order to clearly distinguish it from classes defined in models represented using BMM;

feature (of a class)

any stored or computed element of a class, including constants, attributes (properties) and routines (methods);

property

a stored class feature; also known as 'attribute';

routine

a computed class feature that may be either value-returning (a function) or work-performing (a procedure);

function

a routine that computes and returns a value; typically causes no side-effects in the object;

procedure

a routine that performs a computation; typically has side-effects;

generic (class or type)

a kind of class or type that has parameters of other types; known as 'template' type in some programming languages;

type

generally refers to a type defined in a model expressed in BMM, i.e. an instance of a BMM meta-type;

meta-type

refers to a type in the BMM itself, which is either a class (such as BMM_CLASS) or generically derived (meta-)type in the sense of being an instance generator, where the instances will be concrete type definitions in models represented using BMM.

1.7. Tooling

The openEHR Archie Library fully implements this specification in Java and may be used to build UI tools for compiling, viewing and editing BMM models.

The openEHR ADL Workbench (AWB) fully implements this specification, and provides a convenient way of illustrating BMM semantics. The screenshots used in this specification are all from the ADL Workbench. The tool is written in the Eiffel language, and is available as open source on Github. The BMM libraries can be found in the EOMF Github repository.

2. Overview

2.1. Introduction

One of the key needs in any open computing environment is a computable representation of its own models. This is for a number of purposes, including reasoning about them, performing validation and consistency checking, building software and generating documentation. This is particularly true of openEHR and other archetype-based frameworks, where a further need is to be able to validate archetypes and templates with respect to the reference model, and also to validate runtime instance data against operational templates and the reference model.

A number of computable representations of the openEHR published models have been available in the past. Currently models are represented in two computable forms, namely UML and BMM (i.e. the format described in this specification).

The primary use of the UML expression is for specification publishing. In this role, UML diagrams and static models are built, and then post-processed to correct signatures of class properties and functions. The post-processing corrects UML’s shortcomings and errors in non-singular relations, generic (template) types, and qualified attributes. The result can be used for publishing documentation with feature signatures that are formally correct and will be understood by developers in most programming languages. It can also be serialised and used computably, e.g. in other visualisation or modelling tools. UML’s own serial format, XMI is thus generally unsuitable for such uses, due to the formal errors, as well as its excessive complexity. XMI is also notoriously non-standard across UML tools.

As a result, openEHR introduced the Basic Meta-Model (BMM) in 2009 as a way of representing correct object-oriented semantics of information models for use in tools, along with a serial format by default expressed in the openEHR ODIN syntax.

The BMM provides a standalone alternative to UML/XMI which correctly represents all types, including open and closed generic types, inheritance of generic types, and various other problems with UML. As a meta-model it is adapted to the task, i.e. representing entity types that can appear in object models, rather than the over-generalised semantics of the UML meta-model. This reduced scope, and the fact that it contains no diagram semantics enables its serial form to be human-readable.

2.2. Features

The Basic Meta-Model supports the representation of object models in the ISO RM/ODP information and computational points of view, i.e. in programming terms:

  • definition of classes, properties and methods;

  • delayed routine calls as first-class objects;

  • expressions.

It is designed to enable both human authoring and machine processing, including e.g. extraction of BMM textual schemas from a UML tool or programming language classes. The semantics of the model are heavily influenced by the formal approach to object-orientation described by Bertrand Meyer in Object-oriented Software Construction (Meyer, 1997) and also the Eiffel language, which is significantly better basis for object modelling than the UML 2.x meta-model. The BMM consequently departs from UML in a number of significant ways, and also from the OOSC/Eiffel approach in some aspects (e.g. direct meta-type suport for container types). Its key features are as follows:

  • OO+FP: the Basic Meta-Model is directly based on a combination of Object-oriented class model, functional programming concepts and expression language, rather than being a highly general model like the UML meta-model;

  • Proper type meta-model: types and Classes are distinguished in the meta-model, unlike UML which has no proper formal concept of type beyond a textual name;

  • Full generic types: types as first-order entities enables the proper representation of generic typing and inheritance from open, closed, or partially open generic types, unlike in UML;

  • Container types: such as List<T> and Hash<K,V> have their own meta-types;

  • Enumerated types: supported via the notion of 'range-constrained' classes and also references to external value sets;

  • Built-in Expression Language: fully defined expression meta-model supporting literals, properties, variables, function calls and agents; includes qualifiers;

  • Design by contract (DbC): formally supported via class invariants and routine pre- and post-conditions;

  • Operator / function aliasing: support for mapping symbolic operators to function definitions.

Functional elements are supported via the inclusion of meta-types representing signatures and tuples, enabling the construction of delayed agent calls, known here as agents, and function applications (i.e. function calls).

Note that there is no BMM entity for graphical diagramming semantics. Thus, there is no idea of 'association' distinct from an 'attribute', as per UML, which treats lines between class boxes as formal elements.

2.3. Current State of the Art

2.3.1. UML

One would expect that the IT industry would have fully computable representations of models and diagramming solved, but it is not yet the case. UML 2.x and its associated serialisation format XMI 2.x should in theory mean that complete, interoperable machine expressions of object models would be available in all tools. However the evolution of UML and XMI has not been toward a clear meta-model and language for each of its sub-languages (i.e. static class model, state machine, interaction diagram etc) but rather toward a single universal model of everything in which elements of all of its needs are confusingly buried.

The UML 2.x specifications are exceedingly complex: UML 2.1.2 was specified by two documents, 'Superstructure' (738pp) and 'Infrastructure' (224pp); the UML 2.5.1 specification is only slightly smaller at 796 pages (see the OMG UML page for current specifications). The XMI 2.x specification is correspondingly complex, which seems to have so far prevented reliable tool interoperability (recognised as a critical issue by OMG in 2015). Despite the complexity, there are significant limitations in the UML meta-model, including:

  • the composite or association nature of a class property only being known if it is represented as an association, i.e. a line linking two classes on a UML diagram;

  • the notion of type is not adequately formalised;

  • the meta-model of generic types and container properties is problematic and does not map well to object programming languages;

  • the Design By Contract (DbC) concept (i.e. pre-, post-conditions, class invariants), crucial for proper specifications, is in theory supported via the use of OCL 2.0 constraints in class definitions, but OCL suffers from the same underlying semantic weaknesses as UML;

  • there is no direct support for functional entities, i.e. routine calls as objects (aka 'lambdas').

Experience with various UML tools (up till 2015) highlighted the following problems:

  • poor support for OCL and design by contract in most tools;

  • variable support for generic (i.e. template) classes; even those tools that properly implement the UML 2.5 specification are still very hard to use for defining generic classes because of problems in the specification that remain unaddressed;

  • problems with qualified attributes, which are used to represent identifier references to objects rather than direct references;

  • variable support for XSD generation across tools, where the results are wildly wrong in some tools;

  • in some tools, it is impossible to define an abstract formal model - the only option is to select a particular programming language profile such as Java or C# and thus get locked into the limitations of those languages (messy type systems, weak inheritance semantics, language-specific notion of types such as Array<T>, List<T>, etc.).

Since 2015, the quality of some UML tools has improved, and the XMI generated by some is more reliable. However, XMI generated by different tools is not the same for identical models, and some XMI importers offer numerous switches in order to process the XMI of another tool properly. XMI thus still needs to be processed with care.

Nevertheless, a small number of tools, including MagicDraw (currently used for representing openEHR models for the specifications) and Rational Software Architect (RSA), appear to implement UML 2.5 faithfully. This means that despite the limitations of UML 2.5 (as noted above), models expressed in it can be mostly correctly interpreted and corrected by post-processing for purposes such as code generation and specifications publishing.

Note
Other tools may perform as well or better, and in any case, all tools change over time. No endorsement of a particular tool is intended here.

2.3.2. XML Schema

For some, W3C XML schema represents a way of expressing object models, but it is not semantically suitable for this purpose, primarily due to its problematic non-object-oriented inheritance semantics, lack of generic classes, lack of representation of non-data members, and only marginal support for design by contract. It can be and is often used (including in openEHR) as a derivative serialisation representation.

2.4. Computational Model

The BMM is specified as a structural model representing an abstract syntax tree (AST), which is the result of either in-memory construction (such as by a model authoring tool) or by parsing of a serialised representation of a BMM model. It does not specify an abstract syntax, and indeed, more than one concrete syntax could be parsed to a BMM instance.

Note
for the purposes of explanation, an abstract syntax is used throughout this document that draws freely from mainstream modelling and programming languages.

2.5. Purpose of the BMM

2.5.1. Class Model Representation

The BMM from version 3.0.0 on may be used to represent a full class model at an interface level (i.e. without code for methods) including classes, types, and class feature types including property (i.e. attribute), symbolic constant, manifest value, functions, operators, and procedures.

2.5.2. Meta-Model for Expressions Language

The BMM provides a system of meta-types that act as the basis for a typed expression language. These include references to static entities in scope (constants, variables, properties), literal values, construction of agents (lambda terms), and function calls (lambda applications).

2.5.3. Information Model Representation

Until version 3.0.0, BMM supported only the information point of view, i.e. no computational interface, and in that form, it is often used to express models of data. Tools based on BMM can provide views of an object model expressed in BMM that are particularly useful to information modelling, such as the 'closure' view show below. This is a computed reachability graph of a fully inheritance-flattened class and all properties, including recursive references.

awb class closure
Figure 1. BMM class - closure view

2.5.4. Archetype Modelling

One of the uses of the BMM in the openEHR ADL Workbench and other similar tools is to provide a computable form of the information model for use with domain-level content models, such as archetypes. The following shows an archetype for which each node has its class shown (in colour), and additionally, the inclusion of non-archetyped attributes from the classes of the archetype nodes.

archetype rm
Figure 2. ADL archetype with BMM class properties

Newer tools are able to include the computational features.

The openEHR project makes extensive use of BMM for representing its models for use in tools. The full set of openEHR models in BMM format may be found in the specfications-ITS-BMM repository on Github.

3. Package Structure

3.1. Overview

The BMM packages are as follows:

  • org.openehr.lang.bmm: the BMM

    • model_access: the interface to most features including schema load/reload, generally used by an application as a reflection library;

    • core: the core BMM classes used for in-memory representation of an object model. This consists of a number of sub-packages:

      • model: meta-types representing models and packages;

      • entity: meta-types representing classes and types including enumeration types, represented in the range_constrained sub-package;

      • feature: meta-types representing classes features, i.e. constants, routines, properties;

      • literal_value: meta-types representing literal values;

      • expression: an expression meta-model sufficient for expressing first-order predicate logic expressions, including class invariants and pre- and post-conditions.

Related packages are:

These are illustrated below.

LANG bmm packages
Figure 3. Package Overview

3.2. Class Definitions

3.2.1. BMM_DEFINITIONS Class

Class

BMM_DEFINITIONS

Description

Definitions used by all BMM packages.

Inherit

BASIC_DEFINITIONS

Constants

Signature

Meaning

1..1

Bmm_internal_version: String

Current internal version of BMM meta-model, used to determine if a given schema can be processed by a given implementation of the model.

1..1

Schema_name_delimiter: String = "::"

Delimiter used to separate schema id from package path in a fully qualified path.

1..1

Package_name_delimiter: String = "."

Delimiter used to separate package names in a package path.

1..1

Bmm_schema_file_extension: String = ".bmm"

Extension used for BMM files.

1..1

Type_delimiter: Character = ':'

Appears between a name and a type in a declaration or type signature.

1..1

Generic_left_delimiter: Character = '<'

Left delimiter for generic class and generic type names, as used in List<T>.

1..1

Generic_right_delimiter: Character = '>'

Right delimiter for generic class and generic type names, as used in List<T>.

1..1

Generic_separator: Character = ','

Separator used in Generic types.

1..1

Generic_constraint_delimiter: Character = ':'

Delimiter between formal type parameter and constraint type, as used in Sortable<T: Ordered>.

1..1

Tuple_left_delim: Character = '['

Left delimiter of a Tuple type and also instance. Example:

  • [Integer, String] - a tuple type;

  • [3, "Quixote"] - a tuple.

1..1

Tuple_right_delim: Character = ']'

Right delimiter of a Tuple type and also instance.

1..1

Tuple_separator: Character = ','

Separator used in Tuple types and instances.

1..1

Constraint_left_delim: Character = '«'

Left delimiter used in serial form of instance constrained enumeration.

1..1

Constraint_right_delim: Character = '»'

Right delimiter used in serial form of instance constrained enumeration.

1..1

Metadata_bmm_version: String = "bmm_version"

Attribute name of logical attribute 'bmm_version' in .bmm schema file.

1..1

Metadata_schema_name: String = "schema_name"

Attribute name of logical attribute 'schema_name' in .bmm schema file.

1..1

Metadata_rm_publisher: String = "rm_publisher"

Attribute name of logical attribute 'rm_publisher' in .bmm schema file.

1..1

Metadata_rm_release: String = "rm_release"

Attribute name of logical attribute 'rm_release' in .bmm schema file.

1..1

Metadata_schema_revision: String = "schema_revision"

Attribute name of logical attribute 'schema_revision' in .bmm schema file.

1..1

Metadata_schema_lifecycle_state: String = "schema_lifecycle_state"

Attribute name of logical attribute 'schema_lifecycle_state' in .bmm schema file.

1..1

Metadata_schema_description: String = "schema_description"

Attribute name of logical attribute 'schema_description' in .bmm schema file.

1..1

Metadata_schema_path: String = "schema_path"

Path of schema file.

Functions

Signature

Meaning

1..1

Any_class (): BMM_SIMPLE_CLASS

built-in class definition corresponding to the top `Any' class.

1..1

Any_type (): BMM_SIMPLE_TYPE

Built-in type definition corresponding to the top `Any' type.

1..1

create_schema_id (
a_model_publisher,
a_schema_name,
a_model_release: String[1]
): String

Create schema id, formed from:

a_model_publisher '-' a_schema_name '-' a_model_release

e.g. openehr_rm_1.0.3, openehr_test_1.0.1, iso_13606_1_2008_2.1.2.

4. Model Access Package

4.1. Overview

Note
This package is considered informative within this specification.

The org.openehr.lang.bmm.model_access package provides an interface for the application to load BMM schemas and convert them to BMM model form, and is shown below. In this model, a schema is the serial form of a model or part of a model (i.e. instances of a persistence model like the lang.bmm_persistence model P_XXX classes). One or more schema files are parsed, validated and then converted to create a single BMM_MODEL instance.

LANG bmm.model access
Figure 4. lang.bmm.model_access Package

More than one format for representing serialised BMM models is possible, each having its load, validation and error-reporting logic. The common elements of the load, validate and convert logic are defined by the non format-specific classes in the package, with specific forms of the classes BMM_SCHEMA_DESCRIPTOR and BMM_SCHEMA required for each concrete format. The package above shows the relevant classes for the P_BMM version 2.x format, which is normally saved in .bmm files. Other formats may be saved in files with different extensions.

The singleton class BMM_MODEL_ACCESS acts as the entry point for client software to obtain access to loaded BMM models. Since the latter start as schema files which are typically nested according to an 'include' hierarchy, they must be parsed, validated and merged to create each 'top-level' model. The schemas are accessed via instances of the BMM_SCHEMA_DESCRIPTOR object, one for each schema file. The load() routine of this class loads a BMM schema file by direct deserialisation.

If the file is structurally correct (say ODIN, JSON etc), an in-memory schema instance will result (e.g. P_BMM_SCHEMA in the case of the P_BMM format), and its validate_created method called. If this succeeds, BMM_SCHEMA_DESCRIPTOR.bmm_schema will be set to this instance, of type BMM_SCHEMA. Subsequently, BMM_SCHEMA.merge() will be called repeatedly, which results in each bmm_schema instance being the merged result of its include children and itself. After merging, BMM_SCHEMA_DESCRIPTOR.validate_merged() will be called, and if successful, a call to create_model() will result in BMM_SCHEMA_DESCRIPTOR.model being populated.

Each successfully loaded model is thus instantiated as a BMM_MODEL, and retrievable by calling BMM_MODEL_ACCESS.bmm_model() with a model key, which is a model identifier with full, partial or no version part. In the latter cases, the most recent version model is retrieved for the key. For example, the keys "openEHR_EHR_1.0.4", "openEHR_EHR_1.0", "openEHR_EHR_1", and "openEHR_EHR" will all match the "openEHR_EHR_1.0.4" model, assuming it is the most recent version available. This is convenient for matching models to artefacts (e.g. archetypes) that only mention the model publisher and name, but no version.

The following screenshot shows the BMM schema configuration dialog in the openEHR ADL Workbench, including some meta-data, validation status etc, and also the schema nesting structure. A single hierarchy of schemas corresponds to a single instantiated BMM model.

awb schemas config
Figure 5. BMM schema configuration

The screenshot below shows a number of merged BMM models loaded into the AWB, including some of the packages and classes for the openehr_ehr_extract_1.0.4 model.

awb loaded bmm schemas
Figure 6. BMM schemas loaded

4.2. Class Definitions

4.2.1. BMM_MODEL_ACCESS Class

Class

BMM_MODEL_ACCESS

Description

Access to BMM models that have been loaded and validated from one or more schema sets.

Attributes

Signature

Meaning

0..1

schema_directories: List<String>

List of directories where all the schemas loaded here are found.

0..1

all_schemas: Hash<String,BMM_SCHEMA_DESCRIPTOR>

All schemas found and loaded from schema_directory. Keyed by schema_id.

0..1

bmm_models: Hash<String,BMM_MODEL>

Top-level (root) models in use, keyed by model_id.

0..1

matching_bmm_models: Hash<String,BMM_MODEL>

Validated models, keyed by model_id() and any shorter forms of id, with some or no versioning information. For example, the keys "openEHR_EHR_1.0.4", "openEHR_EHR_1.0", "openEHR_EHR_1", and "openEHR_EHR" will all match the "openEHR_EHR_1.0.4" model, assuming it is the most recent version available.

Functions

Signature

Meaning

0..1

initialise_with_load_list (
a_schema_dirs: List<String>[1],
a_schema_load_list: List<String>[0..1]
)

Initialise with a specific schema load list, usually a sub-set of schemas that will be found in a specified directories a_schema_dirs.

0..1

initialise_all (
a_schema_dirs: List<String>[1]
)

Load all schemas found in a specified directories a_schema_dirs.

0..1

reload_schemas

Reload BMM schemas.

1..1

bmm_model (
a_model_key: String[1]
): BMM_MODEL

Return model containing the model key which is a model_id or any shorter form e.g. model id minus the version. If a shorter key is used, the BMM_MODEL with the most recent version will be selected. Uses matching_bmm_models table to find matches if partial version information is supplied in key.

1..1

has_bmm_model (
a_model_key: String[1]
): Boolean

True if a model for a model_key is available. A model key is a model_id or any shorter form e.g. model id minus the version. If a shorter key is used, the Result s True if a BMM_MODEL with any version exists.

4.2.2. BMM_SCHEMA_DESCRIPTOR Class

Class

BMM_SCHEMA_DESCRIPTOR (abstract)

Description

Descriptor for a BMM schema. Contains a meta-data table of attributes obtained from a mini-ODIN parse of the schema file.

Attributes

Signature

Meaning

0..1

bmm_schema: BMM_SCHEMA

Persistent form of model.

0..1

bmm_model: BMM_MODEL

Computable form of model.

1..1

schema_id: String

Schema id, formed by

{BMM_DEFINITIONS}.create_schema_id( meta_data.item({BMM_DEFINITIONS}.Metadata_model_publisher), meta_data.item({BMM_DEFINITIONS}.Metadata_schema_name), meta_data.item({BMM_DEFINITIONS}.Metadata_model_release)

e.g. openehr_rm_1.0.3, openehr_test_1.0.1, iso_13606_1_2008_2.1.2.

1..1

meta_data: Hash<String, String>

Table of {key, value} of schema meta-data, keys are string values defined by {BMM_DEFINITIONS}.Metadata_* constants.

0..1

includes: List<String>

Identifiers of schemas included by this schema.

Functions

Signature

Meaning

1..1

is_top_level (): Boolean

True if this is a top-level schema, i.e. is the root schema of a 'model'. True if bmm_schema /= Void and then bmm_schema.model_name /= Void.

1..1

is_bmm_compatible (): Boolean

True if the BMM version found in the schema (or assumed, if none) is compatible with that in this software.

0..1

load

Load schema into in-memory form, i.e. a P_BMM_SCHEMA instance, if structurally valid. If successful, p_schema will be set.

0..1

validate_merged

Validate loaded schema and report errors.

0..1

validate_includes (
all_schemas_list: List<String>[0..1]
)

Validate includes list for this schema, to see if each mentioned schema exists in all_schemas list.

0..1

create_model

Create schema, i.e. the BMM_MODEL from one P_BMM_SCHEMA schema.

4.2.3. BMM_MODEL_METADATA Class

Class

BMM_MODEL_METADATA

Description

Core properties of BMM_MODEL, may be used in a serial representation as well, such as P_BMM_SCHEMA.

Attributes

Signature

Meaning

1..1

rm_publisher: String

Publisher of model expressed in the schema.

1..1

rm_release: String

Release of model expressed in the schema as a 3-part numeric, e.g. "3.1.0" .

4.2.4. BMM_SCHEMA Class

Class

BMM_SCHEMA (abstract)

Description

Abstract parent of any persistable form of a BMM model, e.g. P_BMM_SCHEMA.

Inherit

BMM_MODEL_METADATA

Attributes

Signature

Meaning

1..1

bmm_version: String

Version of BMM model, enabling schema evolution reasoning. Persisted attribute.

0..1

includes: Hash<String,BMM_INCLUDE_SPEC>

Inclusion list of any form of BMM model, in the form of a hash of individual include specifications, each of which at least specifies the id of another schema, and may specify a namespace via which types from the included schemas are known in this schema. Persisted attribute.

0..1

bmm_model: BMM_MODEL

Generated by create_bmm_model from persisted elements.

1..1

state: BMM_SCHEMA_STATE

Current processing state.

0..1

model_name: String

Name of this model, if this schema is a model root point. Not set for sub-schemas that are not considered models on their own.

1..1

schema_name: String

Name of model expressed in schema; a 'schema' usually contains all of the packages of one 'model' of a publisher. A publisher with more than one model can have multiple schemas.

1..1

schema_revision: String

Revision of schema.

1..1

schema_lifecycle_state: String

Schema development lifecycle state.

1..1

schema_author: String

Primary author of schema.

1..1

schema_description: String

Description of schema.

0..1

schema_contributors: List<String>

Contributing authors of schema.

Functions

Signature

Meaning

0..1
(abstract)

validate_created

Pre_state: state = State_created
Post_state: passed implies state = State_validated_created

Do some basic validation post initial creation

  • check that package structure is regular:

    • only top-level packages can have qualified names

    • no top-level package name can be a direct parent or child of another (child package must be declared under the parent)

  • check that all classes are mentioned in the package structure

  • check that all models refer to valid packages

0..1
(abstract)

load_finalise

Pre_state: state = State_validated_created
Post_state: state = State_includes_processed or state = State_includes_pending

Finalisation work:

  • convert packages to canonical form, i.e. full hierarchy with no packages with names like aa.bb.cc

  • set up include processing list

0..1
(abstract)

merge (
other: BMM_SCHEMA[1]
)

Pre_state: state = State_includes_pending
Pre_other_valid: includes_to_process.has (included_schema.schema_id)

Merge in class and package definitions from other, except where the current schema already has a definition for the given type or package.

0..1
(abstract)

validate

Main validation prior to generation of bmm_model.

0..1
(abstract)

create_bmm_model

Pre_state: state = P_BMM_PACKAGE_STATE.State_includes_processed

Populate bmm_model from schema.

1..1

read_to_validate (): Boolean

Post_state: state = State_includes_processed

True when validation may be commenced.

1..1

schema_id (): String

Identifier of this schema, used for stating inclusions and identifying files. Formed as:

{BMM_DEFINITIONS}.create_schema_id ( rm_publisher, schema_name, rm_release)

E.g. "openehr_rm_ehr_1.0.4".

4.2.5. BMM_SCHEMA_STATE Enumeration

Enumeration

BMM_SCHEMA_STATE

Description

Enumeration of processing states of a BMM_SCHEMA used by creation and validation routines in BMM_SCHEMA.

Attributes

Signature

Meaning

State_created

Initial state directly after instantiation of schema.

State_validated_created

Initial validation pass after instantiation.

State_includes_pending

State of schema processing if there are still included schemas to process.

State_includes_processed

State when all included schemas have been processed.

4.2.6. BMM_INCLUDE_SPEC Class

Class

BMM_INCLUDE_SPEC

Description

Schema inclusion structure.

Attributes

Signature

Meaning

1..1

id: String

Full identifier of the included schema, e.g. "openehr_primitive_types_1.0.2".

5. Model Structure

5.1. Overview

The core package defines the main BMM meta-model, within which the model sub-package defines the top-level structure of a model which is an instance of the BMM. The UML for this package is shown below.

LANG bmm.core.model
Figure 7. base.bmm.core.model Package - Model structure

5.2. Naming Convention

In a BMM model, names typically appear in the common case-sensitive form used by the model users, and may therefore follow one of a number of common conventions, including 'camel case', 'snake-case' and so on. When used computationally within an instantiated BMM model, it is assumed that case-insensitive matching is used. This means that the class name "Hashable" refers to the same class as "HASHABLE". Note however that underscores are not removed during matching, so that the classes "HashMap" and "HASH_MAP" are understood as different classes.

Note
a future version of BMM may define an option to import schemas using differing naming styles, with transformation into a single style for the target model.

5.3. Model Semantics

In BMM, a model is understood as a set of package and module definitions that are developed and maintained as a unit, by some organisation, and usually having an associated hierarchical namespace. The abstract BMM_MODULE class is the ancestor for any kind of module, which is understood as a container for features of various kinds, including the usual properties, routines, and so on. A BMM model is structured in the same general way as a UML model, i.e. with a hierarchical package containment structure and a set of module definitions, where a commonly used type of module is the class. The following illustrates the structure of a typical 'class' or 'object' model.

bmm structure
Figure 8. BMM model structure

The BMM_MODEL class defines the single instance of each distinct BMM model that may exist within a collection of models, such as shown in the model_access package above. It provides an interface that enables any class definition to be retrieved, as well as various accessor functions to interrogate the model. A BMM Model has a name (the inherited name attribute) that is used to identify the model as a whole within a system using multiple models. It contains a number of other meta-data attributes describing authorship etc, and otherwise contains a list of package and class definitions.

5.3.1. Packages

In BMM, packages have the same role as in UML - as non-semantic organisational logical containers of classes, usually corresponding to file system folders in software implementations. They provide an organisational convenience, and in an instantiated BMM model, contain references to class definitions. A model validity checker ensures that every class is contained within exactly one package.

Package paths are only used in BMM to specify package structures in the serialised form in an efficient way, i.e. by using paths to avoid defining a hierarchy in which only lower packages contain classes. They are not used as namespaces as in UML. Consequently, all classes in a BMM model should be uniquely named.

5.3.2. Use of other Models

A model may use another model. This is the same kind of relationship denoted by the 'import' keyword in many programming languages. In BMM, the use of other models is declared once only, in the using model, rather than on a per-class level as in some languages (e.g. Java). The use of another model makes its contents available for use in declarations (e.g. inheritance) and expressions within the using model. This is achieved by populating the BMM_CLASS.scope attribute with a reference to the used model. In a serial form, a typical syntax such as other_model_name::Class would be used.

5.3.3. Documentation

A documentation attribute is inherited from BMM_MODEL_ELEMENT into BMM_MODULE, BMM_FEATURE and `BMM_PACKAGE_CONTAINER, enabling packages, classes, routines and properties to be individually documented using a keyed table (i.e. Hash) of values.

It is strongly recommended to use the following key /type combinations for the relevant purposes:

  • "purpose": String

  • "keywords": List<String>

  • "use": String

  • "misuse": String

  • "references": String

Other keys and value types may be freely added.

5.3.4. Other Meta-data

The BMM_MODEL_ELEMENT meta-class also defines the attribute extensions of type Hash<String, Any>, to enable representation of meta-data of any type on any model node. This provides a means of extending BMM.

5.4. The Any Class and Type

While a BMM model defines a model in terms of class declarations, it must always have a top class named Any from which all others inherit. Similar to the root class in a typical OOPL type systems (sometimes called 'Object'), the Any class defines semantics true for all objects such as equality (i.e. semantics for an '=' operator) and copying.

A BMM model may define its own Any class, but if it does not, the BMM_MODEL instance representing the model will produce a standard 'Any' class via the any_class_definition() method. This will create the following structure, including a default package structure, and an Any type.

LANG bmm any class
Figure 9. Default Any class

The Any type defined by the model’s Any class, or else the default one above, will be used as the inheritance parent for every class in the model that doesn’t have any other inheritance parent. As a result, the inheritance graph will always have the Any type as its top node.

5.5. Class Definitions

5.5.1. BMM_MODEL_ELEMENT Class

Class

BMM_MODEL_ELEMENT (abstract)

Description

Abstract meta-type of BMM declared model elements. A declaration is a an element of a model within a context, which defines the scope of the element. Thus, a class definition and its property and routine definitions are model elements, but Types are not, since they are derived from model elements.

Attributes

Signature

Meaning

1..1

name: String

Name of this model element.

0..1

documentation: Hash<Any, String>

Optional documentation of this element, as a keyed list.

It is strongly recommended to use the following key /type combinations for the relevant purposes:

  • "purpose": String

  • "keywords": List<String>

  • "use": String

  • "misuse": String

  • "references": String

Other keys and value types may be freely added.

1..1

scope: BMM_MODEL_ELEMENT

Model element within which an element is declared.

0..1

extensions: Hash<Any, String>

Optional meta-data of this element, as a keyed list. May be used to extend the meta-model.

Functions

Signature

Meaning

1..1

is_root_scope (): Boolean

Post_result: Result = (scope = self)

True if this model element is the root of a model structure hierarchy.

5.5.2. BMM_PACKAGE_CONTAINER Class

Class

BMM_PACKAGE_CONTAINER (abstract)

Description

A BMM model component that contains packages and classes.

Inherit

BMM_MODEL_ELEMENT

Attributes

Signature

Meaning

0..1

packages: Hash<String,BMM_PACKAGE>

Child packages; keys all in upper case for guaranteed matching.

1..1
(redefined)

scope: BMM_PACKAGE_CONTAINER

Model element within which a referenceable element is known.

Functions

Signature

Meaning

0..1

package_at_path (
a_path: String[1]
): BMM_PACKAGE

Package at the path a_path.

0..1

do_recursive_packages (
action: EL_PROCEDURE_AGENT[1]
)

Recursively execute action, which is a procedure taking a BMM_PACKAGE argument, on all members of packages.

1..1

has_package_path (
a_path: String[1]
): Boolean

True if there is a package at the path a_path; paths are delimited with delimiter {BMM_DEFINITIONS} Package_name_delimiter.

5.5.3. BMM_PACKAGE Class

Class

BMM_PACKAGE

Description

Abstraction of a package as a tree structure whose nodes can contain other packages and classes.

The name may be qualified if it is a top-level package.

Inherit

BMM_PACKAGE_CONTAINER

Attributes

Signature

Meaning

0..1

members: List<BMM_MODULE>

Member modules in this package.

Functions

Signature

Meaning

0..1

root_classes (): List<BMM_CLASS>

Obtain the set of top-level classes in this package, either from this package itself or by recursing into the structure until classes are obtained from child packages. Recurse into each child only far enough to find the first level of classes.

1..1

path (): String

Full path of this package back to root package.

5.5.4. BMM_MODEL Class

Class

BMM_MODEL

Description

Definition of the root of a BMM model (along with what is inherited from BMM_SCHEMA_CORE).

Inherit

BMM_PACKAGE_CONTAINER, BMM_MODEL_METADATA

Attributes

Signature

Meaning

0..1

class_definitions: Hash<String,BMM_CLASS>

All classes in this model, keyed by type name.

0..1

used_models: List<BMM_MODEL>

List of other models 'used' (i.e. 'imported' by this model). Classes in the current model may refer to classes in a used model by specifying the other class’s scope meta-attribute.

0..1

modules: Hash<String,BMM_MODULE>

All classes in this model, keyed by type name.

Functions

Signature

Meaning

1..1

model_id (): String

Identifier of this model, lower-case, formed from:

<rm_publisher>_<model_name>_<rm_release>

E.g. "openehr_ehr_1.0.4".

1..1

class_definition (
a_name: String[1]
): BMM_CLASS

Retrieve the class definition corresponding to a_type_name (which may contain a generic part).

1..1

type_definition (): BMM_CLASS

Retrieve the class definition corresponding to a_type_name. If it contains a generic part, this will be removed if it is a fully open generic name, otherwise it will remain intact, i.e. if it is an effective generic name that identifies a BMM_GENERIC_CLASS_EFFECTIVE.

1..1

has_class_definition (
a_class_name: String[1]
): Boolean

True if a_class_name has a class definition in the model.

1..1

has_type_definition (
a_type_name: String[1]
): Boolean

True if a_type_name is already concretely known in the system, including if it is generic, which may be open, partially open or closed.

1..1

enumeration_definition (
a_name: String[1]
): BMM_ENUMERATION

Retrieve the enumeration definition corresponding to a_type_name.

0..1

primitive_types (): List<String>

List of keys in class_definitions of items marked as primitive types.

0..1

enumeration_types (): List<String>

List of keys in class_definitions of items that are enumeration types.

1..1

property_definition (): BMM_PROPERTY

Retrieve the property definition for a_prop_name in flattened class corresponding to a_type_name.

1..1

ms_conformant_property_type (
a_bmm_type_name: String[1],
a_bmm_property_name: String[1],
a_ms_property_name: String[1]
): Boolean

True if a_ms_property_type is a valid 'MS' dynamic type for a_property in BMM type a_bmm_type_name. 'MS' conformance means 'model-semantic' conformance, which abstracts away container types like List<>, Set<> etc and compares the dynamic type with the relation target type in the UML sense, i.e. regardless of whether there is single or multiple containment.

1..1

property_definition_at_path (): BMM_PROPERTY

Retrieve the property definition for a_property_path in flattened class corresponding to a_type_name.

1..1

class_definition_at_path (
a_type_name: String[1],
a_prop_path: String[1]
): BMM_CLASS

Retrieve the class definition for the class that owns the terminal attribute in a_prop_path in flattened class corresponding to a_type_name.

0..1

all_ancestor_classes (
a_class: String[1]
): List<String>

Return all ancestor types of a_class_name up to root class (usually Any, Object or something similar). Does not include current class. Returns empty list if none.

1..1

is_descendant_of (
a_class_name: String[1],
a_parent_class_name: String[1]
): Boolean

True if a_class_name is a descendant in the model of a_parent_class_name.

1..1

type_conforms_to (
a_desc_type: String[1],
an_anc_type: String[1]
): Boolean

Check conformance of a_desc_type to an_anc_type; the types may be generic, and may contain open generic parameters like 'T' etc. These are replaced with their appropriate constrainer types, or Any during the conformance testing process.

Conformance is found if:

  • [base class test] types are non-generic, and either type names are identical, or else a_desc_type has an_anc_type in its ancestors;

  • both types are generic and pass base class test; number of generic params matches, and each generic parameter type, after 'open parameter' substitution, recursively passes; type_name_conforms_to test

  • descendant type is generic and ancestor type is not, and they pass base classes test.

1..1

subtypes (
a_type: String[1]
): List<String>

Generate type substitutions for the supplied type, which may be simple, generic (closed, open or partially open), or a container type. In the generic and container cases, the result is the permutation of the base class type and type substitutions of all generic parameters.

Parameters
a_type

Name of a type.

1..1

any_class_definition (): BMM_SIMPLE_CLASS

BMM_SIMPLE_CLASS instance for the Any class. This may be defined in the BMM schema, but if not, use BMM_DEFINITIONS.any_class.

1..1

any_type_definition (): BMM_SIMPLE_TYPE

BMM_SIMPLE_TYPE instance for the Any type.

1..1

boolean_type_definition (): BMM_SIMPLE_TYPE

BMM_SIMPLE_TYPE instance for the Boolean type.

Invariants

Inv_top_level_scope: scope = self

5.5.5. BMM_MODULE Class

Class

BMM_MODULE (abstract)

Description

Meta-type defining a generalised module concept. Descendants define actual structure and contents.

Inherit

BMM_MODEL_ELEMENT

Attributes

Signature

Meaning

0..1

feature_groups: List<BMM_FEATURE_GROUP>

List of feature groups in this class.

0..1

features: List<BMM_FORMAL_ELEMENT>

Features of this module.

1..1
(redefined)

scope: BMM_MODEL

Model within which module is defined.

6. Types

6.1. Overview

One of the foundational distinctions in the BMM is between class and type, in common with the type systems of the modern forms of most object-oriented languages, but in contrast to the UML meta-model. This division is reflected in the two top-level meta-classes BMM_CLASS and BMM_TYPE, and their respective descendants, as shown in the following UML diagram.

LANG bmm.core.entity
Figure 10. base.bmm.core.entity Package - Types

Classes are definitional entities, while types are understood in BMM as the formal generators of instances (where non-abstract). Types are the the basis of static typing in a formal model, and dynamic conformance at execution time, when polymorphic attachment is possible. Most types are specified via the definitions of classes and their constituent parts within a 'model'. Types are used for the following purposes in a BMM model:

  • to define the types of properties;

  • to defined the types of routine parameters and return values;

  • to define formal type parameters in a generic class;

  • to define type(s) of inheritance ancestors of class definitions;

  • to formalise concepts relating to functional programming, including tuples and routine signatures;

  • to determine conformance, which is a relation between types (not classes).

A simple example of typing of properties is shown in the instance diagram below.

bmm entities
Figure 11. BMM Typing

Most types are based on one or more defining class(es), which provide the formal definition for the type. The exceptions are formal generic parameters (e.g. the T in List<T>) and the special built-in types for tuples and routine signatures. The BMM meta-type BMM_TYPE and its descendants define the kinds of types available in a BMM model. The design of the types part of the BMM is based on a taxonomy that makes various distinctions convenient to a formalism intended for modelling rather than pure programming. This leads in particular to the top-level distinction between unitary and container meta-types. The taxonomy is illustrated below, including differentiae.

bmm metatype taxonomy
Figure 12. BMM meta-type taxonomy

BMM_TYPE includes features common to all meta-types:

  • is_abstract: indicates a type based on an abstract class - i.e. one that cannot be directly instantiated;

  • is_primitive: indicates that a type is derived from a primitive class; primitive status has no effect on BMM model semantics, and is provided as a convenience for visualisation and type-system mapping;

  • type_name: the effective type name of an entity; for simple classes, this will just be the class name (BMM_CLASS.name); for generic and container classes it will be generic name such as List<T>, Interval<T> etc; for feature types it will be the declared type, i.e. a simple name, an open type name (e.g. T) or a generic type name (e.g. Interval<Time>);

  • type_signature: a form of the type name that can be used as a fully-defined type signature, which for generic classes includes generic constrainer types, giving a signature such as Interval<T:Ordered>.

Below BMM_TYPE are the abstract meta-type BMM_UNITARY_TYPE and the concrete meta-type BMM_CONTAINER_TYPE and its specialisation BMM_INDEXED_CONTAINER_TYPE. BMM_UNITARY_TYPE is a meta-type for types whose instances are unitary i.e. singular, while the container meta-types correspond to collections of instances. The latter are further described below. This distinction is made to enable BMM to directly represent the notion of collections in the type system rather than treating them in the same way as any other type, which would force modellers (i.e. authors of actual BMM models) to state concrete containment types such as ArrayedList<Packet>, where ArrayedList would have to be defined in the model as well as Packet.

Unitary meta-types are further distinguished as formal generic parameters (BMM_PARAMETER TYPE) and effective types, i.e. concrete unitary types. The former meta-type is used to represent replaceable formal generic parameters (typically 'T', 'U' within types such as List<T> etc) within generic type declarations.

Effective types have as their meta-type BMM_EFFECTIVE_TYPE. Its subtypes are BMM_MODEL_TYPE, a meta-type for types defined by classes in the model (thus characterised by the property base_class: BMM_CLASS), BMM_TUPLE_TYPE, a meta-type for tuples (a list of objects of varying types), and BMM_SIGNATURE, a meta-type representing signatures of routines and typed model elements (properties, variables etc).

BMM_MODEL_TYPE divides into BMM_SIMPLE_TYPE and BMM_GENERIC_TYPE, corresponding to the standard notions of types familiar in modern programming languages. The class definitions of instances (i.e. BMM model class definitions) of these meta-types are available via the property base_class, of meta-type BMM_CLASS for a BMM simple type, and BMM_GENERIC_CLASS for BMM generic type.

These various concrete meta-types are described in more detail below.

6.2. Simple Type

A simple type is a type based only on a simple class, which is a class with no formal generic parameters. An instance of a simple type is fully described by the class on which it is based, with the only difference being the usual object-oriented possibility of polymorphic attachments of sub-objects whose dynamic types conform to their static type counterparts in the original simple type. Thus, for example, a class Organisation may have a property manager of static type Employee. An instance of the simple type Organisation might have its manager property attached to an instance of Manager, which is legal as long as Manager conforms to Employee, which it will do if Manager is defined as a subtype of Employee.

6.2.1. Conformance

Conformance of Simple types follows the inheritance hierarchy via which they are defined, according to the rules:

  • meta-rule: A Simple type can only conform to a Model type, i.e. either another Simple type or a Generic type;

  • concrete rule: A Simple type A conforms to Simple type B iff for base_class of A, all_ancestors() contains B.

6.3. Generic Type

A generic type is a type based on a generic class, which has one or more formal type parameters that are substituted by actual types in its declaration. For example, the generic type Interval<Quantity> can be used in a model that contains the generic class Interval<T:Ordered> and Quantity. The general case is that the generic parameter substitution type (BMM_GENERIC_TYPE.generic_parameters) for any formal parameter (BMM_GENERIC_CLASS.generic_parameters) is of meta-type BMM_UNITARY_TYPE.

A typical programmatic usage of such a type, and its instantiated BMM model structure is shown below.

bmm structure generic 1
Figure 13. Generic type - closed simple

The parameters of a generic type may be:

  • a substitution of a formal parameter from the generic class with a concrete type, including other generic types and container types;

  • an unsubstituted formal parameter, if used as the type of a feature, routine argument etc, whose context has an open generic type to which this parameter conforms.

Consequently, a generic type may be:

  • closed: all formal parameters substituted e.g. Interval<Quantity>;

  • partially closed: at least one formal parameter is substituted e.g. Document<ClinicalContent, U>;

  • open: no formal parameters substituted, e.g. Document<T, U>.

The first case is detected via the function is_closed defined on BMM_GENERIC_TYPE, while the function is_partially_closed distinguishes the latter two cases.

The following shows the BMM instance structure of a generic type that is open.

bmm structure generic 3
Figure 14. Generic type - open

Since the meta-type of BMM_GENERIC_TYPE.generic_parameters in the BMM is BMM_UNITARY_TYPE, constructions such as MyGenericType<List<OtherType>> are prevented, due to the concrete parameter type List<OtherType> being an instance of BMM_CONTAINER_TYPE rather than of BMM_UNITARY_TYPE. Such constructions are nearly always wrong, and not needed in a model expressed in BMM, because containment can be expressed where the formal generic parameter is used, not where the concrete parameter is declared. The following diagram shows the BMM concrete model structure created for a generic type whose formal parameter type is used in this way, i.e. within a container type.

bmm structure generic 2
Figure 15. Generic type - closed container

6.3.1. Conformance

Conformance of Generic types is according to the rules:

  • meta-rule: A Generic type can only conform to another Generic type;

  • concrete rules: A Generic type Ga<Tai, …​> conforms to Generic type Gb<Tbi, …​> iff:

    • for base_class of Ga, all_ancestors() contains Gb; and

    • the number of generic parameters is equal;

    • for each Tai, either

      • Tbi is an open formal parameter, and Tai conforms to any generic constraint type, or;

      • Tai conforms to Tbi.

6.4. Container Meta-types

In object-oriented type theory, 'container' types are generic types whose outer class happens to have the semantics of a container object, such as a list, set etc. Container types such as List<T>, Set<T> and Hash<K,V> are used ubiquitously in object models. In the BMM, containers and non-container generic types are distinguished via the meta-classes BMM_CONTAINER_TYPE and BMM_GENERIC_TYPE respectively. This allows the BMM to treat container types in a special way. A BMM_CONTAINER_TYPE can be thought of as a 1:N counterpart to a BMM_UNITARY_TYPE, such as the type List<Paragraph> with respect to Paragraph. BMM_GENERIC_TYPE is thus used for objects considered to be singular, but whose types are a product of the base class and one or more parameter types, e.g. Interval<Quantity>.

The explicit provision of BMM_CONTAINER_TYPE enables BMM models to mention logical linear container types such as List<T> and Set<T>, on the assumption of their standard semantics in computer science , without worrying about providing concrete types which may be numerous and also variable across programming languages, e.g. ArrayedList<T>, LinkedSet<T>, ArrayedStack<T> and so on.

List and Set semantics are achieved via the BMM_CONTAINER_TYPE attributes is_ordered and is_unique, used in the standard combinations i.e.:

  • is_ordered and not is_unique: List<T>;

  • is_unique: Set<T> (ordered or not);

  • not is_ordered and not is_unique: Bag<T>.

The following diagram shows how the container type List<Paragraph>, declared as the type of an attribute paragraphs in a class Document, is represented in a BMM model.

bmm structure container
Figure 16. Container Type

The semantics of indexed containers, commonly known under the type names Hash<K,V>, HashMap<K,V>, HashTable<K,V>, Dictionary<K,V> and so on, are represented by the meta-type BMM_INDEXED_CONTAINER_TYPE, which inherits from BMM_CONTAINER_TYPE, and adds the property index_type. The latter type represents the key type, which must be such that hash values can be generated, and may be any type, but practically speaking, is almost always a String, Integer, or a Date/Time type.

The following diagram shows how the container type Hash<String, Person> is represented in a BMM model.

bmm structure indexed container
Figure 17. Indexed Container Type

6.4.1. Conformance

Conformance of Container types is according to the rules:

  • meta-rule: A Container type can only conform to another Container type;

  • concrete rules:

    • A Container type Ca<Va> conforms to Container type Cb<Vb> conforms to iff:

      • for base_class of Ca, all_ancestors() contains Cb; and Va conforms to Vb.

    • An indexed Container type Ca<Ka, Va> conforms to indexed Container type Gb<Kb, Vb> iff:

      • for base_class of Ca, all_ancestors() contains Cb; Kb conforms to Kb and Va conforms to Vb.

6.5. Bult-in Meta-types

BMM includes a small number of built-in meta-types that do not have corresponding model-source classes. These are shown in the following UML and described in the following sub-sections.

LANG bmm.core.entity builtin
Figure 18. Built-in meta-types

6.5.1. Tuple Meta-type

The meta-type BMM_TUPLE_TYPE enables the type of a tuple i.e. an array of objects each of which may be of any type, to be stated in terms of other types. This is mostly used to state the type of a set of arguments in the BMM_SIGNATURE class, but standalone tuple types may also be used in a model, providing roughly the effect of an anonymous class (or a struct in C/C++).The notional type Tuple defined by BMM_TUPLE_TYPE is treadted as a BMM built-in, and is therefore not stated in any BMM model.

6.5.1.1. Conformance

Conformance of Tuple types is according to the rules:

  • meta-rule: A Tuple type can only conform to another Tuple type;

  • concrete rules: A Tuple type Tuple[Tai, …​] conforms to Tuple type Tuple[Tbi, …​] iff:

    • for each Tai, Tai conforms to Tbi.

The practical effect of this is that longer tuples may conform to shorter tuples. For example, the tuple type [Document, String, Integer] conforms to the tuple type [Document].

6.5.2. Signature Meta-type

Within any typed formalism, any entity declared as having a type also has a signature. In BMM, this is is the case for any kind of feature of a class, including constants, properties, and routines. The signature of a feature is a formal construct capturing the type structure of the feature. The simplest type of signature is that of properties and constants, which may be expressed formally in a typical abstract syntax as follows:

    T_result

This indicates that both have a return type, being the type of the value they are attached to at execution time.

The general form of routine signatures is as follows:

    Function <[T_arg1, T_arg2, ...], T_result>    -- Function type
    Procedure <[T_arg1, T_arg2, ...]>             -- Procedure type

In the above, the construction [Type, …​] represents a type-tuple. Strictly speaking, the 'Function' and 'Procedure' are unnecessary, since they can be inferred from just the pure signature. However, for readability they are recommended.

Typical examples of function signatures are as follows:

    Function <[], Date>                          -- a 0-order function like current_date
    Function <[Real, Real], Real>                -- a 2nd-order function like '*' for the domain R
    Function <[Integer, Integer], Integer>       -- a 2nd-order function like 'add' for the domain I

Typical procedure signatures include the following:

    Procedure <[]>                               -- a 0-order (argumentless) procedure
    Procedure <[Real]>                           -- a 1st-order procedure for the domain R
    Procedure <[String, Integer]>                -- a procedure taking a String and an Integer argument

In order to support functional semantics such as function-as-object, the notion of signature is defined in BMM as a first order meta-type, BMM_SIGNATURE and descendants. Instances of BMM_SIGNATURE represent any kind of signature and reference the meta-type of the evaluated form via result_type, which may be of any BMM meta-type.

BMM_ROUTINE_TYPE is the meta-type of any kind of agent (i.e. lambda) and provides argument_types, whose meta-type is BMM_TUPLE_TYPE (See [Tuple Type]). The descendant BMM_PROCEDURE_TYPE specialises the return type to the built-in type BMM_STATUS_TYPE (see below), used to represent the status of a procedure call.

The following signatures state the types 'any function' and 'any procedure':

    Function <>                                  -- any function
    Procedure <>                                 -- any procedure

As for the Tuple meta-type, the notional Signature meta-type is a BMM built-in, and is not itself defined in any BMM model.

6.5.2.1. Conformance

Conformance of Signature types is as follows:

  • meta-rule: A Signature type can only conform to another Signature type;

  • concrete rules:

    • all specific Function signatures conform to the signature Function;

    • all specific Procedure signatures conform to the signature Procedure;

    • the conformance of specific Function or Procedure signatures to another Function or Procedure signature is such that:

      • the number of argument types accord and;

      • the type conformance of each corresponding argument and result type (for functions) follows the rules for conformance given by the meta-types of those types.

6.5.3. Status Meta-type

The meta-type BMM_STATUS_TYPE is provided to represent the return type of procedure calls, i.e. of which the pure formal type is often denoted Void or None in programming languages. Using a special return type simplifies the meta-model of routines, since without it, procedures create an anomaly within a system in which all other class features have a result type. Within BMM, procedures are considered to be state-changing actions, and the Status return type enables call and/or execution status information to be returned. Usually this can be ignored, and procedures can be called without assignment. This approach is similar to that of Haskell, in which procedure calls return the 'unit' type.

6.6. Type Conformance

An algorithm to determine conformance of two type-names (e.g. to implement BMM_MODEL.type_conforms_to()) is as follows:

Boolean type_conforms_to (String a_type, anc_type)
{
    BMM_TYPE_NAME a_type_name, anc_type_name;

    if attached create_type_name_from_string (a_a_type) as a_type_name and
        attached create_type_name_from_string (anc_type) as anc_type_name
    {
        base_class = a_type_name.name;
        anc_base_class = anc_type_name.name;

        if (base_class.is_case_insensitive_equal (anc_base_class) or else
            class_definition (base_class).has_ancestor_class (anc_base_class))
        {
            BMM_CLASS bmm_def_class = class_definition (base_class);

            // ---- Tuple types

            // ---- Signature types ----

            // ---- Generic types
            // handle case where formal generic names appear in type name
            if (valid_generic_type_name (a_type) and bmm_def_class instanceOf (BMM_GENERIC_CLASS) {

                // in the case of both being generic, we need to compare generics
                // to start with, the number of generics must match
                BMM_CLASS anc_bmm_def_class = class_definition (anc_base_class);
                if (valid_generic_type_name (anc_type) and anc_bmm_def_class instanceOf (BMM_GENERIC_CLASS)) {
                    ArrayedList<String> a_type_gen_params = a_type_name.generic_parameters_type_list;
                    ArrayedList<String> anc_type_gen_params = anc_type_name.generic_parameters_type_list;

                    if (a_type_gen_params.count = anc_type_gen_params.count) {

                        Iterator<String> this_gen_parms_it = a_type_gen_params.iterator();
                        Iterator<String> other_gen_parms_it = anc_type_gen_params.iterator();

                        Boolean result = True;
                        String a_type_gen_type, anc_type_gen_type;

                        while (this_gen_parms_it.hasNext() && other_gen_parms_it.hasNext() || !result) {
                            // first we convert any open generic parameters to their conformance types
                            // We assume type names of 1 letter are open parameters
                            String this_gen_parm = this_gen_parms_it.next();
                            String other_gen_parm = other_gen_parms_it.next();
                            if (formal_generic_parameter_name (this_gen_parm))
                                a_type_gen_type = this_bmm_gen_class.generic_parameter_conformance_type (this_gen_parm);
                            else
                                a_type_gen_type = this_gen_parm;

                            if (formal_generic_parameter_name (other_gen_parm))
                                anc_type_gen_type = other_bmm_gen_class.generic_parameter_conformance_type (other_gen_parm);
                            else
                                anc_type_gen_type = other_gen_parm;

                            -- now do the test
                            result = type_conforms_to (a_type_gen_type, anc_type_gen_type);
                        }

                        return result;
                    }

                }
                // Conforms - case where anc type is not provided in generic form, but desc is
                // e.g. Interval<Integer> conforms to Interval
                else
                    return True;
            }
            // in the following case, the descendant type is not generic,
            // so the ancestor type cannot be either, for conformance
            else
                return not valid_generic_type_name (anc_type);
        }
    }
}

6.7. Model Theoretic Questions

The above model produces a number of outcomes that are not necessarily immediately obvious or expected, including:

  • Inheritance is from classes to types rather than classes;

  • A Generic type parameter can only be a unitary type, i.e. not a container type;

  • Tuple and Signature types are pure types, i.e. not defined in generating model other than by implication due to use as routine argument lists;

  • In theory, a Signature type could be a BMM_GENERIC_TYPE descendant but the specialisation restriction would make the meta-model more complex for no obvious benefit.

6.8. Class Definitions

6.8.1. BMM_TYPE Class

Class

BMM_TYPE (abstract)

Description

Abstract idea of specifying a type in some context. This is not the same as 'defining' a class. A type specification is essentially a reference of some kind, that defines the type of an attribute, or function result or argument. It may include generic parameters that might or might not be bound. See subtypes.

Functions

Signature

Meaning

1..1
(abstract)

type_name (): String

Formal string form of the type as per UML.

1..1

type_signature (): String

Signature form of the type name, which for generics includes generic parameter constrainer types E.g. Interval<T:Ordered>.

Defaults to the value of type_name().

1..1
(abstract)

is_abstract (): Boolean

If true, indicates a type based on an abstract class, i.e. a type that cannot be directly instantiated.

1..1
(abstract)

is_primitive (): Boolean

If True, indicates that a type based solely on primitive classes.

1..1
(abstract)

unitary_type (): BMM_UNITARY_TYPE

Type with any container abstracted away; may be a formal generic type.

1..1
(abstract)

effective_type (): BMM_EFFECTIVE_TYPE

Type with any container abstracted away, and any formal parameter replaced by its effective constraint type.

1..1
(abstract)

flattened_type_list (): List<String>

Completely flattened list of type names, flattening out all generic parameters.

6.8.2. BMM_UNITARY_TYPE Class

Class

BMM_UNITARY_TYPE (abstract)

Description

Parent of meta-types that may be used as the type of any instantiated object that is not a container object.

Inherit

BMM_TYPE

Functions

Signature

Meaning

1..1
(effected)

unitary_type (): BMM_UNITARY_TYPE

Result = self.

6.8.3. BMM_EFFECTIVE_TYPE Class

Class

BMM_EFFECTIVE_TYPE (abstract)

Description

Meta-type for a concrete, unitary type that can be used as an actual parameter type in a generic type declaration.

Inherit

BMM_UNITARY_TYPE

Functions

Signature

Meaning

1..1
(effected)

effective_type (): BMM_EFFECTIVE_TYPE

Result = self.

1..1
(abstract)

type_base_name (): String

Name of base generator type, i.e. excluding any generic parts if present.

6.8.4. BMM_PARAMETER_TYPE Class

Class

BMM_PARAMETER_TYPE

Description

Definition of a generic parameter in a class definition of a generic type.

Inherit

BMM_UNITARY_TYPE

Attributes

Signature

Meaning

1..1

name: String

Name of the parameter, e.g. 'T' etc. The name is limited to 1 character and upper-case.

0..1

type_constraint: BMM_EFFECTIVE_TYPE

Optional conformance constraint that must be the name of a defined type.

0..1

inheritance_precursor: BMM_PARAMETER_TYPE

If set, is the corresponding generic parameter definition in an ancestor class.

Functions

Signature

Meaning

1..1

flattened_conforms_to_type (): BMM_EFFECTIVE_TYPE

Result is either conforms_to_type or inheritance_precursor.flattened_conforms_to_type.

1..1
(redefined)

type_signature (): String

Signature form of the open type, including constrainer type if there is one, e.g. T:Ordered.

1..1
(effected)

is_primitive (): Boolean

Result = False - generic parameters are understood by definition to be non-primitive.

1..1
(effected)

is_abstract (): Boolean

Result = False - generic parameters are understood by definition to be non-abstract.

1..1
(effected)

type_name (): String

Return name.

1..1
(effected)

flattened_type_list (): List<String>

Result is either flattened_conforms_to_type.flattened_type_list or the Any type.

1..1
(effected)

effective_type (): BMM_EFFECTIVE_TYPE

Generate ultimate conformance type, which is either flattened_conforms_to_type or if not set, 'Any'.

Invariants

Inv_generic_name: name.count = 1 and name.is_upper

6.8.5. BMM_MODEL_TYPE Class

Class

BMM_MODEL_TYPE (abstract)

Description

A type that is defined by a class (or classes) in the model.

Inherit

BMM_EFFECTIVE_TYPE

Attributes

Signature

Meaning

0..1

value_constraint: BMM_VALUE_SET_SPEC

1..1

base_class: BMM_CLASS

Base class of this type.

Functions

Signature

Meaning

1..1
(effected)

type_base_name (): String

Result = base_class.name.

1..1
(effected)

is_primitive (): Boolean

Result = base_class.is_primitive.

6.8.6. BMM_SIMPLE_TYPE Class

Class

BMM_SIMPLE_TYPE

Description

Type reference to a single type i.e. not generic or container type.

Inherit

BMM_MODEL_TYPE

Attributes

Signature

Meaning

1..1
(redefined)

base_class: BMM_SIMPLE_CLASS

Defining class of this type.

Functions

Signature

Meaning

1..1
(effected)

type_name (): String

Result is base_class.name.

1..1
(effected)

is_abstract (): Boolean

Result is base_class.is_abstract.

1..1
(effected)

flattened_type_list (): List<String>

Result is base_class.name .

1..1

effective_base_class (): BMM_SIMPLE_CLASS

Main design class for this type, from which properties etc can be extracted.

6.8.7. BMM_GENERIC_TYPE Class

Class

BMM_GENERIC_TYPE

Description

Meta-type based on a non-container generic class, e.g. Packet<Header>.

Inherit

BMM_MODEL_TYPE

Attributes

Signature

Meaning

1..1

generic_parameters: List<BMM_UNITARY_TYPE>

Generic parameters of the root_type in this type specifier. The order must match the order of the owning class’s formal generic parameter declarations, and the types may be defined types or formal parameter types.

1..1
(redefined)

base_class: BMM_GENERIC_CLASS

Defining generic class of this type.

Functions

Signature

Meaning

1..1
(effected)

type_name (): String

Return the full name of the type including generic parameters, e.g. DV_INTERVAL<T>, TABLE<List<THING>,String>.

1..1
(redefined)

type_signature (): String

Signature form of the type, which for generics includes generic parameter constrainer types E.g. Interval<T:Ordered>.

1..1
(effected)

is_abstract (): Boolean

True if base_class.is_abstract or if any (non-open) parameter type is abstract.

1..1
(effected)

flattened_type_list (): List<String>

Result is base_class.name followed by names of all generic parameter type names, which may be open or closed.

1..1

is_partially_closed (): Boolean

Returns True if there is any substituted generic parameter.

1..1

effective_base_class (): BMM_GENERIC_CLASS

Effective underlying class for this type, abstracting away any container type.

1..1

is_open (): Boolean

True if all generic parameters from ancestor generic types have been substituted in this type.

6.8.8. BMM_BUILTIN_TYPE Class

Class

BMM_BUILTIN_TYPE (abstract)

Description

Parent of built-in types, which are treated as being primitive and non-abstract.

Inherit

BMM_EFFECTIVE_TYPE

Constants

Signature

Meaning

1..1

base_name: String = 

Base name (built-in typename).

Functions

Signature

Meaning

1..1
(effected)

is_abstract (): Boolean

Return False.

1..1
(effected)

is_primitive (): Boolean

Return True.

1..1
(effected)

type_base_name (): String

Return base_name.

1..1
(effected)

type_name (): String

Return base_name.

6.8.9. BMM_TUPLE_TYPE Class

Class

BMM_TUPLE_TYPE

Description

Built-in meta-type representing the type of a tuple, i.e. an array of any number of other types. This includes both container and unitary types, since tuple instances represent concrete objects.

Note that both open and closed generic parameters are allowed, as with any generic type, but open generic parameters are only valid within the scope of a generic class.

Inherit

BMM_BUILTIN_TYPE

Constants

Signature

Meaning

1..1
(redefined)

base_name: String = "Tuple"

Base name (built-in).

Attributes

Signature

Meaning

1..1

item_types: Hash<String,BMM_TYPE>

List of types of the items of the tuple, keyed by purpose in the tuple.

Functions

Signature

Meaning

1..1
(effected)

flattened_type_list (): List<String>

Return the logical set (i.e. unique types) from the merge of flattened_type_list() called on each member of item_types.

6.8.10. BMM_SIGNATURE Class

Class

BMM_SIGNATURE

Description

Built-in meta-type that expresses the type structure of any referenceable element of a model. Consists of potential arguments and result, with constraints in descendants determining the exact form.

Inherit

BMM_BUILTIN_TYPE

Constants

Signature

Meaning

1..1
(redefined)

base_name: String = "Signature"

Base name (built-in).

Attributes

Signature

Meaning

1..1

result_type: BMM_TYPE

Result type of signature.

Functions

Signature

Meaning

1..1
(effected)

flattened_type_list (): List<String>

Return the logical set (i.e. unique items) consisting of argument_types.flattened_type_list() and result_type.flattened_type_list().

6.8.11. BMM_PROPERTY_TYPE Class

Class

BMM_PROPERTY_TYPE

Description

Meta-type for property and variable signatures.

Inherit

BMM_SIGNATURE

6.8.12. BMM_ROUTINE_TYPE Class

Class

BMM_ROUTINE_TYPE

Description

Meta-type for routine objects.

Inherit

BMM_SIGNATURE

Constants

Signature

Meaning

1..1
(redefined)

base_name: String = "Routine"

Base name (built-in).

Attributes

Signature

Meaning

0..1

argument_types: BMM_TUPLE_TYPE

Type of arguments in the signature, if any; represented as a type-tuple (list of arbitrary types).

6.8.13. BMM_FUNCTION_TYPE Class

Class

BMM_FUNCTION_TYPE

Description

Meta-type for function object signatures.

Inherit

BMM_ROUTINE_TYPE

Constants

Signature

Meaning

1..1
(redefined)

base_name: String = "Function"

Base name (built-in).

6.8.14. BMM_PROCEDURE_TYPE Class

Class

BMM_PROCEDURE_TYPE

Description

Form of routine specific to procedure object signatures, with result_type being the special Status meta-type

Inherit

BMM_ROUTINE_TYPE

Constants

Signature

Meaning

1..1
(redefined)

base_name: String = "Procedure"

Base name (built-in).

Attributes

Signature

Meaning

0..1
(redefined)

result_type: BMM_STATUS_TYPE

Result type of a procedure.

6.8.15. BMM_STATUS_TYPE Class

Class

BMM_STATUS_TYPE

Description

Built-in meta-type representing action status, e.g. result of a call invocation.

Inherit

BMM_BUILTIN_TYPE

Constants

Signature

Meaning

1..1
(redefined)

base_name: String = "Status"

Base name (built-in).

6.8.16. BMM_CONTAINER_TYPE Class

Class

BMM_CONTAINER_TYPE

Description

Meta-type that specifies linear containers with a generic parameter corresponding to the type of contained item, and whose container type is a generic type such as List<T>, Set<T> etc.

Inherit

BMM_TYPE

Attributes

Signature

Meaning

1..1

container_class: BMM_GENERIC_CLASS

The type of the container. This converts to the root_type in BMM_GENERIC_TYPE.

1..1

item_type: BMM_UNITARY_TYPE

The container item type.

0..1

is_ordered: Boolean
{default = true}

True indicates that order of the items in the container attribute is considered significant and must be preserved, e.g. across sessions, serialisation, deserialisation etc. Otherwise known as 'list' semantics.

0..1

is_unique: Boolean
{default = false}

True indicates that only unique instances of items in the container are allowed. Otherwise known as 'set' semantics.

Functions

Signature

Meaning

1..1
(effected)

type_name (): String

Return full type name, e.g. List<ELEMENT>.

1..1
(effected)

is_abstract (): Boolean

Post_is_abstract: Result = container_type.is_abstract

True if the container class is abstract.

1..1
(effected)

flattened_type_list (): List<String>

Post_result: Result = item_type.flattened_type_list

Flattened list of type names of item_type, i.e. item_type.flattened_type_list().

1..1
(effected)

unitary_type (): BMM_UNITARY_TYPE

Return item_type.

1..1
(effected)

is_primitive (): Boolean

Post_result: Result = item_type.is_primitive

True if item_type is primitive.

1..1
(effected)

effective_type (): BMM_EFFECTIVE_TYPE

Return item_type.effective_type().

6.8.17. BMM_INDEXED_CONTAINER_TYPE Class

Class

BMM_INDEXED_CONTAINER_TYPE

Description

Meta-type of linear container type that indexes the contained items in the manner of a standard Hash table, map or dictionary.

Inherit

BMM_CONTAINER_TYPE

Attributes

Signature

Meaning

1..1

index_type: BMM_SIMPLE_TYPE

Type of the element index, typically String or Integer, but may be a numeric type or indeed any type from which a hash value can be derived.

Functions

Signature

Meaning

1..1
(effected)

type_name (): String

Return full type name, e.g. HashMap<String, ELEMENT>.

7. Classes

7.1. Overview

This section describes the semantics of the BMM_CLASS meta-class, its sub-types, constituent parts and relationships. Classes in BMM are generators of types, and are what is authored (i.e. 'programmed') in order to create a model or program text.

The formally typed parts of a class are collectively known as features, and consist of functions, procedures, constants and properties, which appear in feature groups. Within a class, all features are contained in the features attribute (inherited from BMM_MODULE), with features of each specific type being referenced in a dedicated map (BMM_CLASS.properties etc). The following UML illustrates classes and relationships to constituent feature meta-types. Features are described in detail in the following section.

LANG bmm.core class
Figure 19. base.bmm.core Package - Classes

Class definitions are the definitional basis of a BMM model, i.e. they are the means of defining the types that are statically used in the model, and the dynamic types generated at runtime. Types are thus derived entities.

The top meta-class BMM_CLASS defines two properties inherent in classes defined in a model, and derived in resulting types: is_abstract and is_primitive. The Boolean attribute is_abstract indicates a class that cannot be directly instantiated. The attribute is_primitive indicates that a class is considered to be part of a primitive type set (typically corresponding to primitive types in another type system). Primitive status has no effect on BMM model semantics, and is provided as a convenience for visualisation and type-system mapping.

BMM distinguishes between simple and generic class definitions via two descendants of BMM_CLASS, i.e. BMM_SIMPLE_CLASS and BMM_GENERIC_CLASS, with the first providing a concrete form of BMM_CLASS that applies to non-generic classes, and the latter defining the additional semantics of generic classes. The meta-type BMM_ENUMERATION is a specialisation of BMM_SIMPLE_CLASS used to represent enumeration classes in BMM models. The meta-types are further described below.

7.2. Simple Classes

The simplest type of class definition in a model is an instance of the meta-type BMM_SIMPLE_CLASS, and has a 1:1 relationship with its type. Such classes might be specified in the following abstract syntax:

class DvQuantity
{
    feature
        // feature definitions
}

class Observation
{
    feature
        // feature definitions
}

7.3. Generic Classes

The generic class meta-type BMM_GENERIC_CLASS adds generic parameters to BMM_CLASS, enabling formal generic parameters to be represented. Each such parameter is expressed using an instance of BMM_PARAMETER_TYPE which names the parameter and optionally allows a type constraint to be associated with it, in the usual object-oriented fashion. In BMM, formal parameters have single-letter names, such as 'T', 'U' etc, following typical usage in programming languages. A generic class may also be primitive. Generic classes can be defined in a syntax similar to the following.

//
// a primitive generic class with an open type parameter
//
primitive class List <T>

feature
    // feature definitions


//
// a generic class with a constrained type parameter
//
class DvInterval <T:DvOrdered>

feature
    // feature definitions

//
// a primitive generic class two type parameters
//
primitive class HashMap <K:Ordered, V>

feature
    // feature definitions

The following example shows a generic class Interval<T:Ordered>, which is a class Interval with one formal parameter T constrained to be of type Ordered or any descendant.

awb generic class
Figure 20. BMM class - generic class

7.4. Range-Constrained Classes

The value range of any defined type is by default open, meaning that its instances may take any value allowed by the type definition. For primitive types such as String and Integer, this means that any String or Integer value is a valid instance of their respective types. For complex types, instances are composed of hierarchies of values which are similarly unconstrained with respect to their types.

A useful derived form of any concrete type definition (i.e. instance of BMM_EFFECTIVE_TYPE in a model) is one that constrains the legal values of its instances to a particular set of values. The Pascal language provided a well-known precedent, 'sub-range types' that could restrict primitive type value ranges. BMM supports two kinds of range constraint: enumeration and 'value sets'. The additional meta-classes are shown below.

LANG bmm.core.range constrained
Figure 21. bmm.core.range_constrained Package - Constrained-range Meta-Types, including Enumeration

7.4.1. Enumerated Types

In modern programming languages, the enumerated type is the most common kind of range constraint mechanism. In Java for example, an enumeration is a finite set of labels each associated with a singleton value object - either automatically assigned integers, or else programmatically associated instances of any other kind. Enumerated types are supported in BMM via the BMM_ENUMERATION meta-type and descendants.

An enumerated type could in theory be based on any BMM defined type, i.e. any simple or generic type, since instances of either could be constrained. BMM makes the simplification that an enumerated type can only be based on a BMM simple type, which means that in the defined model, an enumeration of a closed generic type Gen<T_subst> is achieved by first defining a simple type based on the closed generic type via inheritance, e.g. a type Gen_T_subst that inherits from Gen<T_subst> can be used as the ancestor of a BMM enumeration type.

For this reason, the BMM_ENUMERATION meta-type is defined as a descendant of BMM_SIMPLE_CLASS, and may have only one ancestor. The value enumeration is represented via a set of enumeration labels (item_names) and constant values (item_values), the latter of which must be of the type represented in the concrete model by the instance of the ancestor class.

Since String and Integer valued enumerations are by far the most common in real models, two descendant classes BMM_ENUMERATION_STRING and BMM_ENUMERATION_INTEGER are provided, which fix the values and types to String and Integer respectively.

The following diagram shows the BMM instance structure corresponding to an attribute declaration lifecycle: TaskLifecycle in a class Order.

bmm structure enumeration
Figure 22. Integer-based Enumeration Type

The following shows the same class in an abstract syntax.

// an Integer-based enumeration
enumeration class TASK_LIFECYCLE

feature -- Enumeration Literals

    planned   = 0;
    available = 1;
    cancelled = 2;
    aborted   = 3;
    abandoned = 4;
    underway  = 5;
    suspended = 6;
    resumed   = 7;
    completed = 8;

The following screenshot shows how this enumeration class appears within a BMM model.

awb enumeration
Figure 23. Enumeration Example

The following shows another enumeration class, this time based on the String type.

// a String-based enumeration
enumeration class ContractStatus

feature -- Enumeration Literals
    initial   = "Initial";
    cancelled = "Cancelled";
    active    = "Active";
    completed = "Completed";

The types String and Integer are assumed to be defined via primitive classes of the same names.

7.4.2. Value-set Types

Another form of range constraint that occurs in many models is the use of 'coded terms' that represent codes from e.g. ISO or IANA value sets such as ISO 639 (languages) and IANA media types. These are particularly prevalent in type systems used in the biosciences where object models routinely include attributes of a Coded Term type that refer to terminologies such as SNOMED CT, WHO ICD10 etc. In such models, it is typical to want to define an attribute being not just of a Coded Term type, but also limited to a particular terminology (such as a coded attribute representing 'language'), or even a specific 'value set' from such a terminology.

The same kind of constraint may be applied to any kind of model type, for example a type representing Medication may be constrained to be instantiated only as instances defined by a medications database. This kind of constraint is known here as a value set, following the common usage in the biomedical sciences, and is supported in a different way than enumerations. The latter is a common programming concept which always involves a dedicated type representing the enumeration. Since the required value-sets are represented explicitly in the model but in an external database or other resource, the constraint is limited to a reference to the relevant resource, and is applied directly to the use of a type within a feature definition, rather than requiring the definition of a new type.

Accordingly, BMM provides the attribute value_constraint: BMM_VALUE_SET_SPEC defined on BMM_MODEL_TYPE. The BMM_VALUE_SET_SPEC meta-type contains two String attributes resource_id and value_set_id which may be used to define a resource (equivalently a namespace) and an identifier of a value set within that resource. BMM does not impose any particular format or resolution algorithm on these identifiers - it is assumed that they can be correctly defined and used within the context of the concrete model usage.

Consequently, an attribute within a standard concrete model such as language: CodedTerm could now be expressed notionally as language: CodedTerm <<iso::639-*>> or language: CodedTerm <<iso::languages>>. The construction within the <<>> is parsed into two pieces around the :: separator, which are then used to populate the BMM_VALUE_SET_SPEC for a type.

The following diagram shows the meta-model structure corresponding to an attribute declaration language: CodedText whose instances are constrained to be from a value-set iso_639-2 within the resource namespace iso.

bmm structure value set
Figure 24. Value-set Constrained Type

The following shows a possible abstract syntax value-set type definition.

// a Value-set type
class Document

feature
    property language: CodedText <<"iso::iso_639-2">> [1];

7.5. Class Qualifiers

The following sub-sections describe qualifiers that may be used on any class definition to achieve a specific status within the model system. BMM qualifiers are designed to map to typical features in programming languages.

7.5.1. Abstract Classes

Any class definition in a BMM model may be marked as 'abstract', to indicate that it cannot be directly instantiated. This qualifier generally maps to the concept of abstract classes in most OOPLs. It may be specified in an abstract syntax as follows.

abstract class ENTRY

feature
    // feature definitions

7.5.2. Primitive Type Classes

Class definitions within a BMM model may be marked as 'primitive', enabling them to be visualised and queried as a separate group without otherwise changing the semantics of the entity in the BMM meta-type system. This is normally done to distinguish 'built-in' types used by a model from the classes for which the model was created. An abstract syntax definition may look as follows:

primitive class Integer

feature
    // feature definitions


primitive class String

feature
    // feature definitions

The following shows part of a BMM model in which a number of classes are classified as primitive (shown in light and dark grey).

awb primitive types
Figure 25. Primitive classes

Primitive classes are normal BMM classes, other than being marked primitive for convenience, and do not have different semantics.

7.6. Class Invariants

A class defined within a model may include invariants, i.e. assertions relating to its state that hold true before and after all public routine calls. Assertions are instances of the class BMM_ASSERTION, which is a tagged Boolean-valued Expression.

The following shows classes with invariants.

//
// a class with simple invariants
//
class COMPOSITION

feature
    // feature definitions

invariant
    Is_archetype_root: is_archetype_root
    Content_valid: content /= Void implies not content.is_empty


//
// a class with more complex invariants
//
class VERSIONED_COMPOSITION

feature
    // feature definitions

invariant
    Archetype_node_id_valid: all_versions.for_all (
        agent (v: VERSION) {
            v.archetype_node_id.is_equal (all_versions.first.archetype_node_id);
        }
    )

    Persistent_validity: all_versions.for_all (
        agent (v: VERSION) {
            v.is_persistent = all_versions.first.data.is_persistent;
        }
    )

7.7. Inheritance

Inheritance in BMM is a relation between a class and one or more types, rather than classes, as in many class-based formalisms. This is primarily to allow classes to be based on specific generic types, rather than just the 'open' type represented by the underlying classes. Multiple inheritance is permitted, with same-named features from different types being treated as clashes needing resolution. See Section 13.1 for a detailed description.

7.8. Model Theoretic Questions

The class meta-model as defined here entails certain choices that have consequences, including:

  • All Enumeration types are based on literal values (i.e. not only names), which may be of any concrete type, including constructed types.

7.9. Class Definitions

7.9.1. BMM_CLASS Class

Class

BMM_CLASS (abstract)

Description

Meta-type corresponding a class definition in an object model. Inheritance is specified by the ancestors attribute, which contains a list of types rather than classes. Inheritance is thus understood in BMM as a stated relationship between classes. The equivalent relationship between types is conformance.

Note
unlike UML, the name is just the root name, even if the class is generic. Use type_name() to obtain the qualified type name.

Inherit

BMM_MODULE

Attributes

Signature

Meaning

0..1

ancestors: Hash<String,BMM_MODEL_TYPE>

List of immediate inheritance parents.

1..1

package: BMM_PACKAGE

Package this class belongs to.

0..1

properties: Hash<String,BMM_PROPERTY>

Properties defined in this class (subset of features).

1..1

source_schema_id: String

Reference to original source schema defining this class. Useful for UI tools to determine which original schema file to open for a given class for manual editing.

0..1

immediate_descendants: List<BMM_CLASS>

List of computed references to base classes of immediate inheritance descendants, derived when members of ancestors are attached at creation time.

1..1

is_override: Boolean

True if this definition overrides a class of the same name in an included schema.

0..1

static_properties: Hash<String,BMM_STATIC>

Static properties defined in this class (subset of features).

0..1

functions: Hash<String,BMM_FUNCTION>

Functions defined in this class (subset of features).

0..1

procedures: Hash<String,BMM_PROCEDURE>

Procedures defined in this class (subset of features).

0..1

is_primitive: Boolean
{default = false}

True if this class represents a type considered to be primitive in the type system, i.e. any typically built-in or standard library type such as String, Date, Hash<K,V> etc.

0..1

is_abstract: Boolean
{default = false}

True if this class is marked as abstract, i.e. direct instances cannot be created from its direct type.

0..1

invariants: List<BMM_ASSERTION>

0..1

creators: Hash<String,BMM_PROCEDURE>

Subset of procedures that may be used to initialise a new instance of an object, and whose execution will guarantee that class invariants are satisfied.

0..1

converters: Hash<String,BMM_PROCEDURE>

Subset of creators that create a new instance from a single argument of another type.

0..1
(redefined)

features: List<BMM_FEATURE>

Features of this module.

Functions

Signature

Meaning

1..1
(abstract)

type (): BMM_MODEL_TYPE

Generate a type object that represents the type for which this class is the definer.

0..1

all_ancestors (): List<String>

List of all inheritance parent class names, recursively.

0..1

all_descendants (): List<String>

Compute all descendants by following immediate_descendants.

0..1

suppliers (): List<String>

List of names of immediate supplier classes, including concrete generic parameters, concrete descendants of abstract statically defined types, and inherited suppliers. (Where generics are unconstrained, no class name is added, since logically it would be Any and this can always be assumed anyway). This list includes primitive types.

0..1

suppliers_non_primitive (): List<String>

Same as suppliers minus primitive types, as defined in input schema.

0..1

supplier_closure (): List<String>

List of names of all classes in full supplier closure, including concrete generic parameters; (where generics are unconstrained, no class name is added, since logically it would be Any and this can always be assumed anyway). This list includes primitive types.

1..1

package_path (): String

Fully qualified package name, of form: package.package.

1..1

class_path (): String

Fully qualified class name, of form: package.package.CLASS with package path in lower-case and class in original case.

1..1

is_primitive (): Boolean

True if this class is designated a primitive type within the overall type system of the schema. Set from schema.

1..1

is_abstract (): Boolean

True if this class is abstract in its model. Value provided from an underlying data property set at creation or construction time.

0..1

features ()

List of all feature definitions introduced in this class.

0..1

flat_features ()

Consolidated list of all feature definitions from this class and all inheritance ancestors.

0..1

flat_properties (): List<BMM_PROPERTY>

List of all properties due to current and ancestor classes, keyed by property name.

Invariants

Inv_constructors: for_all p in creators : procedures.has(p)

Inv_converters: for_all p in converters : creators.has(p) and p.arity() = 1

7.9.2. BMM_SIMPLE_CLASS Class

Class

BMM_SIMPLE_CLASS

Description

Definition of a simple class, i.e. a class that has no generic parameters and is 1:1 with the type it generates.

Inherit

BMM_CLASS

Functions

Signature

Meaning

1..1
(effected)

type (): BMM_SIMPLE_TYPE

Generate a type object that represents the type of this class. Can only be an instance of BMM_SIMPLE_TYPE or a descendant.

7.9.3. BMM_GENERIC_CLASS Class

Class

BMM_GENERIC_CLASS

Description

Definition of a generic class in an object model.

Inherit

BMM_CLASS

Attributes

Signature

Meaning

1..1

generic_parameters: Hash<String,BMM_PARAMETER_TYPE>

List of formal generic parameters, keyed by name. These are defined either directly on this class or by the inclusion of an ancestor class which is generic.

Functions

Signature

Meaning

0..1
(redefined)

suppliers (): List<String>

Add suppliers from generic parameters.

1..1
(effected)

type (): BMM_GENERIC_TYPE

Generate a fully open BMM_GENERIC_TYPE instance that corresponds to this class definition

1..1

generic_parameter_conformance_type (
a_name: String[1]
): String

For a generic class, type to which generic parameter a_name conforms e.g. if this class is Interval <T:Comparable> then the Result will be the single type Comparable. For an unconstrained type T, the Result will be Any.

7.9.4. BMM_ENUMERATION Class

Class

BMM_ENUMERATION

Description

Definition of an enumeration class, understood as a class whose value range is constrained extensionally, i.e. by an explicit enumeration of named singleton instances.

Only one inheritance ancestor is allowed in order to provide the base type to which the range constraint is applied.

The common notion of a set of literals with no explicit defined values is represented as the degenerate subtype BMM_ENUMERATION_INTEGER, whose values are 0, 1, …​

Inherit

BMM_SIMPLE_CLASS

Attributes

Signature

Meaning

0..1

item_names: List<String>

The list of names of the enumeration. If no values are supplied, the integer values 0, 1, 2, …​ are assumed.

0..1

item_values: List<BMM_PRIMITIVE_VALUE>

Optional list of specific values. Must be 1:1 with item_names list.

Functions

Signature

Meaning

1..1

name_map (): Hash<String, String>

Map of item_names to item_values (stringified).

7.9.5. BMM_ENUMERATION_STRING Class

Class

BMM_ENUMERATION_STRING

Description

String-based enumeration meta-type.

Inherit

BMM_ENUMERATION

Attributes

Signature

Meaning

0..1
(redefined)

item_values: List<BMM_STRING_VALUE>

Optional list of specific values. Must be 1:1 with item_names list.

7.9.6. BMM_ENUMERATION_INTEGER Class

Class

BMM_ENUMERATION_INTEGER

Description

Integer-based enumeration meta-type.

Inherit

BMM_ENUMERATION

Attributes

Signature

Meaning

0..1
(redefined)

item_values: List<BMM_INTEGER_VALUE>

Optional list of specific values. Must be 1:1 with item_names list.

7.9.7. BMM_VALUE_SET_SPEC Class

Class

BMM_VALUE_SET_SPEC

Description

Definition of a range-constrained class whose value range is defined by reference to a 'value set' within an external resource, e.g. a reference data service.

Attributes

Signature

Meaning

1..1

resource_id: String

Identifier of a resource (typically available as a service) that contains legal values of a specific type. This is typically a URI but need not be.

1..1

value_set_id: String

Identifier of a value set within the resource identified by resource_id, which specifies the set of legal values of a type. This might be a URI, but need not be.

8. Class Features

8.1. Overview

Within the definition of each class in a BMM model are found the declarations of its features. Variables are declared within routines. Features and variables are kinds of formal elements, i.e. typed entities having a signature (BMM_FORMAL_ELEMENT). This section describes class features, their parts, and their semantics.

8.1.1. Feature Taxonomy

Features are understood in BMM as typed entities referenceable within a module context. Class features consist of the formal sub-parts of a class, namely:

  • routines: procedures and functions;

  • properties: mutable static definitions, described in detail in previous sections;

  • constants: immutable static values.

The taxonomy of feature declarations is shown below in the simplified view of the BMM feature meta-model.

LANG bmm.core.feature taxonomy
Figure 26. Feature taxonomy

8.1.2. Class Model

The full feature meta-model is shown below.

LANG bmm.core.feature
Figure 27. base.bmm.core.feature package

8.1.3. Feature Groups and Visibility

Features are arranged within a class in feature groups, each represented by an instance of a meta-type BMM_FEATURE_GROUP, shown in the following UML view.

LANG bmm.core.feature group
Figure 28. Feature Groups

By default there is at least one feature group called "feature". Feature groups may be given any name, and are usually used to group features on the basis of things like:

  • meta-type, e.g. a group called "rules" limited to publicly visible functions only;

  • logical feature type, e.g. commands, queries, factory methods etc.

The primary purpose of feature groups is to represent specific meta-data that naturally applies to more than one feature in general, and is thus convenient to represent on a logical container rather than repeat individually. Feature group meta-data is recorded in the properties attribute. A feature group may also set default visibility for all features in the group.

Selective visibility of features to external clients is expressed in the attributes BMM_FEATURE_GROUP.visibility with potential overrides achieved using BMM_FEATURE.visibility, i.e. at an individual feature level. Visibility is defined using sub-types of the abstract meta-class BMM_VISIBILITY.

TBD: define visibility meta-model; probably need to support C++/Java approach and type-based.

8.1.4. Differential and Flat Form

In modelling or programming terms, the features defined on a particular class within a model constitute the features it introduces with respect to its inheritance parent(s). We can think of this list of features as the differential set. A 'top-level' class with no declared inheritance ancestor is considered to inherit by default from the Any class, and its feature set is relationally differential to the top class.

In contrast, the effective set of features for an instance at runtime is the result of evaluating these lists of features down the inheritance hierarchy to obtain the flat set of features. The features properties and flat_properties defined on BMM_CLASS provide access to these two lists for any class.

8.1.5. Signatures

All features are formal computational entities, and therefore have formal signatures (described in Section 6.5.2), represented by BMM_FORMAL_ELEMENT.signature. A standard taxonomy of feature signature types is illustrated below, in which properties have signatures with no arguments (this is also true for argument-less functions), and procedures have the special built-in Status result type (BMM_STATUS_TYPE), following the meta-model of various functional languages, e.g. Haskell (in which procedure invocations return the special 'unit' type).

signature taxonomy
Figure 29. Signature taxonomy

8.1.6. Synthesis due to Generic Parameter Substitution

Due to the possibility of generating concrete types via substitution of concrete generic parameters for formal parameters of generic classes, new concrete types of features may routinely result anywhere in a fully computed in-memory BMM model. BMM allows such features to be synthesised with their resulting concrete types rather than their 'source-defined' open parameter types, and provides the Boolean flag is_synthesised_generic on BMM_FEATURE to mark any such synthesised feature. An example of the use of this is described below in Section 13.1.2.

8.2. Properties

Properties are features whose values are stored rather than computed on each reference, and are represented by the meta-type BMM_INSTANTIABLE_FEATURE. They are distinguished from routines by having no arguments (signature of degree zero).

8.2.1. Static Properties

Static properties are properties whose values are pre-defined by some means, and read-only during execution (is_nullable is False).

8.2.1.1. Constants

Constant class features (meta-type BMM_CONSTANT) correspond to classic constants in most computer languages, and are defined with a literal value.

The following abstract syntax illustrates how constants may be defined in a BMM model.

class BASIC_DEFINITIONS

feature
    //
    // simple constants
    //
    constant CR: Character = '\015';
    constant LF: Character = '\012';

    //
    // constant of complex type
    // TODO: correct JSON (maybe YAML?) or other syntax
    //
    constant SafeSpeed: Interval<Quantity> = |0.0 km/h .. 60.0 km/h|;
8.2.1.2. Singletons

The other kind of static property is computed once during execution (meta-type BMM_SINGLETON) via an argumentless function-body. Like a value-based constant, it has the same value for all instances of the containing type, including descendant and generically derived types.

The following illustrates how singletons may be defined in a BMM model.

feature
    //
    // constant generated by a function call
    //
    singleton criticalPressure: ProxyVar<Quantity>
        Result := {ProxyVar<Quantity>}({Quantity}(0.0, "kPa"), {Quantity}(150.0, "kPa"));

8.2.2. Writable Properties

Writable class properties are defined via the meta-class BMM_PROPERTY, and its subtypes which distinguish unitary properties (single-valued attributes in a class) from container properties (multiply-valued attributes).

The BMM_PROPERTY meta-type defines semantics common to all properties, including is_composition, which indicates whether the property reference instantiates a part-of relationship or an association.

8.2.2.1. Unitary versus Container Properties

Single-valued properties in a BMM model are instances of the type BMM_UNITARY_PROPERTY, and have as their type the meta-type BMM_UNITARY_TYPE. Container properties are instances of the meta-type BMM_CONTAINER_PROPERTY, which adds the attribute cardinality, enabling the possible number of container elements to be constrained (this corresponds to the multiplicities used at the end of UML associations). The meta-type BMM_INDEXED_CONTAINER_PROPERTY adds the attribute index_type, enabling representation of indexed concrete container types such as Hash<K,V> etc.

A typical example of properties of class is shown below, in which the flattened property view of a class OBSERVATION includes the inherited properties other_participations and links properties exemplifying the container property meta-type:

awb class properties
Figure 30. BMM class - properties view

The following illustrates how various kinds of properties may appear in a BMM model. The first two properties are associations, used to represent references to shared objects (including singletons), while the remainder are normal compositional sub-parts, i.e. owned sub-instances that will cease to exist when the parent object is destroyed. All of the properties are single-valued, other than other_participations, which is defined as a container property with cardinality [*] (i.e. 0..*) and 'set' semantics.

abstract class ENTRY extend CARE_ENTRY

feature -- Locale
    association property language: CODE_PHRASE <<"iso::iso_639-2">> [0..1];
    association property encoding: CODE_PHRASE <<"iana::character-sets">> [0..1];

feature -- Access
    composition property protocol: ITEM_STRUCTURE[1];
    composition property guideline_id: OBJECT_REF[0..1];
    composition property subject: PARTY_PROXY[0..1];
    composition property other_participations: PARTICIPATION[*]{set};

8.2.3. Semantic Level

TBD: this BMM feature requires review

Properties also include two other Boolean meta-data items, is_im_runtime and is_im_infrastructure, which can be used to classify property values in a model according to a 'semantic level', which roughly corresponds to the continuum from domain-specific to infrastructure. These may be individually set, or both may be False. The three meaningful value settings are as follows:

  • both False: the value of the property is considered to be design-time constrainable;

  • is IM runtime: True if the property value is only knowable at runtime, as is typically the case for identifiers, dates etc;

  • is infrastructure: True if the property is not a user- or business-oriented property, but something required by software design, e.g instance identifier, meta-data etc.

The above screenshot also includes properties have different settings of the is_im_runtime and is_im_infrastructure meta-data flags: property names in black are neither; those in grey are IM runtime (guideline_id, workflow_id), and those in light grey are infrastructure properties (language, encoding, uid, etc).

8.3. Functions and Procedures

Functions and procedures are kinds of routine, which are computational features of a class. The classes BMM_FUNCTION, BMM_PROCEDURE and BMM_ROUTINE respectively provide the meta-model for definitions of the two types of routine.

The formal parameter definitions of both kinds of routines are represented by an ordered list of instances of the meta-class BMM_PARAMETER, which is defined as a kind of variable. A formal parameter may optionally have the read/write direction defined, which indicates whether the variable contains an input value, should only be written to, or both, i.e. read then written to. The is_nullable meta-attribute inherited from BMM_FEATURE indicates whether each parameter is mandatory or not.

An additional feature of the meta-model for functions is the notion of operator, which supports the representation of a function call in a formal expression as an operator symbol with one or two operands, in the typical form found in programming languages and first order logics. The BMM approach considers an operator as an optional addition to any function of arity 1 or 2 that may reasonably be represented in an abstract syntax using operator syntax. Operators thus support the use of expressions like weight > 90 to mean weight.gt (90), where weight is of type Real, and the function gt(other: Real) is defined.

Any routine may have pre- and/or post-conditions defined for it, represented in BMM by BMM_ASSERTIONs populating the pre_conditions and post_conditions attributes of BMM_ROUINE. An Assertion is a tagged Boolean Expression.

The following abstract syntax illustrates the various elements of function definitions.

abstract class DV_AMOUNT
    inherit
        DV_QUANTIFIED

feature -- Arithmetic Operations

    function equal (other: DV_AMOUNT[1]): Boolean[1]
        alias {infix '='};

    function less_than (other: DV_AMOUNT[1]): Boolean[1]
        alias {infix '<'};

feature -- Arithmetic Operations

    function add (other: DV_AMOUNT[1]): DV_AMOUNT[1]
        alias {infix '+'};

    function subtract (other: DV_AMOUNT[1]): DV_AMOUNT[1]
        alias {infix '-'};

    function multiply (val: Real[1]): DV_AMOUNT[1]
        alias {infix '*'};

    function divide (val: Real[1]): DV_AMOUNT[1]
        alias {infix '/', infix '÷'};

8.3.1. Pre- and Post-conditions

All BMM routine definitions may include pre- and/or post-conditions, with the semantics of Djikstra’s weakest pre-condition logic (Dijkstra (1976)), Object-Z (Smith (2000)) and the Eiffel language (Meyer (1997)).

The essential semantics are as follows:

  • pre-conditions specify truth conditions on public object state and/or parameters that must hold for the routine to execute correctly;

    • if a pre-condition is not met at the moment of routine call, the client (caller) is at fault;

  • post-conditions specify truth conditions on public object state and/or result (in the case of functions) that will hold at the end of routine execution;

    • if a post-condition is not met at the moment of routine completion, the routine is at fault, i.e. contains bugs.

The use of pre- and post-conditions is also known as design by contract (DbC), a term introduced by Meyer, and is widely used in general IT, particularly in specification languages such as OMG Interface Definition Language (IDL).

The following shows how a routine contract may be specified in an abstract syntax.

class I_EHR_SERVICE

feature -- Creation

    create_ehr_with_id (
        an_ehr_id: UUID[1];
        an_ehr_status: EHR_STATUS[0..1]
    ): UUID[1]
        pre_condition
            No_duplicate: not has_ehr (an_ehr_id)
        post_condition
            Has_ehr: has_ehr (Result)

8.3.2. Creators and Converters

In common with may OOPLs, BMM classes may specify creators, i.e. instance-creating procedures, known as 'constructors' in some OOPLs. These are just a subset of all procedures known in BMM_CLASS.procedures that when executed will satisfy the class invariants. A further subset of the creators are single-argument converters which can initialise a new instance from an instance of another type. Converter routines are typically used to support type conversion in expressions, e.g. String to Date etc. These two subsets are formally defined as the creators and converters reference lists of procedures on BMM_CLASS, as shown in the following UML view.

LANG bmm.core.class creators
Figure 31. Class creators and converters

Creators and converters might be distinguished among other procedures in an abstract syntax as follows.

class Date

inherit
    Temporal

convert
    create_from_string

feature -- Creators

    procedure create_from_string (a_date_str: String[1])

    procedure create (a_day, a_month, a_year: Integer[1])

feature -- Modification

    procedure set_day (a_day: Integer[1])

8.3.3. Routine Body

BMM supports the definition of statements, i.e. implementation within a ROUTINE as well as 'external' routines, which are represented by an instance of the meta-class BMM_ROUTINE_EXTERNAL. These classes are shown in the following UML view.

LANG bmm.core.feature routine
Figure 32. Routine body

The meta-model of statements is described in detail in Section 12.

8.4. Variables

At the finest level of detail of a model definition are what are typically thought of as variables within a routine scope. These may be either writable (BMM_WRITABLE_VARIABLE) or read-only (BMM_READONlY_VARIABLE) variables.

Writable variables include local variables (variables declared locally within a routine) and the special pre-defined variable Result, which is automatically available within any function. Read-only variables include parameters (declared in the arguments part of a routine declaration), and the special variable Self, which represents the current instance.

8.5. Model Theoretic Questions

The features meta-model as defined here entails certain choices that have consequences. One question is how to treat procedures. In a mathematical sense, procedures have no return type, and therefore should not be allowed within 'normal' expressions. However in a computational sense, a procedure call normally performs some state-changing action (for example, authenticating to a database), and it is potentially useful to obtain an execution status and use it in further logic. The choice made in BMM is to treat procedures as typed entities, with a result meta-type and concrete type of Status (represented by BMM_STATUS_TYPE). This is similar to the approach in various languages such as Haskell and Kotlin, which both have a 'unit' type for the same purpose. This approach allows procedures to fit within the typed framework without complicating the meta-model.

Procedure calls are prevented from appearing in expressions by the expressions part of the meta-model, and can only appear on their own (the usual case) or in an assignment statement in which a result status value may be obtained from the Status object. This value may then be used in normal expressions, e.g. a case statement.

8.6. Class Definitions

8.6.1. BMM_FORMAL_ELEMENT Class

Class

BMM_FORMAL_ELEMENT (abstract)

Description

A formal element having a name, type and a type-based signature.

Inherit

BMM_MODEL_ELEMENT

Attributes

Signature

Meaning

1..1

type: BMM_TYPE

Declared or inferred static type of the entity.

0..1

is_nullable: Boolean
{default = false}

True if this element can be null (Void) at execution time. May be interpreted as optionality in subtypes..

Functions

Signature

Meaning

1..1
(abstract)

signature (): BMM_SIGNATURE

Formal signature of this element, in the form:

name [arg1_name: T_arg1, …​][:T_value]

Specific implementations in descendants.

1..1

is_boolean (): Boolean

Post_result: Result = type().equal( {BMM_MODEL}.boolean_type_definition())

True if type is notionally Boolean (i.e. a BMM_SIMPLE_TYPE with type_name() = 'Boolean').

8.6.2. BMM_FEATURE Class

Class

BMM_FEATURE (abstract)

Description

A module-scoped formal element.

Inherit

BMM_FORMAL_ELEMENT

Attributes

Signature

Meaning

0..1

is_synthesised_generic: Boolean
{default = false}

True if this feature was synthesised due to generic substitution in an inherited type, or further constraining of a formal generic parameter.

0..1

feature_extensions: List<BMM_FEATURE_EXTENSION>

Extensions to feature-level meta-types.

1..1

group: BMM_FEATURE_GROUP

Group containing this feature.

1..1
(redefined)

scope: BMM_CLASS

Model element within which an element is declared.

8.6.3. BMM_FEATURE_GROUP Class

Class

BMM_FEATURE_GROUP

Description

A logical group of features, with a name and set of properties that applies to the group.

Attributes

Signature

Meaning

1..1

name: String
{default = "feature"}

Name of this feature group; defaults to 'feature'.

1..1

properties: Hash<String, String>

Set of properties of this group, represented as name/value pairs. These are understood to apply logically to all of the features contained within the group.

0..1

features: List<BMM_FEATURE>

Set of features in this group.

0..1

visibility: BMM_VISIBILITY

Optional visibility to apply to all features in this group.

8.6.4. BMM_VISIBILITY Class

Class

BMM_VISIBILITY (abstract)

Description

Abstract parent of visibility representation.

TODO: define schemes; probably need to support C++/Java scheme as well as better type-based schemes.

8.6.5. BMM_INSTANTIABLE_FEATURE Class

Class

BMM_INSTANTIABLE_FEATURE (abstract)

Description

Meta-type representing instantiable features, i.e. features that are created as value objects.

Inherit

BMM_FEATURE

Invariants

Inv_signature_no_args: signature().arguments = Void

8.6.6. BMM_STATIC Class

Class

BMM_STATIC (abstract)

Description

Meta-type for static (i.e. read-only) properties.

Inherit

BMM_INSTANTIABLE_FEATURE

Invariants

Inv_not_nullable: is_nullable = False

8.6.7. BMM_CONSTANT Class

Class

BMM_CONSTANT

Description

An immutable, static value-returning element scoped to a class. The value is the result of the evaluation of the generator, which may be as simple as a literal value, or may be any expression, including a function call.

Inherit

BMM_STATIC

Attributes

Signature

Meaning

1..1

generator: BMM_LITERAL_VALUE

Literal value of the constant.

8.6.8. BMM_SINGLETON Class

Class

BMM_SINGLETON

Description

Meta-type for static value properties computed once by a function invocation.

Inherit

BMM_STATIC

Attributes

Signature

Meaning

1..1

generator: BMM_ROUTINE_DEFINITION

Generator of the value of this static property.

8.6.9. BMM_PROPERTY Class

Class

BMM_PROPERTY (abstract)

Description

Meta-type of a writable property definition within a class definition of an object model. The is_composition attribute indicates whether the property has sub-part or an association semantics with respect to the owning class.

Inherit

BMM_INSTANTIABLE_FEATURE

Attributes

Signature

Meaning

0..1

is_im_runtime: Boolean
{default = false}

True if this property is marked with info model im_runtime property.

0..1

is_im_infrastructure: Boolean
{default = false}

True if this property was marked with info model im_infrastructure flag.

0..1

is_composition: Boolean
{default = false}

True if this property instance is a compositional sub-part of the owning class instance. Equivalent to 'composition' in UML associations (but missing from UML properties without associations) and also 'cascade-delete' semantics in ER schemas.

Functions

Signature

Meaning

1..1

existence (): Multiplicity_interval

Interval form of 0..1, 1..1 etc, derived from is_nullable.

1..1

display_name (): String

Name of this property to display in UI.

8.6.10. BMM_UNITARY_PROPERTY Class

Class

BMM_UNITARY_PROPERTY

Description

Meta-type of for properties of unitary type.

Inherit

BMM_PROPERTY

Attributes

Signature

Meaning

1..1
(redefined)

type: BMM_UNITARY_TYPE

Declared or inferred static type of the entity.

8.6.11. BMM_CONTAINER_PROPERTY Class

Class

BMM_CONTAINER_PROPERTY

Description

Meta-type of for properties of linear container type, such as List<T> etc.

Inherit

BMM_PROPERTY

Attributes

Signature

Meaning

0..1

cardinality: Multiplicity_interval

Cardinality of this container.

1..1
(redefined)

type: BMM_CONTAINER_TYPE

Declared or inferred static type of the entity.

Functions

Signature

Meaning

1..1
(redefined)

display_name (): String

Name of this property in form name: ContainerTypeName<>.

8.6.12. BMM_INDEXED_CONTAINER_PROPERTY Class

Class

BMM_INDEXED_CONTAINER_PROPERTY

Description

Meta-type of for properties of linear container type, such as Hash<Index_type, T> etc.

Inherit

BMM_CONTAINER_PROPERTY

Attributes

Signature

Meaning

1..1
(redefined)

type: BMM_INDEXED_CONTAINER_TYPE

Declared or inferred static type of the entity.

Functions

Signature

Meaning

1..1
(redefined)

display_name (): String

Name of this property in form name: ContainerTypeName<IndexTypeName, …​>.

8.6.13. BMM_ROUTINE Class

Class

BMM_ROUTINE (abstract)

Description

A feature defining a routine, scoped to a class.

Inherit

BMM_FEATURE

Attributes

Signature

Meaning

0..1

parameters: List<BMM_PARAMETER>

Formal parameters of the routine.

0..1

pre_conditions: List<BMM_ASSERTION>

Boolean conditions that must evaluate to True for the routine to execute correctly, May be used to generate exceptions if included in run-time build.

A False pre-condition implies an error in the passed parameters.

0..1

post_conditions: List<BMM_ASSERTION>

Boolean conditions that will evaluate to True if the routine executed correctly, May be used to generate exceptions if included in run-time build.

A False post-condition implies an error (i.e. bug) in routine code.

0..1

definition: BMM_ROUTINE_DEFINITION

Body of a routine, i.e. executable program.

Functions

Signature

Meaning

1..1

arity (): Integer

Return number of arguments of this routine.

8.6.14. BMM_FUNCTION Class

Class

BMM_FUNCTION

Description

A formal element with signature of the form: name ({arg:TArg}*):TResult. A function is a computed (rather than data) element, generally assumed to be non-state-changing.

Inherit

BMM_ROUTINE

Attributes

Signature

Meaning

0..1

operator_definition: BMM_OPERATOR

Optional details enabling a function to be represented as an operator in a syntactic representation.

1..1

result: BMM_RESULT

Automatically created Result variable, usable in body and post-condition.

Invariants

Operator_validity: operator_def /= Void implies arity in |1..2|

Inv_result_type: type = Result.type

8.6.15. BMM_OPERATOR Class

Class

BMM_OPERATOR

Description

Definition of a symbolic operator associated with a function.

Attributes

Signature

Meaning

1..1

position: BMM_OPERATOR_POSITION

Position of operator in syntactic representation.

1..1

symbols: List<String>

Set of String symbols that may be used to represent this operator in a textual representation of a BMM model.

1..1

name: String

Formal name of the operator, e.g. 'minus' etc.

8.6.16. BMM_OPERATOR_POSITION Enumeration

Enumeration

BMM_OPERATOR_POSITION

Description

Enumeration of possible position of operator in a syntactic representation for operators associated with 1- and 2- degree functions.

Attributes

Signature

Meaning

prefix

Prefix operator position: operator comes before operand.

infix

Infix operator position: operator comes between left and right operands.

8.6.17. BMM_PROCEDURE Class

Class

BMM_PROCEDURE

Description

A formal element with signature of the form: name ({arg:TArg}*):TStatus, where TStatus is the built-in type BMM_STATUS_TYPE.. A procedure is a computed (rather than data) element, generally assumed to be state-changing, and is usually called in the form name ({arg:TArg}*).

Inherit

BMM_ROUTINE

Attributes

Signature

Meaning

1..1
(redefined)

type: BMM_STATUS_TYPE

Declared or inferred static type of the entity.

Functions

Signature

Meaning

1..1
(effected)

signature (): BMM_PROCEDURE_TYPE

Formal signature of this element, in the form:

name [arg1_name: T_arg1, …​][:T_value]

Specific implementations in descendants.

8.6.18. BMM_VARIABLE Class

Class

BMM_VARIABLE (abstract)

Description

A routine-scoped formal element.

Inherit

BMM_FORMAL_ELEMENT

Attributes

Signature

Meaning

1..1
(redefined)

scope: BMM_ROUTINE

Routine within which variable is defined.

8.6.19. BMM_WRITABLE_VARIABLE Class

Class

BMM_WRITABLE_VARIABLE (abstract)

Description

Meta-type for writable variables, including the special variable Result.

Inherit

BMM_VARIABLE

8.6.20. BMM_LOCAL Class

Class

BMM_LOCAL

Description

A routine local variable (writable).

Inherit

BMM_WRITABLE_VARIABLE

8.6.21. BMM_RESULT Class

Class

BMM_RESULT

Description

Automatically declared variable representing result of a Function call (writable).

Inherit

BMM_WRITABLE_VARIABLE

Attributes

Signature

Meaning

1..1
(redefined)

name: String
{default = "Result"}

Name of this model element.

8.6.22. BMM_READONLY_VARIABLE Class

Class

BMM_READONLY_VARIABLE (abstract)

Description

Meta-type for writable variables, including routine parameters and the special variable Self.

Inherit

BMM_VARIABLE

Invariants

Inv_not_nullable: is_nullable = False

8.6.23. BMM_SELF Class

Class

BMM_SELF

Description

Meta-type for an automatically created variable referencing the current instance. Typically called 'self' or 'this' in programming languages. Read-only.

Inherit

BMM_READONLY_VARIABLE

Attributes

Signature

Meaning

1..1
(redefined)

name: String
{default = "Self"}

Name of this model element.

8.6.24. BMM_PARAMETER Class

Class

BMM_PARAMETER

Description

A routine parameter variable (read-only).

Inherit

BMM_READONLY_VARIABLE

Attributes

Signature

Meaning

0..1

direction: BMM_PARAMETER_DIRECTION

Optional read/write direction of the parameter. If none-supplied, the parameter is treated as in, i.e. readable.

8.6.25. BMM_PARAMETER_DIRECTION Enumeration

Enumeration

BMM_PARAMETER_DIRECTION

Description

Enumeration of parameter read/write direction values.

Attributes

Signature

Meaning

in

Parameter is an input parameter, and treated as readonly by the receiving routine.

out

Parameter is an output parameter, and treated as a reference to an entity writeable by the receiving routine.

in_out

Parameter is an input and output parameter, and treated as a reference to an entity readable and writeable by the receiving routine.

8.6.26. BMM_ROUTINE_DEFINITION Class

Class

BMM_ROUTINE_DEFINITION (abstract)

Description

Abstract ancestor of routine body meta-types.

8.6.27. BMM_LOCAL_ROUTINE Class

Class

BMM_LOCAL_ROUTINE

Description

Meta-type for locally declared routine body.

Inherit

BMM_ROUTINE_DEFINITION

Attributes

Signature

Meaning

0..1

locals: List<BMM_LOCAL>

Local variables of the routine, if there is a body defined.

1..1

body: BMM_STATEMENT_BLOCK

Body of routine declaration.

8.6.28. BMM_EXTERNAL_ROUTINE Class

Class

BMM_EXTERNAL_ROUTINE

Description

External routine meta-type, containing sufficient meta-data to enable a routine in an external library to be called.

Inherit

BMM_ROUTINE_DEFINITION

Attributes

Signature

Meaning

1..1

meta_data: Hash<String, String>

External call general meta-data, including target routine name, type mapping etc.

0..1

argument_mapping: Hash<String, String>

Optional argument-mapping meta-data.

9. Literal Values

9.1. Overview

With a typical formal model, there is a need for formal representation of literal values. This is needed to support constant declarations, 'default values' (a UML concept), enumeration literals and literal routine calls (see next section). In BMM, all such values have as their meta-type the type BMM_LITERAL_VALUE<T> or a descendant. The type hierarchy mostly mimicks parts of the BMM_TYPE meta-type hierarchy, allowing for literal values of any of the meta-types in that part of the model. The UML model is shown below.

LANG bmm.core.literal value
Figure 33. base.bmm.core.literal_value package - Literal Values

9.2. General Model

When a BMM model is instantiated in its in-memory form, e.g. in a BMM modelling tool, any literal values in the model such as constant values (e.g. Real Pi = 3.1415926), default values (e.g. Person.name: String = "(unknown)") etc are instances of 'two types':

  • their declared types withing the model, e.g. Real, String, Observation;

  • the meta-type BMM_LITERAL_VALUE<T> (or a matching descendant if there is one), which is instantiated to represent the value object within the model.

The value of any such instance is represented by the value_literal field within its BMM_LITERAL_VALUE object. This is assumed to carry a serialised form of the value expressed in a syntax known to the model processing environment within which the BMM model is being used. This may be a programming language syntax, JSON, or any other serialisable format, and is specified by BMM_LITERAL_VALUE.syntax.

9.3. Container Literals

Literals representing Lists or Sets of values of objects of other types have as their BMM meta-type BMM_CONTAINER_VALUE<T>. For example, if the serialised value ["Feyerabend", "Lakatos", "Popper"] (which happens to be a JSON Array of Strings) were parsed as a List<String> instance, its meta-type would be a BMM_CONTAINER_VALUE instance whose value_literal was the same string, assuming JSON were used as the syntax, and whose type will be BMM_CONTAINER_TYPE. Similarly a syntax that supported literal Sets using braces, e.g. {"Feyerabend", "Lakatos", "Popper"} may be parsed to a Set<String> instance, with the same meta-type as for the List.

In a similar way, a Hash table (aka 'map', 'dictionary' etc) with a formal type of Hash<K, V> has as its meta-type BMM_INDEXED_CONTAINER_VALUE.

9.4. Literal Tuples

Literal tuples may be expressed in BMM, but are not instances of BMM_LITERAL_VALUE; instead they are instances (at the meta level) of EL_TUPLE, an expression-related meta-type. This is a consequence of the fact that Tuple is considered a BMM built-in meta-type rather than a model-provided type, and also that a Tuple instance may contain items of any meta-type, not just literal values. Tuple instances are used in BMM expressions and described in Section 10.4.

9.5. Type Extensions

If it were desired to create a full set of 'native' types for BMM, in the way supplied for UML in the UML Standard Profile, specific descendants would be added to the meta-type classes BMM_SIMPLE_TYPE and BMM_GENERIC_TYPE, as well as BMM_LITERAL_VALUE, which would allow such instances to be directly representable in the internal BMM type system. This would still need to be ultimately mapped to the types actually available in any language in which BMM is implemented.

9.6. Class Definitions

9.6.1. BMM_LITERAL_VALUE Class

Class

BMM_LITERAL_VALUE<T> (abstract)

Description

Meta-type for literal instance values declared in a model. Instance values may be inline values of primitive types in the usual fashion or complex objects in syntax form, e.g. JSON.

Attributes

Signature

Meaning

1..1

value_literal: String

A serial representation of the value.

0..1

value: Any

A native representation of the value, possibly derived by deserialising value_literal.

0..1

syntax: String

Optional specification of formalism of the value_literal attribute for complex values. Value may be any of json | json5 | yawl | xml | odin | rdf or another value agreed by the user community. If not set, json is assumed.

1..1

type: T

Concrete type of this literal.

9.6.2. BMM_CONTAINER_VALUE Class

Class

BMM_CONTAINER_VALUE

Description

Meta-type for literals whose concrete type is a linear container type, i.e. array, list or set.

Inherit

BMM_LITERAL_VALUE

9.6.3. BMM_INDEXED_CONTAINER_VALUE Class

Class

BMM_INDEXED_CONTAINER_VALUE

Description

Meta-type for literals whose concrete type is an indexed container, i.e. Hash table, Map etc.

Inherit

BMM_LITERAL_VALUE

9.6.4. BMM_UNITARY_VALUE Class

Class

BMM_UNITARY_VALUE<T> (abstract)

Description

Meta-type for literals whose concrete type is a unitary type in the BMM sense.

Inherit

BMM_LITERAL_VALUE

9.6.5. BMM_PRIMITIVE_VALUE Class

Class

BMM_PRIMITIVE_VALUE<>

Description

Meta-type for literals whose concrete type is a primitive type.

Inherit

BMM_UNITARY_VALUE

Attributes

Signature

Meaning

1..1
(redefined)

type: BMM_SIMPLE_TYPE

Concrete type of this literal.

9.6.6. BMM_STRING_VALUE Class

Class

BMM_STRING_VALUE

Description

Meta-type for a literal String value, for which type is fixed to the BMM_TYPE representing String and value is of type String.

Inherit

BMM_PRIMITIVE_VALUE

Attributes

Signature

Meaning

1..1
(redefined)

value: String

Native String value.

9.6.7. BMM_INTEGER_VALUE Class

Class

BMM_INTEGER_VALUE

Description

Meta-type for a literal Integer value, for which type is fixed to the BMM_TYPE representing Integer and value is of type Integer.

Inherit

BMM_PRIMITIVE_VALUE

Attributes

Signature

Meaning

1..1
(redefined)

value: Integer

Native Integer value.

9.6.8. BMM_BOOLEAN_VALUE Class

Class

BMM_BOOLEAN_VALUE

Description

Meta-type for a literal Boolean value, for which type is fixed to the BMM_TYPE representing Boolean and value is of type Boolean.

Inherit

BMM_PRIMITIVE_VALUE

Attributes

Signature

Meaning

1..1
(redefined)

value: Boolean

Native Boolean value.

9.6.9. BMM_INTERVAL_VALUE Class

Class

BMM_INTERVAL_VALUE

Description

Meta-type for literal intervals of type Interval<Ordered>.

Inherit

BMM_LITERAL_VALUE

10. Expressions

10.1. Overview

Expressions in BMM are used to specify class invariants, routine pre- and post-conditions, and may be used more generally in other contexts requiring expressions. They are defined by a set of classes prefixed by 'EL', indicating 'expression language'. The BMM expression meta-model is based on the following taxonomy of expression entities:

LANG bmm.expression type hierarchy
Figure 34. Expression Taxonomy

The meta-types defined in this part of the BMM model may be understood as the types of entities in an abstract syntax tree (AST) generated from expression parsing. Conversely, one or more expression syntaxes may be parsed into a tree based on the model described here. Note however, that whatever the variation in surface syntax, all such syntaxes parsed this way ultimately have the semantics defined by the BMM EL meta-model. This is true even for expressions written in a syntax whose published semantics are in fact different, e.g. a well-known programming language.

The UML model of the BMM expression package, consisting of mostly direct equivalents of the taxonomy classes above, is shown below.

LANG bmm.expression
Figure 35. bmm.expression Package

EL classes are descendants of the class EL_EXPRESSION, which is characterised by the feature eval_type(). This is the BMM meta-type of the result type of the expression entity when used in an expression; for literals, this is the inferred type; for object references (including function calls), this is the same as the declared type, and for agents it is the meta-type BMM_SIGNATURE.

Most EL_EXPRESSIONs are either value generating constructs (EL_VALUE_GENERATOR) or operator expressions. The special sub-type E_TUPLE represents tuple objects which are created on the fly by inline expressions of the form [expr, expr, …​].

10.2. Terminal Entities

Terminal entities are atomic with respect to operator expressions, and are either simple entities of familiar kinds (function calls, variable references etc) or else complex logic structures that when evaluated generate a value.

10.2.1. Simple Terminal Entities

The simple terminal meta-types in EL are as follows:

  • literal values: inline-generated values created without reference to a model instance, but which must be instances of types defined by the model (EL_LITERAL);

  • value generators (EL_VALUE_GENERATOR) based on formal model elements that may be called to (potentially) obtain an instance at runtime;

  • predicates: Boolean-generating expression elements formed by predicates applied to any of the other value-generating expression elements.

10.2.1.1. Literals

A literal value may appear as a separate entity within an operator expression, as well as a functional call or agent parameter. The literal values that may be used are either instances of the openEHR Foundation Types or a complex object instance in a structured serial format (such as JSON, a JSON derivative, ODIN format etc), specified by BMM_LITERAL_VALUE.syntax.

10.2.1.2. Value Generators

Value generators are categorised as follows:

  • feature references: (EL_FEATURE_REF)

    • references to instantiable features: symbolic references to properties and constants (EL_PROPERTY_REF, EL_CONSTANT_REF);

    • calls to functions: appropriately constructed calls to functions of the types that define instances (EL_FUNCTION_CALL);

    • generation of agents: a special kind of reference to any routine of a model type that generates a delayed routine call object (EL_AGENT);

  • variable reference: references to variables within the scope of the current routine, including local variables, parameters, the current object (Self), or the current function result (Result) (EL_VARIABLE);

  • a type reference: (EL_TYPE_REF) a reference representing a type object assumed to be available at runtime, on which argumentless function calls and constants may be accessed.

The arguments of function calls and delayed routine calls may be complex expressions, but will eventually resolved to literal values and instance references. Consequently, the value generated by any expression is ultimately founded upon literal values and instance references.

To be valid, any model-based feature reference must have a scoping object (represented via the attribute scope in EL_SCOPED), which is one of:

  • the current object - implied;

  • another object, which may be designated via:

    • a specified scoping object, achieved through 'dot-notation' in most languages;

    • a type reference.

Feature References

In BMM, a feature reference is any symbolic reference to a class feature that resolves to an object at evaluation time. This includes all referenceable entities within classes except procedures, which have no return value. Concretely, a feature reference takes the form of one of:

  • a property name, e.g. name;

  • a constant name, e.g. pi;

  • a variable or parameter name, e.g. a_name, call_name;

  • a function call.

Function calls are described in detail in the following section.

Type Reference

A special meta-type, EL_TYPE_REF is provided to refer to a type as an object. This is exclusively used as a convenient way (common in many programming languages) of accessing class features that do not depend on instance properties (i.e. 'constant', 'enum', and 'static' members in C-based languages) without having to explicitly create an instance. As an expression, a type reference will normally only appear as a qualifier of a feature reference, using syntax such as {TypeName}.feature, or with arguments, {TypeName}.function (args…​).

A class feature is defined as one that is:

  • a constant;

  • an enumeration literal;

  • a function that does not reference any class property or make any call that does, in its body, pre_conditions or post_conditions.

The last category typically includes 'external' functions that are wrappers for calls to the operating system or other external resource that maintains its own state independently.

Since a type reference can be made without instantiation, it may be made to an abstract class as well as a concrete one. This facilitates the use of so-called 'utility' classes containing groups of useful functions e.g. for handling specific kinds of strings.

Examples of type references as qualifiers of class features include the following:

  • {Env}.current_time to access the class function current_time defined on the class (or interface) Env;

  • {Colours}.red, to access an enumeration literal;

  • {Version_utils}.version_higher ("1.5.40", "11.5.4").

A type reference may also be used on its own, such as in the following type test, which is the EL equivalent of programming language operators like type_of().

  • admission_dates.type = {Interval<Iso8601_date_time>}.

Agents

An agent is the BMM term for a delayed routine call, and has the meta-type EL_AGENT, which in turn has as its formal evaluation type (eval_type) is the meta-type BMM_SIGNATURE. It usually appears as a standalone expression, or else a parameter within another agent or function call. Agents are described in detail in the following section.

10.2.1.3. Variables

Symbolic variables (meta-type EL_VARIABLE) are one of the following:

  • variables declared locally in a routine (EL_VARIABLE.definition = BMM_LOCAL);

  • named arguments of a routine (EL_VARIABLE.definition = BMM_PARAMETER);

  • a special variable called 'Result' representing the result object of a function (EL_VARIABLE.definition = BMM_RESULT);

  • a special variable (often called 'this' or 'self' in object-oriented programming languages) to refer to the object acting as the context for enclosed statements (EL_VARIABLE.definition = BMM_SELF).

10.2.1.4. Predicates

Predicates in BMM are Boolean-returning terminal expressions taking one feature reference operand, and are represented by the meta-type EL_PREDICATE. Predicates conceptually apply to data instance structures and may be understood as queries on data. Any number of specific predicates might be added as extensions via inheritance. In particular, Xpath-style predicates could be supported by addition of meta-types descending from EL_PREDICATE. The following UML shows the predicate meta-types.

LANG bmm.expression predicate
Figure 36. Predicates

The following predicates are pre-defined.

Attached (x)

The attached predicate is used to test for an instance reference (including a function call result) being Void. It may be used in expressions such as the following class invariant.

class SmartRef

feature

    property url: Url;
    property value: Base64String;

    invariant
        Validity: attached(url) or attached(value)
Defined (x)

The defined predicate is used to test whether an instance that is mapped to an external data access method exists in the data context (regardless of its value there).

TBD: this might be replaced by another approach.

10.2.2. Decision Tables

The BMM expression package contains the meta-class EL_DECISION_TABLE that defines an abstract decision table construct, consisting of an ordered set of items, each of type EL_DECISION_BRANCH, and having a result of any expression type (including another decision table). Two concrete subtypes of each of these abstract meta-types are used to represent two common kinds of decision structure found in procedural and most object-oriented programming languages:

  • an if/then/elseif/else condition chain (meta-classes EL_CONDITION_CHAIN and EL_CONDITIONAL_EXPRESSION); and

  • a case statement style table (meta-classes EL_CASE_TABLE and EL_CASE), whose conditions are value intervals against which the table’s input value expression is evaluated to determine the result.

The else branch will be used to provide the result expression in the case that all other branches fail, guaranteeing a result.

EL_DECISION_TABLE and its descendants are also kind of expression, enabling them to be used as value-returning entities in certain other expression contexts, including inside other decision tables.

The following UML illustrates.

LANG bmm.expression decision table
Figure 37. Decision Tables

The logic of a EL_CONDITION_CHAIN is the same as an if/then/elseif/else chain in procedural programming, except that instead of assignment statements on each branch, pure result expressions are used. This enables a more sophisticated syntactic rendering, resembling a table, such as the following:

    molecular_subtype: Terminology_term
        Result := choice in
            =======================================================
            er_positive and
            her2_negative and
            not ki67.in_range (#high):    #luminal_A,
            -------------------------------------------------------
            er_positive and
            her2_negative and
            ki67.in_range (#high):        #luminal_B_HER2_negative,
            -------------------------------------------------------
            er_positive and
            her2_positive:                #luminal_B_HER2_positive,
            -------------------------------------------------------
            er_negative and
            pr_negative and
            her2_positive and
            ki67.in_range (#high):        #HER2,
            -------------------------------------------------------
            er_negative and
            pr_negative and
            her2_negative and
            ki67.in_range (#high):        #triple_negative,
            -------------------------------------------------------
            *:                            #none
            =======================================================
        ;

The above is a function that computes the molecular subtype of breast cancer using a decision table whose branches are based on a number of input variables that appear in expressions down the left-hand side and which returns a Terminology_code instance (the notation #identifier represents a literal Terminology_code instance).

An example of EL_CASE_TABLE is shown below. Here, two case tables are used, with each generating a numeric result based on the values of the platelets and gfr variables respectively.

    cyclophosphamide_dose: Quantity
        Result := cyclophosphamide_dose_per_m2 * BSA.bsa_m2
            * case platelets.range in
                ===================
                #normal:      1,
                #low:         0.75
                ===================
            * case gfr.range in
                ===================
                #normal:      1,
                #low:         0.75,
                #very_low:    0.5
                ===================
            ;

10.3. Operator Expressions

BMM contains meta-types representing operators, but assumes that all operators are surface aliases for functions defined on some class. For this reason, an occurrence of an operator within an expression, represented an instance of a descendant of EL_OPERATOR, contains the attribute definition to refer to the corresponding function definition. This has to be inferred from the types of its operands. Consequently, 'operator expressions' as commonly understood are simply function calls (often nested) in BMM. The following UML shows the relevant meta-types.

LANG bmm.expression operator
Figure 38. Operator meta-types

The following example illustrates the general meta-model of expressions, using a typical use of expression, the class invariant.

class Account

feature
    balance: Decimal
    overdraft_limit: Decimal

invariant
    balance + overdraft_limit > 0

The expression balance + overdraft_limit > 0 makes use of two operators + and >, which are really functions defined on the type Decimal, as follows.

class Decimal

feature
    greater_than (other: Decimal): Boolean
        alias '>'

    addition: (other: Decimal): Decimal
        alias '+'

A parser processing this expression would produce the result shown below, assuming that the BMM model containing these classes had already been instantiated.

bmm expression property ref
Figure 39. Instantiated Operator Expression

Below, we consider a number of examples illustrating expressions containing the various kinds of terminal reference, based on the following assumed declarations.

    feature -- Definitions

        Fast_resting_heart_rate: Real = 100;
        Atrial_fibrillation_heart_rate: Real = 120;
        Erratic: Terminology_code = {
            "terminology_id": "snomed_ct",
            "code_string": "286761003"
        }
        Blood_pressure_units: String = "mm[Hg]";

    feature -- Accessors

        heart_rate: Real;
        heart_rhythm: Terminology_code;
        bp_samples: List<Quantity>;
        patient: Patient;

The first example is a comparison of a property value to a value, where the >= operator maps to the function Real.greater_than_or_equal()

    heart_rate >= 80

The following shows the comparison of a property value with a constant, where the >= operator maps to the function Real.greater_than_or_equal()

    heart_rate >= Fast_resting_heart_rate

The following is a logical condition, where the = operator maps to a function such as Terminology_code.equal(); and maps to Boolean.and(); and >= maps to Real.greater_than_or_equal().

    heart_rhythm = Erratic and heart_rate >= Atrial_fibrillation_heart_rate

The following is the same logical condition, but with the use of object scope specified with 'dot notation', here 'patient.'.

    patient.heart_rhythm = Erratic and patient.heart_rate >= Atrial_fibrillation_heart_rate

The following shows a function call whose argument is an expression.

    date_of_birth.earlier ({Env}.current_date - P10Y)

The following shows the use of an inline agent as an argument to the function List.for_all().

    bp_samples.for_all (
        agent (a_quantity: Quantity) {
            a_quantity.units.is_equal (Blood_pressure_units);
        }
    );

10.4. Tuples

Although rarely useful in class definitions, a Tuple of any degree may be formed from any combination of other EL expressions and used on its own as an expression terminal element. The main use for this construct is to express a literal tuple, i.e. one whose constituents consist only of proper literal values.

For more general uses of BMM Expressions, tuple instances are the basis of representing ad hoc query results which have a formal type such as List<[Ta, Tb, Tc]>, where [Ta, Tb, Tc] represents a tuple of three types.

10.5. Usage in BMM Models

Expressions as used in BMM models to express class invariants and routine pre- and post-conditions are always in the form of an BMM_ASSERTION, i.e. a tagged Boolean-returning EL_EXPRESSION.

10.5.1. Simple Assertions

Simple assertions may be formed from common operators and operands, including the usual logical arithmetic and comparison operators, as well as any operators relating to specific data types. Normally the top-level operator in the Expression graph is a logical or relational operator. Since all operators are mapped to functions defined on types, there are no 'floating' or 'built-in' operators as such.

10.5.2. Existential and Universal Quantifier Invariants

A common kind of expression used in class invariants operates over collections and uses the existential and universal quantifier operators, i.e. ∃ and ∀, from predicate logic. A typical expression to use within a class invariant is shown below in an abstract syntax.

class PersonName
property items: String[1..*];

invariant
     nameItem: items | not nameItem.isEmpty()

A different syntax might express it as follows.

    invariant
        for nameItem in items all
            not nameItem.isEmpty()
        end

A similar invariant, this time using ∃, is shown below.

    invariant
        for nameItem in items
             not nameItem.isEmpty()

Regardless of the surface syntax, expressions such as the above map to functions such as for_all and there_exists defined on relevant linear container types. These functions have the following signatures in which the 'test' expression appears as a Function agent type.

class Container<T>

feature

    for_all (test: Function<[T], Boolean>): Boolean;
            -- True if for every v in container, test (v) is True

    there_exists (test: Function<[T], Boolean>): Boolean;
            -- True if there is any v in container for which test (v) is True

10.6. Class Definitions

10.6.1. EL_EXPRESSION Class

Class

EL_EXPRESSION (abstract)

Description

Abstract parent of all typed expression meta-types.

Functions

Signature

Meaning

1..1
(abstract)

eval_type (): BMM_TYPE

Meta-type of expression entity used in type-checking and evaluation.

Effected in descendants.

1..1

is_boolean (): Boolean

Post_result: Result = eval_type().equal( {BMM_MODEL}.boolean_type_definition())

True if eval_type is notionally Boolean (i.e. a BMM_SIMPLE_TYPE with type_name() = Boolean).

10.6.2. EL_TERMINAL Class

Class

EL_TERMINAL (abstract)

Description

Expression entities that are terminals (i.e. leaves) within operator expressions or tuples.

Inherit

EL_EXPRESSION

10.6.3. EL_SIMPLE Class

Class

EL_SIMPLE (abstract)

Description

Simple terminal i.e. logically atomic expression element.

Inherit

EL_TERMINAL

10.6.4. EL_VALUE_GENERATOR Class

Class

EL_VALUE_GENERATOR (abstract)

Description

Meta-type representing a value-generating simple expression.

Inherit

EL_SIMPLE

Attributes

Signature

Meaning

1..1

is_writable: Boolean

1..1

name: String

Name used to represent the reference or other entity.

Functions

Signature

Meaning

1..1

reference (): String

Generated full reference name, based on constituent parts of the entity. Default version outputs name field.

10.6.5. EL_TYPE_REF Class

Class

EL_TYPE_REF

Description

Meta-type for reference to a non-abstract type as an object. Assumed to be accessible at run-time. Typically represented syntactically as TypeName or {TypeName}.

May be used as a value, or as the qualifier for a function or constant access.

Inherit

EL_VALUE_GENERATOR

Attributes

Signature

Meaning

1..1

type: BMM_TYPE

Type, directly from the name of the reference, e.g. {SOME_TYPE}.

1..1

is_mutable: Boolean
{default = false}

Functions

Signature

Meaning

1..1
(effected)

eval_type (): BMM_TYPE

Return type.

10.6.6. EL_LITERAL Class

Class

EL_LITERAL

Description

Literal value of any type known in the model, including primitive types. Defined via a BMM_LITERAL_VALUE.

Inherit

EL_SIMPLE

Attributes

Signature

Meaning

1..1

value: BMM_LITERAL_VALUE<BMM_TYPE>

The reference item from which the value of this node can be computed.

Functions

Signature

Meaning

1..1
(effected)

eval_type (): BMM_TYPE

Return value.type.

10.6.7. EL_VARIABLE Class

Class

EL_VARIABLE (abstract)

Description

Abstract meta-type of any kind of symbolic variable.

Inherit

EL_VALUE_GENERATOR

10.6.8. EL_WRITABLE_VARIABLE Class

Class

EL_WRITABLE_VARIABLE

Description

Meta-type of writable variables, including routine locals and the special variable 'Result'.

Inherit

EL_VARIABLE

Attributes

Signature

Meaning

1..1

definition: BMM_WRITABLE_VARIABLE

Variable definition to which this reference refers.

1..1
(redefined)

is_writable: Boolean
{default = true}

Defined to return True in all cases.

10.6.9. EL_READONLY_VARIABLE Class

Class

EL_READONLY_VARIABLE

Description

Meta-type of read-only variables, including routine parameter and the special variable 'Self'.

Inherit

EL_VARIABLE

Attributes

Signature

Meaning

1..1

definition: BMM_READONLY_VARIABLE

Variable definition to which this reference refers.

1..1
(redefined)

is_writable: Boolean
{default = false}

Defined to return False in all cases.

10.6.10. EL_FEATURE_REF Class

Class

EL_FEATURE_REF (abstract)

Description

A reference that is scoped by a containing entity and requires a context qualifier if it is not the currently scoping entity.

Inherit

EL_VALUE_GENERATOR

Attributes

Signature

Meaning

0..1

scoper: EL_VALUE_GENERATOR

Scoping expression, which must be a EL_VALUE_GENERATOR.

Functions

Signature

Meaning

1..1
(redefined)

reference (): String

Generated full reference name, consisting of scoping elements and name concatenated using dot notation.

10.6.11. EL_PROPERTY_REF Class

Class

EL_PROPERTY_REF

Description

Reference to a writable property.

Inherit

EL_FEATURE_REF

Attributes

Signature

Meaning

1..1

definition: BMM_PROPERTY

Property definition (within class).

1..1
(redefined)

is_writable: Boolean
{default = true}

Defined to return True.

Functions

Signature

Meaning

1..1
(effected)

eval_type (): BMM_TYPE

Type definition (i.e. BMM meta-type definition object) of the constant, property or variable, inferred by inspection of the current scoping instance. Return definition.type.

10.6.12. EL_STATIC_REF Class

Class

EL_STATIC_REF

Description

Reference to a writable property, either a constant or computed.

Inherit

EL_FEATURE_REF

Attributes

Signature

Meaning

1..1

definition: BMM_STATIC

Constant definition (within class).

1..1
(redefined)

is_writable: Boolean
{default = false}

Defined to return False.

10.6.13. EL_AGENT_CALL Class

Class

EL_AGENT_CALL (abstract)

Description

A call made to a 'closed' agent, i.e. one with no remaining open arguments.

Attributes

Signature

Meaning

1..1

agent: EL_AGENT

The agent being called.

Invariants

Inv_valid_call: agent.is_callable()

10.6.14. EL_FUNCTION_CALL Class

Class

EL_FUNCTION_CALL

Description

A call made on a closed function agent, returning a result. Equivalent to an 'application' of a function in Lambda calculus.

Inherit

EL_FEATURE_REF, EL_AGENT_CALL

Attributes

Signature

Meaning

1..1
(redefined)

agent: EL_FUNCTION_AGENT

The function agent being called.

1..1
(redefined)

is_writable: Boolean
{default = false}

Defined to return False.

Functions

Signature

Meaning

1..1
(effected)

eval_type (): BMM_TYPE

Return agent.definition.type.

1..1
(redefined)

reference (): String

Generated full reference name, consisting of any scoping elements, function name and routine parameters enclosed in parentheses.

Invariants

Inv_valid_agent: agent.is_callable()

10.6.15. EL_AGENT Class

Class

EL_AGENT (abstract)

Description

A delayed routine call, whose arguments may be open, partially closed or closed. Generated by special reference to a routine, usually via a dedicated keyword, such as 'lambda' or 'agent', or other special syntax.

Instances may include closed delayed calls like calculate_age (dob="1987-09-13", today="2019-06-03") but also partially open calls such as format_structure (struct=?, style=3), where struct is an open argument.

Evaluation type (i.e. type of runtime evaluated form) is BMM_SIGNATURE.

Inherit

EL_FEATURE_REF

Attributes

Signature

Meaning

0..1

closed_args: EL_TUPLE

Closed arguments of a routine call as a tuple of objects.

0..1

open_args: List<String>

Optional list of names of open arguments of the call. If not provided, and the name refers to a routine with more arguments than supplied in closed_args, the missing arguments are inferred from the definition.

0..1

definition: BMM_ROUTINE

Reference to definition of a routine for which this is an agent, if one exists.

1..1
(redefined)

name: String

Name of the routine being called.

1..1
(redefined)

is_writable: Boolean
{default = false}

Functions

Signature

Meaning

1..1
(effected)

eval_type (): BMM_ROUTINE_TYPE

Post_result: Result = definition.signature

Eval type is the signature corresponding to the (remaining) open arguments and return type, if any.

1..1

is_callable (): Boolean

Post_result_validity: Result = open_arguments = Void

True if there are no open arguments.

1..1
(redefined)

reference (): String

Generated full reference name, including scoping elements.

10.6.16. EL_FUNCTION_AGENT Class

Class

EL_FUNCTION_AGENT

Description

An agent whose signature is of a function, i.e. has a result type.

Inherit

EL_AGENT

Attributes

Signature

Meaning

0..1
(redefined)

definition: BMM_FUNCTION

Reference to definition of a routine for which this is a direct call instance, if one exists.

Functions

Signature

Meaning

1..1
(effected)

eval_type (): BMM_FUNCTION_TYPE

Post_result: Result = definition.signature

Eval type is the signature corresponding to the (remaining) open arguments and return type, if any.

10.6.17. EL_PROCEDURE_AGENT Class

Class

EL_PROCEDURE_AGENT

Description

An agent whose signature is of a procedure, i.e. has no result type.

Inherit

EL_AGENT

Attributes

Signature

Meaning

0..1
(redefined)

definition: BMM_PROCEDURE

Reference to definition of routine for which this is a call instance.

Functions

Signature

Meaning

1..1
(effected)

eval_type (): BMM_PROCEDURE_TYPE

Post_result: Result = definition.signature

Eval type is the signature corresponding to the (remaining) open arguments and return type, if any.

10.6.18. EL_PREDICATE Class

Class

EL_PREDICATE (abstract)

Description

Parent type of predicate of any object reference.

Inherit

EL_SIMPLE

Attributes

Signature

Meaning

1..1

operand: EL_VALUE_GENERATOR

The target instance of this predicate.

Functions

Signature

Meaning

1..1
(effected)

eval_type (): BMM_SIMPLE_TYPE

Return {BMM_MODEL}.boolean_type_definition().

10.6.19. EL_DEFINED Class

Class

EL_DEFINED

Description

A predicate taking one external variable reference argument, that returns true if the reference is resolvable, i.e. the external value is obtainable.

Note
probably to be removed.

Inherit

EL_PREDICATE

10.6.20. EL_ATTACHED Class

Class

EL_ATTACHED

Description

A predicate on any object reference (including function call) that returns True if the reference is attached, i.e. non-Void.

Inherit

EL_PREDICATE

10.6.21. EL_DECISION_TABLE Class

Class

EL_DECISION_TABLE<T> (abstract)

Description

Meta-type for decision tables. Generic on the meta-type of the result attribute of the branches, to allow specialised forms of if/else and case structures to be created.

Inherit

EL_TERMINAL

Attributes

Signature

Meaning

1..1

items: List<EL_DECISION_BRANCH>

Members of the chain, equivalent to branches in an if/then/else chain and cases in a case statement.

1..1

else: T

Result expression of conditional, if its condition evaluates to True.

10.6.22. EL_DECISION_BRANCH Class

Class

EL_DECISION_BRANCH<T> (abstract)

Description

Abstract parent of meta-types representing a branch of some kind of decision structure. Defines result as being of the generic type T.

Attributes

Signature

Meaning

1..1

result: T

Result expression of conditional, if its condition evaluates to True.

10.6.23. EL_CONDITION_CHAIN Class

Class

EL_CONDITION_CHAIN<T>

Description

Compound expression consisting of a chain of condition-gated expressions, and an ungated else member that as a whole, represents an if/then/elseif/else chains.

Evaluated by iterating through items and for each one, evaluating its condition, which if True, causes the evaluation result of the chain to be that item’s result evaluation result.

If no member of items has a True-returning condition, the evaluation result is the result of evaluating the else expression.

Inherit

EL_DECISION_TABLE

Attributes

Signature

Meaning

1..1
(redefined)

items: List<EL_CONDITIONAL_EXPRESSION>

Members of the chain, equivalent to branches in an if/then/else chain and cases in a case statement.

10.6.24. EL_CONDITIONAL_EXPRESSION Class

Class

EL_CONDITIONAL_EXPRESSION<T>

Description

Conditional structure used in condition chain expressions. Evaluated by evaluating its condition, which is a Boolean-returning expression, and if this returns True, the result is the evaluation result of expression.

Inherit

EL_DECISION_BRANCH

Attributes

Signature

Meaning

1..1

condition: EL_EXPRESSION

Boolean expression defining the condition of this decision branch.

Invariants

Inv_condition_boolean: condition.is_boolean()

10.6.25. EL_CASE_TABLE Class

Class

EL_CASE_TABLE<T>

Description

Compound expression consisting of a list of value-range / expression pairs, and an else member that as a whole, represents a case statement flavour of decision table.

Evaluated by iterating through items and for each one, comparing input to the item value_range. If the input is in the range, the evaluation result of the table is that item’s result evaluation result.

If no member of items has a True-returning condition, the evaluation result is the result of evaluating the else expression.

Inherit

EL_DECISION_TABLE

Attributes

Signature

Meaning

1..1

test_value: EL_VALUE_GENERATOR

Expressing generating the input value for the case table.

1..1
(redefined)

items: List<EL_CASE>

Members of the chain, equivalent to branches in an if/then/else chain and cases in a case statement.

10.6.26. EL_CASE Class

Class

EL_CASE<T>

Description

One branch of a Case table, consisting of a value constraint (the match criterion) and a result, of the generic parameter type T.

Inherit

EL_DECISION_BRANCH

Attributes

Signature

Meaning

1..1

value_constraint: C_OBJECT

Constraint on

10.6.27. EL_OPERATOR Class

Class

EL_OPERATOR (abstract)

Description

Abstract parent of operator types.

Inherit

EL_EXPRESSION

Attributes

Signature

Meaning

0..1

precedence_overridden: Boolean

True if the natural precedence of operators is overridden in the expression represented by this node of the expression tree. If True, parentheses should be introduced around the totality of the syntax expression corresponding to this operator node and its operands.

0..1

symbol: String

The symbol actually used in the expression, or intended to be used for serialisation. Must be a member of OPERATOR_DEF.symbols.

1..1

call: EL_FUNCTION_CALL

Function call equivalent to this operator expression, inferred by matching operator against functions defined in interface of principal operand.

Functions

Signature

Meaning

1..1

operator_definition (): BMM_OPERATOR

Operator definition derived from definition.operator_definition().

1..1

equivalent_call (): EL_FUNCTION_CALL

Function call equivalent to this operator.

10.6.28. EL_UNARY_OPERATOR Class

Class

EL_UNARY_OPERATOR

Description

Unary operator expression node.

Inherit

EL_OPERATOR

Attributes

Signature

Meaning

1..1

operand: EL_EXPRESSION

Operand node.

10.6.29. EL_BINARY_OPERATOR Class

Class

EL_BINARY_OPERATOR

Description

Binary operator expression node.

Inherit

EL_OPERATOR

Attributes

Signature

Meaning

1..1

left_operand: EL_EXPRESSION

Left operand node.

1..1

right_operand: EL_EXPRESSION

Right operand node.

10.6.30. EL_TUPLE Class

Class

EL_TUPLE

Description

Defines an array of optionally named items each of any type.

Inherit

EL_EXPRESSION

Attributes

Signature

Meaning

0..1

items: List<EL_TUPLE_ITEM>

Items in the tuple, potentially with names. Typical use is to represent an argument list to routine call.

1..1

type: BMM_TUPLE_TYPE

Static type inferred from literal value.

Functions

Signature

Meaning

1..1
(effected)

eval_type (): BMM_TYPE

Return type.

10.6.31. EL_TUPLE_ITEM Class

Class

EL_TUPLE_ITEM

Description

A single tuple item, with an optional name.

Attributes

Signature

Meaning

0..1

item: EL_EXPRESSION

Reference to value entity. If Void, this indicates that the item in this position is Void, e.g. within a routine call parameter list.

0..1

name: String

Optional name of tuple item.

10.6.32. EL_CONSTRAINED Class

Class

EL_CONSTRAINED (abstract)

Description

Abstract parent for second-order constrained forms of first-order expression meta-types.

Inherit

EL_EXPRESSION

Attributes

Signature

Meaning

1..1

base_expression: EL_EXPRESSION

The base expression of this constrained form.

10.6.33. EL_BOOLEAN_EXPRESSION Class

Class

EL_BOOLEAN_EXPRESSION

Description

Boolean-returning expression.

Inherit

EL_CONSTRAINED

Invariants

Inv_boolean_expression: base_expression.is_boolean()

11. Functional Elements

11.1. Overview

BMM provides support for representing functional entities, often known as lambdas. The two key functional entities are known in the calculus as a lambda term and an application. The first is more commonly understood by programmers as a delayed routine call, here denoted by the term agent. The latter is what programmers understand as a 'call', i.e. an application of a lambda term.

An agent is formed by reference to a function or procedure in an expression context, potentially with provision of some or all arguments. This creates an entity whose type is an instance of the meta-type BMM_SIGNATURE. There are three variations as follows:

  • no arguments supplied: this is just a reference to a function or procedure by name, and is typically used to pass it as an argument to some other routine;

  • some arguments supplied: this generates a new delayed function or procedure call whose formal signature is the projection of the remaining open arguments with respect to the original signature;

  • all arguments supplied: this generates a new fully closed delayed call that may be invoked.

A call is thus an invocation of a closed agent. The evaluation type of a function call is the result type of the original function definition, thus its meta-type is just BMM_TYPE. A procedure call has no evaluation type.

Both calls and agents are special kinds of references to their original routines, and both can appear within an expression context, including as arguments passed to routine invocations. The following UML view of the bmm.expression package illustrates these details.

LANG bmm.expression functional
Figure 40. bmm.expression package - Functional Elements

11.2. Agents

In the model the three classes EL_AGENT, EL_FUNCTION_AGENT, and EL_PROCEDURE_AGENT (centre) define respectively, Agent and its Function and Procedure forms. An Agent is understood as one kind of terminal expression, since it is concretely a reference that generates a value, in this case, to a routine that generates a delayed call object. It potentially has closed_args, in the form of an EL_TUPLE which is a meta-type for tuple instances, which instantiate an instance BMM_TUPLE_TYPE (such as [String, Integer]). The items of the tuple are each in the form of an EL_TUPLE_ITEM consisting of the argument name (optional) and an item, which is an EL_EXPRESSION, having an eval_type of BMM_TYPE. By this means, the actual arguments to a routine call may be any expression, including operators, and (as shown), terminal expressions. This includes other agent expressions, and also function calls (but not procedure calls, since they are not value-generating entities).

An example of a delayed function call in syntax form is nodeCount (struct=?, depth=3) (the exact syntax will vary according to programming language). Here, the struct argument is left open, while the depth argument is closed with the supplied value 3. This expression generates an agent whose signature is [StructType]:Integer (assuming the concrete type of the struct argument is StructType). This capability is known as function currying and is the basis for enabling delayed routine calls to have their arguments progressively filled before final execution, each time generating a new agent with a reduced signature.

11.3. Calls

On the left of the UML diagram is the meta-class EL_FUNCTION_CALL, which represents a call to a function Agent, and which is also an EL_SIMPLE. For such a call to be possible, all arguments must be supplied (which may be none, in the case of a parameterless function).

An example of a Function Call is calculateAge ('1982-03-22', '2019-06-01'), which calculates a person’s age from his date of birth and a given date. In normal programming languages, any of the parameters may be any referenceable value-returning entity, i.e. any in-scope variable, other function call, or a valid operator expression, e.g. calculateAge ('1982-03-22', today()), where today() is a function returning the date of today.

Such calls are direct equivalents for expressions using basic mathematical operators and functions, on the usual basis that any operator (such as 'plus', i.e. +) is formally defined as a function such as add (arg1, arg2: Numeric): Numeric.

The instance structure for a typical expression such as the Body Mass Index (BMI), i.e. weight / height^2, is shown below.

LANG bmm nested call
Figure 41. Function call example - Body Mass index (BMI)

12. Statements

12.1. Overview

BMM provides meta-model elements for defining the body of a routine, consisting of statements. This facility is not needed for achieving the original purpose of BMM, i.e. a computable in-memory representation of a model at the interface level (classes, types and signatures), rather it provides a basis for representing program logic, such as function definitions.

BMM statements are formalised using the classes BMM_STATEMENT_ITEM, BMM_STATEMENT_BLOCK and BMM_STATEMENT and various descendant types, as shown in the UML view below.

LANG bmm.statement
Figure 42. Features for routine definition

The use of the three-class hierarchy pattern allows a Routine body to be a simple statement or a block, containing statements and/or more blocks. The class BMM_STATEMENT is abstract, allowing specific statement meta-models to be developed whose 'statement' meta-types inherit from this class. A number of common types are included by default, and are described below.

This facility is primarily provided to support the definition of higher-level languages by embedding them in the outer BMM meta-model.

12.2. Variable Declaration

Writable variables are declared using a variable declaration (BMM_DECLARATION). This may be understood as the creation of an instance of the relevant meta-type, i.e. of EL_WRITABLE_VARIABLE, that will represent the variable for all subsequent uses in the program text.

12.3. Assignment

A BMM assignment is the same concept as found in most frame-based programming languages, and provides a meta-model entity to represent a writable target (variable or property) being assigned to from a source, which is any expression of the same evaluation type. Type checking is thus based on a comparison of definition.type of the target and eval_type() of the source.

The following example shows a simple assignment in the definition of the function position.

class Simple_bank_account

feature -- Definitions

    overdraft_limit: Decimal = 250;

feature -- State

    balance: Decimal;

feature -- Interface

    position: Decimal {
        Result := balance + overdraft_limit
    }

invariant
    Solvent: position >= 0.0

The BMM meta-model for this statement is shown below.

bmm assignment
Figure 43. Assignment to function Result

12.4. Procedure Call

A procedure call is represented in BMM by the meta-type BMM_PROCEDURE_CALL, which refers to an instance of EL_PROCEDURE_AGENT, the same way that a function call is represented in terms of an EL_FUNCTION_AGENT. The effect of a procedure call is to cause an external action to be performed, such as display something on the screen, write to a database etc.

In the following example, the procedure put() is called from the deposit() and withdraw() functions in the class Account_access.

class Simple_bank_account

feature -- Modification

    put (val: Decimal)
        precondition
            valid_amount: val + overdraft_limit >= 0.0
    {
        balance := balance + val
    }

class Account_access

feature -- Command

    deposit (v: Decimal; ac: Simple_bank_account)
        pre_condition
            valid_amount: v > 0.0
    {
        ac.put (v);
    }

    withdraw (v: Decimal; ac: Simple_bank_account)
        pre_condition
            valid_amount: ac.overdraft_limit - v >= 0.0
    {
        ac.put (-v);
    }

The BMM meta-model instance structure for the call is shown below.

bmm procedure call
Figure 44. Procedure call

12.5. Action Tables

The BMM statement package includes the meta-classes BMM_ACTION_TABLE and BMM_CONDITIONAL_ACTION, which together provide a way of representing a decision table whose outputs are statements (rather than values, as in the case of the related Expression meta-classes EL_DECISION_TABLE and EL_CONDITIONAL_EXPRESSION). An action table corresponds closely to the standard constructs 'if/then/elseif' and the case statement.

The following example shows the logic of a BMM Action table meta-type, within a procedure that generates appropriate alerts or alarms based on patient vital signs, using the standard if/then/else constrol structure.

    check_vital_signs
        if systolic_pressure.in_range ([critical_high])
            raise_alarm ([emergency])

        elseif systolic_pressure.in_range ([high]) and oxygen_sat.in_range([low])
            call_staff
        end
    end

In a functional style syntax that directly mirrors the Action table meta-model, this may be written as:

    check_vital_signs
        ============================================================================
        systolic_pressure.in_range ([critical_high]):     raise_alarm ([emergency]),
        ----------------------------------------------------------------------------
        systolic_pressure.in_range ([high]) and
        oxygen_sat.in_range([low]):                       call_staff
        ============================================================================
    end

12.6. Assertions

The BMM statement model includes a statement meta-type to represent the notion of an assertion as a statement, typically expressed in syntax such as assert (<boolean expression>). This kind of statement is understood as an executable instruction to check that the condition is true, and if not, to generate an exception of the appropriate type, assuming exceptions are available.

12.7. Class Definitions

12.7.1. BMM_STATEMENT_ITEM Class

Class

BMM_STATEMENT_ITEM (abstract)

Description

Abstract parent of statement types representing a locally defined routine body.

12.7.2. BMM_STATEMENT_BLOCK Class

Class

BMM_STATEMENT_BLOCK

Description

A statement 'block' corresponding to the programming language concept of the same name. May be used to establish scope in specific languages.

Inherit

BMM_STATEMENT_ITEM

Attributes

Signature

Meaning

0..1

items: List<BMM_STATEMENT_ITEM>

Child blocks of the current block.

12.7.3. BMM_STATEMENT Class

Class

BMM_STATEMENT (abstract)

Description

Abstract parent of 'statement' types that may be defined to implement BMM Routines.

Inherit

BMM_STATEMENT_ITEM

12.7.4. BMM_SIMPLE_STATEMENT Class

Class

BMM_SIMPLE_STATEMENT (abstract)

Description

Simple statement, i.e. statement with one logical element - a single expression, procedure call etc.

Inherit

BMM_STATEMENT

12.7.5. BMM_DECLARATION Class

Class

BMM_DECLARATION

Description

Declaration of a writable variable, associating a name with a type.

Inherit

BMM_SIMPLE_STATEMENT

Attributes

Signature

Meaning

1..1

name: String

1..1

result: EL_WRITABLE_VARIABLE

1..1

type: BMM_TYPE

The declared type of the variable.

12.7.6. BMM_ASSIGNMENT Class

Class

BMM_ASSIGNMENT

Description

Statement type representing an assignment from a value-generating source to a writable entity, i.e. a variable reference or property.

At the meta-model level, may be understood as an initialisation of an existing meta-model instance.

Inherit

BMM_SIMPLE_STATEMENT

Attributes

Signature

Meaning

1..1

target: EL_VALUE_GENERATOR

The target variable on the notional left-hand side of this assignment.

1..1

source: EL_EXPRESSION

Source right hand side) of the assignment.

Invariants

Inv_target_writable: target.is_writable

12.7.7. BMM_PROCEDURE_CALL Class

Class

BMM_PROCEDURE_CALL

Description

A call made on a closed procedure agent. The method in BMM via which external actions are achieved from within a program.

Inherit

EL_AGENT_CALL, BMM_SIMPLE_STATEMENT

Attributes

Signature

Meaning

1..1
(redefined)

agent: EL_PROCEDURE_AGENT

The procedure agent being called.

Invariants

Inv_valid_agent: agent.is_callable()

12.7.8. BMM_ASSERTION Class

Class

BMM_ASSERTION

Description

A statement that asserts the truth of its expression. If the expression evaluates to False the execution generates an exception (depending on run-time settings).

May be rendered in syntax as assert condition or similar.

Inherit

BMM_SIMPLE_STATEMENT

Attributes

Signature

Meaning

1..1

expression: EL_BOOLEAN_EXPRESSION

Boolean-valued expression of the assertion.

0..1

tag: String

Optional tag, typically used to designate design intention of the assertion, e.g. "Inv_all_members_valid".

12.7.9. BMM_ACTION_TABLE Class

Class

BMM_ACTION_TABLE

Description

Multi-branch conditional statement structure

Inherit

BMM_STATEMENT

Attributes

Signature

Meaning

1..1

decision_table: BMM_ACTION_DECISION_TABLE

A specialised decision table whose outputs can only be procedure agents. In execution, the matched agent will be invoked.

12.7.10. BMM_ACTION_DECISION_TABLE Class

Class

BMM_ACTION_DECISION_TABLE

Description

Specialised form of Decision Table that allows only procedure call agents (lambdas) as the result of branches.

13. Model Semantics

This section describes various semantics that apply at a whole-of-model level rather than within single entities such as a class, type or property.

13.1. Inheritance

13.1.1. Simple Inheritance

The BMM supports single and multiple inheritance, although it does not distinguish between different types of inheritance relation as some programming languages do. Inheritance is formally defined to be between a class definition (an instance of BMM_CLASS) and a defined type, i.e. a BMM_SIMPLE_TYPE or BMM_GENERIC_TYPE. This is because the inheritance parents of a class may be any of:

  • a simple class;

  • a generic class;

  • a class type, i.e. the effective class definition corresponding to an effective generic type, which has one or more formal parameters substituted.

The general case for all three is represented by the corresponding type, i.e., a simple type or generic type.

The evaluation of inheritance relations defined in a BMM model results in an acyclic graph such that ancestors and descendants can be visualised for any class. The following screen shot shows the ancestors view of a class OBSERVATION.

awb class ancestors
Figure 45. BMM class - ancestors view

The next screenshot shows the descendants view of one of the ancestor classes of the same class.

awb class descendants
Figure 46. BMM class - descendants view

13.1.2. Generic Inheritance

Inheritance between generic classes works in the same way as for simple classes, with the additional semantics of formal parameter inheritance, which are as follows:

  • each unsubstituted formal parameter of the parent type must have a same-named counterpart in the formal parameters of the inheriting class;

  • the formal parameters of the inheriting class may further constrain any of the ancestor type’s formal parameters.

The following example shows the class DV_INTERVAL<T:DV_ORDERED> inheriting from Interval<T:Ordered>. Here the number of open generic parameters remains unchanged, while the type constraint Ordered is covariantly narrowed to DV_ORDERED, which inherits from the Ordered type.

awb generic class
Figure 47. Generic inheritance, constraint-narrowing

The resulting types of lower and upper are now T:DV_ORDERED rather than T:Ordered from the parent. In the fully computed model shown above, these two properties are synthesised within DV_INTERVAL<T> with their new concrete types. Their BMM meta-type objects (type BMM_UNITARY_PROPERTY) will both have the meta-attribute is_synthesised_generic set to True and are marked with an asterisk within the property view to indicate this.

A simple class may also inherit from a closed generic type, with the parameters of the latter fixed to specific type(s), as shown in the following example.

awb generic inheritance closed
Figure 48. Generic inheritance, closed

In this case, The resulting type of event is TIMER_EVENT rather than T:EVENT from the parent. As in the previous example, this property has been synthesised new within TIMER_WAIT, with the meta-attribute is_synthesised_generic set True and is marked accordingly within the tool.

The general case is that any number of formal generic parameters may be substituted or left open down the inheritance lineage, as shown by the variant descendants of the class GENERIC_PARENT<T:SUPPLIER, U:SUPPLIER> in the following example.

awb generic inheritance mixed
Figure 49. Generic inheritance, mixed open and closed

Generic substitution may be with other open, closed or partly-closed generic types. The following example illustrates the inheritance by X_VERSIONED_COMPOSITION of X_VERSIONED_COMPOSITION<ORIGINAL_VERSION<COMPOSITION>>.

awb generic inheritance
Figure 50. Generic inheritance, open parameter

13.1.3. Multiple Inheritance

Multiple inheritance is typically used in the definition of classes that have a Liskov substitution inheritance relation as well as a re-use inheritance relation. The following shows a class DV_INTERVAL<T> multiply inheriting from Interval<T> and DATA_VALUE, where the latter is considered the substitutable type, and the former an interface re-use.

awb multiple inheritance
Figure 51. Multiple inheritance

13.1.4. Inheritance and Invariants, Pre-conditions and Post-conditions

TBD

14. BMM Extensions

14.1. Overview

14.2. General Extensions

14.3. Feature Extensions

References

Dijkstra, E. W. (1976). A discipline of programming. Prentice-Hall Englewood Cliffs, N.J.

Meyer, B. (1997). Object-oriented Software Construction (Second.). Prentice Hall.

Smith, G. (2000). The Object Z Specification Language. Kluwer Academic Publishers. Retrieved from http://www.itee.uq.edu.au/ smith/objectz.html