openEHR logo

Basic Meta-Model (BMM)

Issuer: openEHR Specification Program

Release: BASE Release-1.0.4

Status: TRIAL

Revision: [latest_issue]

Date: [latest_issue_date]

Keywords: reflection, meta-model, UML

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

3.0.0

Separate P_BMM model and syntax to BMM Persistence specification;
refactor / tighten class model:
rename BMM_GENERIC_PARAMTER 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_CLASIFIER 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.

  • 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

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.

1.2. Status

This specification is in the TRIAL state. The development version of this document can be found at {openehr_base_bmm}[www.openehr.org/releases/BASE/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)

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 BASE 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. 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 have used the following terms:

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.

1.6. 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 very human-readable.

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.

2.2. Current State of the Art

2.2.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 {uml}[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 holes in the UML meta-model, including: the notion of 'type' is not formalised and 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 underlying semantic weaknesses as UML.

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 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 post-processed for purposes such as code generation.

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

2.2.2. XML Schema

For some, 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, no 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.3. Design Approach

The Basic Meta-Model supports the representation of object models in the ISO RM/ODP information point of view. It is designed to enable both human authoring and machine extraction (e.g. from a UML tool or programming language classes) of textual schemas. 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_OOSC2] and also the Eiffel language, which is significantly better match to object modelling than the UML 2.x meta-model.

Currently the BMM supports only the information point of view, i.e. no methods. It is oriented toward developing models of data. Tools that use the BMM can provide views of an object model expressed in BMM that are particularly useful to information modelling, such as '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

One of the main uses of the BMM in the 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

2.4. Specification Structure

This specification defines a BMM object model, i.e. the in-memory object structure of a BMM. The related {openehr_base_bmm_persistence}[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 ODIN, JSON or XML.

The BMM packages are as follows:

  • bmm: the BMM

    • rm_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;

These are illustrated below.

BASE bmm packages
Figure 3. Package Overview

3. Model Access Package

3.1. Overview

Note
This package is considered informative within this specification, not normative.

The 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 a concrete serial form of a model or part of a model. One or more schema files are parsed, validated and then converted to create a single BMM_MODEL instance.

BASE bmm.model access
Figure 4. base.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 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, SCHEMA_DESCRIPTOR.schema will be set to this instance. Subsequently, schema.merge() will be called repeatedly, which results in each 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 referenceable via BMM_MODEL_ACCESS.valid_models, which keys models by model identifiers (BMM_SCHEMA_CORE.identifier). The methods model_for_namespace() and model_for_namespace() are used to access a given model for a namespace to which the model applies.

The following screenshot shows the BMM schema configuration dialog in the AWB, 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

3.2. Class Definitions

3.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.

Inherit

BMM_DEFINITIONS

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) schemas in use. Table is keyed by model_id.

0..1

matching_bmm_models: Hash<String,BMM_MODEL>

BMM_MODELs keyed by model_id() and any shorter form used in calls to

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 ref 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 highest version will be selected.

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.

3.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.

Inherit

BMM_DEFINITIONS

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 from:

  • meta_data.item(Metadata_model_publisher) '-' meta_data.item(metadata_schema_name) '-' meta_data.item(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} pairs of schema meta-data, keys are string values corresponding to values in P_BMM_SCHEMA_METADATA_KEY.

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. not included by some other schema.

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.

3.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" .

3.2.4. BMM_SCHEMA Class

Class

BMM_SCHEMA (abstract)

Description

Parent of pesistable forms of BMM_MODEL. Defines the abstract interface and some common implementation elements for descendants, which provide concrete persistence formats.

Inherit

P_BMM_PACKAGE_CONTAINER, BMM_MODEL_METADATA

Attributes

Signature

Meaning

1..1

bmm_version: String

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

0..1

primitive_types: List<P_BMM_CLASS>

Primitive type definitions. Persisted attribute.

0..1

class_definitions: List<P_BMM_CLASS>

Class definitions. Persisted attribute.

0..1

includes: Hash<String,BMM_INCLUDE_SPEC>

Inclusion list, 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_schema: BMM_MODEL

Generated by create_bmm_schema 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

1..1

schema_id (): String

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

rm_publisher '' _schema_name '' _rm_release

E.g. 'openehr_rm_ehr_1.0.4'.

3.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.

3.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".

3.2.7. P_BMM_SCHEMA_DESCRIPTOR Class

Class

P_BMM_SCHEMA_DESCRIPTOR

Description

Concrete descendant of BMM_SCHEMA_DESCRIPTOR that provides a way to read an ODIN or other similarly encoded P_BMM schema file.

Inherit

BMM_SCHEMA_DESCRIPTOR

Attributes

Signature

Meaning

0..1
(redefined)

bmm_schema: P_BMM_SCHEMA

Persistent form of model.

3.2.8. P_BMM_SCHEMA Class

Class

P_BMM_SCHEMA

Description

Persisted form of BMM_SCHEMA.

Inherit

P_BMM_PACKAGE_CONTAINER, BMM_SCHEMA

Attributes

Signature

Meaning

0..1
(redefined)

primitive_types: List<P_BMM_CLASS>

Primitive type definitions. Persisted attribute.

0..1
(redefined)

class_definitions: List<P_BMM_CLASS>

Class definitions. Persisted attribute.

0..1
(redefined)

includes: Hash<String,BMM_INCLUDE_SPEC>

Inclusion list, 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.

Functions

Signature

Meaning

0..1
(effected)

validate_created

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

Implementation of validate_created()

0..1
(effected)

load_finalise

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

Implementation of load_finalise()

0..1
(effected)

merge (
other: P_BMM_SCHEMA[1]
)

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

Implementation of merge()

0..1
(effected)

validate

Implementation of validate()

0..1
(effected)

create_bmm_model

Pre_state: state = P_BMM_PACKAGE_STATE.State_includes_processed

Implementation of create_bmm_model()

1..1

canonical_packages (): P_BMM_PACKAGE

Package structure in which all top-level qualified package names like xx.yy.zz have been expanded out to a hierarchy of BMM_PACKAGE objects.

4. BMM Structure

4.1. Overview

The core package defines the main BMM model. The following figure shows it in overview.

BASE bmm.core overview
Figure 7. base.bmm.core Package - Overview

A BMM model is structured in the same basic way as a UML model, i.e. with a hierarchical package containment structure and a set of class definitions. Class definitions consist of property definitions, each of which refers to a type, which in turn refers to a 'base class'.

bmm structure
Figure 8. BMM model structure

4.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 provide an option to import schemas using differing naming styles, with transformation into a single style for the target model.

4.3. 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 serialsed 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.

4.4. Documentation

A documentation attribute is inherited from BMM_MODEL_ELEMENT into BMM_CLASS, BMM_PROPERTY, BMM_MODEL and BMM_PACKAGE (the latter two via BMM_PACKAGE_CONTAINER), enabling packages, classes and properties to be individually documented.

TBD: expand to be of type Hash<String,Any> or similar?

4.5. Model

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 (model_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.

4.6. Class Definitions

4.6.1. BMM_DEFINITIONS Class

Class

BMM_DEFINITIONS

Description

Definitions used by all BMM packages.

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.

4.6.2. BMM_MODEL_ELEMENT Class

Class

BMM_MODEL_ELEMENT (abstract)

Description

Ancestor class of most BMM model elements.

Inherit

BMM_DEFINITIONS

Attributes

Signature

Meaning

0..1

documentation: String

Optional documentation of this element.

4.6.3. BMM_PACKAGE_CONTAINER Class

Class

BMM_PACKAGE_CONTAINER

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.

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: PROCEDURE[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 Package_name_delimiter.

4.6.4. BMM_PACKAGE Class

Class

BMM_PACKAGE

Description

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

Inherit

BMM_PACKAGE_CONTAINER

Attributes

Signature

Meaning

1..1

name: String

Name of this package. This name may be qualified if it is a top-level package.

0..1

classes: List<BMM_CLASS>

Classes listed as being 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.

4.6.5. 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 schema, keyed by type name.

1..1

model_name: String

Name of this model.

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

any_class_definition (): BMM_SIMPLE_CLASS

BMM_CLASS instance for the Any class. This may be defined in the BMM schema, but if not, a default Any class will be generated.

1..1

any_type_definition (): BMM_SIMPLE_TYPE

5. BMM Entities

5.1. Overview

The following UML diagram shows the semantically important part of the BMM, defining classes and types, known collectively as entities.

BASE bmm.core main
Figure 9. base.bmm.core Package - Main

The general structure of a BMM consists of a set of classes, whose properties are each typed by an instance of BMM_TYPE, as shown below. Structures specific to generic and container types are shown in relevant sections below.

bmm entities
Figure 10. BMM entities

5.2. The Class / Type Division

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. Classes are definitional entities, while 'type' has two meanings:

  • as the static (design time) type of a class feature (property or function result), and

  • as the dynamic (run-time) type of the object referred to by or computed by that feature.

In a static model, types are references. For simple types, they refer to the corresponding simple class definition, but for generic types, they refer to a particular usage of a generic class definition. A generic class may generate numerous types.

This central division is reflected in the two classes BMM_CLASS and BMM_TYPE. The common parent class BMM_ENTITY defines a small number of properties that classify both classes and types in a model: entity_metatype, is_abstract and is_primitive. These are combined to produce a String classifier entity_category, which can be used to help visualise elements of a BMM model.

The Boolean attribute is_abstract on an entity indicates an abstract class in a BMM model, or a type based on an abstract class. The attribute is_primitive indicates that a class in a BMM model is considered to be part of a primitive type set (typically corresponding to primitive types in another type system); for types, it is derived from the setting of the base_class. Primitive status has no effect on BMM model semantics, and is provided as a convenience for visualisation and type-system mapping.

The taxonomy represented by BMM_ENTITY.entity_category is illustrated below.

bmm entity taxonomy
Figure 11. BMM entity taxonomy

5.3. Class Definitions

5.3.1. BMM_ENTITY Class

Class

BMM_ENTITY (abstract)

Description

Abstract parent of type and class meta-types.

Inherit

BMM_DEFINITIONS

Constants

Signature

Meaning

1..1

Entity_metatype_simple: String = "simple_entity"

Category of a simple entity, other than enumerated types.

1..1

Entity_metatype_enumeration: String = "enumeration_entity"

Category of any enumeration entity.

1..1

Entity_metatype_generic: String = "generic_entity"

Category of any generic entity that is not a container entity.

1..1

Entity_metatype_parameter: String = "generic_parameter_entity"

Category of a formal generic parameter entity.

1..1

Entity_metatype_container: String = "container_entity"

Category of any container entity.

1..1

Entity_category_modifier_abstract: String = "abstract"

Category modifier indicating an entity is formally defined as abstract, i.e. not-directly instantiable within a BMM model.

1..1

Entity_category_modifier_primitive: String = "primitive"

Category modifier indicating that an entity is considered to be primitive within the type system of a given BMM model. Has no semantic consequences within the BMM.

Functions

Signature

Meaning

1..1
(abstract)

entity_category (): String

Generate a category code-string to use in visualisation, that indicates:

  • entity meta-type: simple | enumerated | generic | generic_effective | parameter

  • abstract modifier - abstract status

  • primitive modifier primitive status

The code is structured as:

entity_metatype [ '-' abstract_modifier ] [ '-' primitive_modifier ]

1..1
(abstract)

entity_metatype (): String

Meta-type of entity, which classifies it according to the kind of formal entity it represents from the following:

  • simple (non-generic)

  • generic

  • enumeration

  • type parameter

  • container type

These meta-types don’t exactly match the BMM_* types defined in the model, but are useful for displaying models visually.

1..1
(abstract)

is_abstract (): Boolean

If true, indicates an abstract class in a BMM model, or 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 the entity in a BMM model is considered to relate to a primitive type set, i.e. be a primitive type, or be a definer of one.

6. Types

6.1. Overview

Types are used for three purposes in a BMM model:

  • to define the type of a property;

  • to define formal type parameters in a generic class;

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

Every type entity can be mapped back to its generating class(es), which provide the definitional basis for the type. The BMM class BMM_TYPE and its descendants define the kinds of types available in a BMM model. The BMM_TYPE class includes features common to all meta-types:

  • effective_base_class: a reference to the effective generating class;

  • 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 corresponds to meta-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 division is made to enable BMM to directly support collections in the type system.

Unitary meta-types are further distinguished as either formal generic parameters (BMM_PARAMETER TYPE) and defined types, i.e. types with class definitions, via the abstract meta-type BMM_DEFINED_TYPE. The subtypes of the BMM defined meta-type are BMM_SIMPLE_TYPE and BMM_GENERIC TYPE, corresponding to the standard notions of type familiar in modern programming languages. The class definitions of instances (i.e. BMM model class deifintions) 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.

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 ony 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 simle type. Thus, for example, a class Organisation may have a property managers of static type List<Person>. An instance of the simple type Organisation might have its managers property attached to an instance of List<Manager>, which is legal as long as Manager conforms to Person, which it will do it the same-named classes inherit in the usual sense.

6.3. Generic Type

A generic type is any type based on a generic class, which has one or more open type parameters that are substituted for 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. A typical programmatic usage of such a type, and its instantiated BMM model structure are shown below.

bmm structure generic 1
Figure 12. 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.

Consequently, a generic type may be:

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

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

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

The feature is_partially_closed () defined on BMM_GENERIC_TYPE can be used to distinguish the latter two cases.

The following diagram shows the BMM instance structure created for a generic type based on a generic class and another generic type.

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

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

bmm structure generic 3
Figure 14. Generic type - open

6.4. Container 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> and Set<T> are used ubiquitously in object models. In the BMM, containers and non-container generic types are distinguished via the meta-classes BMM_GENERIC_TYPE and BMM_CONTAINER_TYPE. 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 typically 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 Array<T>, 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. (This corrects one of the errors in UML, which does not represent containment via typing, but via cardinality, and uniqueness constraints.)

The following diagram shows how the container type List<Paragraph> is represented in a BMM model.

bmm structure container
Figure 15. Container Type

One other container type is also ubiquitous in object models and object-oriented programming: indexed containers, commonly known under the type name Hash<K,V>, HashMap<K,V>, HashTable<K,V>, Dictionary<K,V> and so on. This type always takes two parameters, a key type and a value type. The key type must be such that hash values can be generated, and may be any type, but practically speaking, is almost always a String or Integer, or a Date/Time type if such exists.

The indexed container is represented by the meta-type BMM_INDEXED_CONTAINER_TYPE, which inherits from BMM_CONTAINER_TYPE, and adds the property index_type. The following diagram shows how the container type Hash<String, Person> is represented in a BMM model.

bmm structure indexed container
Figure 16. Indexed Container Type

6.5. Type Conformance

In object-oriented theory, the important relationship between types is substitutability, which governs which instances may be dynamically attached to property references of particular declared static types. In the BMM, a type is conformant to another type if the base classes of its constituent elements are inheritance descendants of the corresponding elements of the other type. This is known in object-oriented type theory as covariant 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 this_type, other_type) {
    BMM_TYPE_NAME this_type_name, other_type_name;

    if attached create_type_name_from_string (a_this_type) as this_type_name and
        attached create_type_name_from_string (other_type) as other_type_name
    {
        this_base_class = this_type_name.name;
        other_base_class = other_type_name.name;

        if (this_base_class.is_case_insensitive_equal (other_base_class) or else
            class_definition (this_base_class).has_ancestor_class (other_base_class))
        {
            // handle case where formal generic names appear in type name
            BMM_DEFINED_CLASS this_bmm_def_class = class_definition (this_base_class);
            if (valid_generic_type_name (this_type) and this_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_DEFINED_CLASS other_bmm_def_class = class_definition (other_base_class);
                if (valid_generic_type_name (other_type) and other_bmm_def_class instanceOf BMM_GENERIC_CLASS) {
                    this_type_gen_params = this_type_name.generic_parameters_type_list;
                    other_type_gen_params = other_type_name.generic_parameters_type_list;

                    if (this_type_gen_params.count = other_type_gen_params.count) {

                        Iterator<String> this_gen_parms_it = this_type_gen_params.iterator();
                        Iterator<String> other_gen_parms_it = other_type_gen_params.iterator();

                        Boolean result = True;
                        String this_type_gen_type, other_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))
                                this_type_gen_type = this_bmm_gen_class.generic_parameter_conformance_type (this_gen_parm);
                            else
                                this_type_gen_type = this_gen_parm;

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

                            -- now do the test
                            result = type_conforms_to (this_type_gen_type, other_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 (other_type);
        }
    }
}

6.6. Class Definitions

6.6.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.

Inherit

BMM_ENTITY

Functions

Signature

Meaning

1..1
(abstract)

effective_base_class (): BMM_CLASS

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

1..1
(abstract)

type_name (): String

Formal string form of the type as per UML.

1..1
(abstract)

has_subtypes (): Boolean

Determine if there are any type substitutions.

1..1
(abstract)

subtypes (): List<String>

List of type substitutions if any available for this type within the current BMM model.

1..1
(abstract)

flattened_type_list (): List<String>

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

1..1

type_signature (): String

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

Generally useful for display purposes.

1..1
(effected)

is_primitive (): Boolean

True if base_class.is_primitive.

1..1
(effected)

entity_metatype (): String

Meta-type of type is by default assumed to be the meta-type of its base_class.

6.6.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

6.6.3. BMM_SIMPLE_TYPE Class

Class

BMM_SIMPLE_TYPE

Description

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

Inherit

BMM_DEFINED_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
(effected)

subtypes (): List<String>

Result is base_class.all_descendants .

1..1
(effected)

has_subtypes (): Boolean

True if base_class.has_descendants .

1..1
(effected)

effective_base_class (): BMM_SIMPLE_CLASS

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

6.6.4. BMM_CONTAINER_TYPE Class

Class

BMM_CONTAINER_TYPE

Description

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

base_type: BMM_UNITARY_TYPE

The target type; this converts to the first parameter in generic_parameters in BMM_GENERIC_TYPE.

Functions

Signature

Meaning

1..1
(effected)

type_name (): String

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

1..1
(effected)

effective_base_class (): BMM_CLASS

Post_validity: Result = base_type.base_class

Result is base_class of base_type.

1..1
(effected)

is_abstract (): Boolean

True if base_type.is_abstract or container_type.is_abstract.

1..1
(effected)

entity_metatype (): String

Meta-type of container type is Classifier_metatype_container.

1..1
(effected)

flattened_type_list (): List<String>

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

1..1
(effected)

subtypes (): List<String>

Result is all permutations of current container type and its descendants with the current base_type and its descendants.

1..1
(effected)

has_subtypes (): Boolean

Determine if there are any type substitutions.

6.6.5. BMM_INDEXED_CONTAINER_TYPE Class

Class

BMM_INDEXED_CONTAINER_TYPE

Description

Type of linear container 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.

6.6.6. BMM_GENERIC_TYPE Class

Class

BMM_GENERIC_TYPE

Description

Type reference based on a generic class, e.g. HashTable <List <Packet>, String>.

Inherit

BMM_DEFINED_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.

1..1
(redefined)

base_class: BMM_GENERIC_CLASS

The target type; this converts to the first parameter in generic_parameters in BMM_GENERIC_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
(effected)

subtypes (): List<String>

Result is the permutation of the base class type and type substitutions of all generic parameters.

1..1
(effected)

has_subtypes (): Boolean

True if base_class.has_descendants or any generic parameter type type_substitutions is True.

1..1

is_partially_closed (): Boolean

Returns True if there is any substituted generic parameter.

1..1
(effected)

effective_base_class (): BMM_GENERIC_CLASS

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

6.6.7. 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_DEFINED_TYPE

Optional conformance constraint that must be another valid class name.

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 (): String

Result is either conforms_to_type or inheritance_precursor.flattened_conforms_to_type.

1..1

effective_conforms_to_type (): BMM_CLASS

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

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)

entity_metatype (): String

Meta-type of a container type is Entity_metatype_generic_parameter.

1..1
(effected)

effective_base_class (): BMM_CLASS

The effective conformance type of this parameter, or the 'Any' class if none.

1..1
(effected)

has_subtypes (): Boolean

True if effective_conforms_to_type.base_class.has_descendants.

1..1
(effected)

subtypes (): List<String>

Result is effective_conforms_to_type.base_class.all_descendants .

1..1
(effected)

type_name (): String

Result is name.

1..1
(effected)

flattened_type_list (): List<String>

Result is either flattened_conforms_to_type.flattened_type_list or the Any type.

Invariants

Inv_generic_name: name.count = 1 and name.is_upper

7. Classes

7.1. Overview

Class definitions are the core of any BMM model. 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.

Class properties are defined using the generic class BMM_PROPERTY <T: BMM_TYPE>. The use of a generic meta-type provides a formal way of expressing the semantics of meta-types described in the section on types. The generic parameter is one of the following BMM_TYPE descendants:

  • a BMM_SIMPLE_TYPE - corresponds to a simple type such as Document;

  • a BMM_GENERIC_TYPE - a type generated by the use of a generic class with one or more filled type parameters, e.g. Interval<Time>, Packet<T,Payload>;

  • a BMM_CONTAINER_TYPE - a type generated by the use of a linear container type such as List<T>, Hash<T,U> with actual generic parameters;

  • a BMM_PARAMETER_TYPE - corresponds to a generic parameter type from the class type definition, e.g. T, U etc.

In modelling or programming terms, the properties of a class constitute the features it introduces with respect to its inheritance parent(s). We can think of this list of properties 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 property set is relationally differential to the top class.

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

7.2. Primitive Classes

As noted above, class definitions can be marked as being 'primitive' within a BMM model, enabling them to be visualised and queried as a separate group without otherwise impacting on the semantics of the entity in BMM meta-type system. 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 17. Primitive classes

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

7.3. Enumeration Classes

The enumeration meta-type adds a set of enumeration labels and optional String or Integer values, in the manner of contemporary languages such as Java and C#. This meta-type allows classes to be declared in a BMM to be enumerations without either having to manufacture a representation from simple class definitions, or having to replicate the representation of enumerations in some target language. The following screenshot shows how a BMM integer enumeration class appears within a BMM model.

awb enumeration
Figure 18. Enumeration Example

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

7.4. 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. 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 19. BMM class - generic class

7.5. Properties

Properties in BMM class definitions occur in two flavours, corresponding to the unitary and container type meta-types. The BMM_PROPERTY<T:BMM_TYPE> meta-type defines semantics common all properties, including name and is_mandatory, and type, a generically typed reference to the property type in a BMM model. 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 use in runtime systems. 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.

Unitary properties in a BMM model are instances of the types BMM_PROPERTY<BMM_SIMPLE_TYPE> and so on. Container properties are instances of the type BMM_CONTAINER_PROPERTY, which inherits from BMM_PROPERTY<BMM_CONTAINER_TYPE>, in order to add the meta-data item cardinality, which enables the possible number of container elements to be constrained, corresponding to the multiplicities used at the end of UML associations.

The following example shows a BMM class in a model whose flat 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, and those in light grey are infrastructure properties.

awb class properties
Figure 20. BMM class - properties view

7.6. Class Definitions

7.6.1. BMM_CLASS Class

Class

BMM_CLASS (abstract)

Description

Meta-type defining a class definition in an object model.

Inherit

BMM_ENTITY, BMM_MODEL_ELEMENT

Attributes

Signature

Meaning

1..1

name: String

Name of this class. Note that unlike UML, names of classes are just the root name, even if the class is generic. Use type_name() to obtain the full type name.

0..1

ancestors: Hash<String,BMM_DEFINED_TYPE>

List of immediate inheritance parents.

1..1

package: BMM_PACKAGE

Package this class belongs to.

0..1

properties: Hash<String,BMM_PROPERTY>

List of attributes defined in this class.

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 references to base classes of immediate inheritance descendants.

1..1

is_override: Boolean

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

Functions

Signature

Meaning

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.

0..1

flat_properties (): List<Hash<String, BMM_PROPERTY<BMM_TYPE>>>

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

1..1
(effected)

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
(effected)

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.

1..1
(abstract)

type (): BMM_DEFINED_TYPE

Generate a type object that represents the type of this class.

7.6.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.

1..1
(effected)

entity_metatype (): String

Meta-type of BMM_SIMPLE_CLASS, which is Entity_metatype_simple.

7.6.3. BMM_ENUMERATION Class

Class

BMM_ENUMERATION<T>

Description

Definition of an enumeration type. In the BMM system, an 'enumeration' type is understood as an underlying basic type and a set of named constants of that type. It is designed so that the default type is Integer, and the default constants are numbered 0, 1, …​ Optional model elements can be specified to override the values and / or the type.

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<T>

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

1..1

underlying_type_name: String

Name of type any concrete BMM_ENUMERATION_* sub-type is based on, i.e. the name of type bound to 'T' in a declared use of this type.

Functions

Signature

Meaning

1..1
(effected)

entity_metatype (): String

Meta-type of BMM_ENUMERATION, which is Entity_metatype_enumeration.

1..1

name_map (): Hash<String,String>

Map of item_values (stringified) to item_names.

7.6.4. BMM_ENUMERATION_STRING Class

Class

BMM_ENUMERATION_STRING

Description

String-based enumeration type.

Inherit

BMM_ENUMERATION

Attributes

Signature

Meaning

1..1
(redefined)

underlying_type_name: String
{default = "STRING"}

Name of type any concrete BMM_ENUMERATION_* sub-type is based on.

7.6.5. BMM_ENUMERATION_INTEGER Class

Class

BMM_ENUMERATION_INTEGER

Description

Integer-based enumeration type.

Inherit

BMM_ENUMERATION

Attributes

Signature

Meaning

1..1
(redefined)

underlying_type_name: String
{default = "INTEGER"}

Name of type any concrete BMM_ENUMERATION_* sub-type is based on.

7.6.6. 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 generic parameter definitions, keyed by name of generic parameter; these are defined either directly on this class or by the addition of an ancestor class which is generic.

Functions

Signature

Meaning

0..1
(redefined)

suppliers (): List<String>

Add suppliers from generic parameters.

1..1
(effected)

entity_metatype (): String

Meta-type of BMM_GENERIC_CLASS, which is Entity_metatype_generic.

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.6.7. BMM_PROPERTY Class

Class

BMM_PROPERTY<T>

Description

Model of a property definition within a class definition of an object model. The generic parameter accommodates the possible meta-type variant descendants of BMM_TYPE.

Inherit

BMM_MODEL_ELEMENT

Attributes

Signature

Meaning

1..1

name: String

Name of this property in the model.

0..1

is_mandatory: Boolean

True if this property is mandatory in its class.

0..1

is_computed: Boolean

True if this property is computed rather than stored in objects of this class.

1..1

type: T

Formal type of this property.

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_synthesised_generic: Boolean
{default = false}

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

Functions

Signature

Meaning

1..1

existence (): Multiplicity_interval

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

1..1

display_name (): String

Name of this property to display in UI.

7.6.8. BMM_CONTAINER_PROPERTY Class

Class

BMM_CONTAINER_PROPERTY

Description

Subtype of BMM_PROPERTY that represents a container type based on one of the inbuilt types List<T>, Set<T>, Array<T>.

Inherit

BMM_PROPERTY

Attributes

Signature

Meaning

0..1

cardinality: Multiplicity_interval

Cardinality of this container.

1..1
(redefined)

type: BMM_CONTAINER_TYPE

Functions

Signature

Meaning

1..1
(redefined)

display_name (): String

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

8. Model Semantics

8.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 21. 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 22. BMM class - descendants view

8.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 being covariantly narrowed to DV_ORDERED, which inherits from the Ordered type.

awb generic inheritance
Figure 23. Generic inheritance, open parameter

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 24. Generic inheritance, closed

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 variants in the following example.

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

8.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 26. Multiple inheritance

References