Chapter 8. Modeling the State Structure of a System
KerML's Kernel layer essentially consists of the modeling concepts DataTypes, Classes, Associations, Structures, Behaviors, Connectors, and Steps, as shown in the following diagram.
In KerML, "Classes" are occurrence types subsuming both "Structures" (or object types) and "Behaviors" (or action types). The instances of Classes are not objects, but occurrences (things that happen over time). Objects are instances of Structures.
The state structure of a system is captured by modeling all types of objects the system consists of. This also includes modeling the features (mainly attributes, component properties and connectors) of object types and the associations between them.
8.1. Data Types
Data types are classifiers that classify data values, which are abstract things that do not exist in time or space.
datatype IdNumber specializes ScalarValues::Integer;
If a data type has features, their values cannot change over time, because different feature values would inherently identify a different data value.
datatype SensorReading { feature sensorId : IdNumber; feature value : ScalarValues::Real; }
The KerML library Base includes the predefined data type DataValue, which is the most general data type in the sense that every other data type is a subtype of it. A Kernel-layer data type declaration made with the keyword "datatype" like the following one:
datatype URL;
is equivalent to the following Core-layer classifier declaration made with the help of the predefined data type DataValue:
classifier URL specializes DataValue;
8.2. Occurrence Types ("Classes")
In KerML, Classes are occurrence types:
Classes are classifiers that classify occurrences, which happen in time (and space). Relations between an occurrence and other things can change over time and space, while the occurrence still maintains its identity.
KerML defines two kinds of occurrence types: "Structures" (better called object types) and Behaviors (better called action types). However, the specification does not explain if these occurrence types classify only completed occurrences or both completed and ongoing occurrences.
The KerML library Occurrences includes the predefined Class Occurrence, which is the most general Class in the sense that every other Class is a subtype of it. A Kernel-layer Class declaration made with the keyword "class" like the following one:
class ArrivalEvent;
is equivalent to the following Core-layer classifier declaration made with the help of the predefined Class Occurrence:
classifier ArrivalEvent specializes Occurrence;
8.3. Object Types ("Structures")
In KerML, objects are considered as occurrences (happening over time like processes) and object types are called "Structures", while action types are called "Behaviors":
Structures are Classes that classify objects, which are kinds of occurrences. Structures and Behaviors do not overlap, but Structures can own Behaviors, and the objects they classify can be involved in Behaviors (e.g., they can perform Behaviors).
An example of an object type declaration:
struct Sensor { feature id : IdNumber; feature currentReading : Real; step updateReading { ... } // a behavioral feature }
The KerML library Objects includes the predefined classifier Object, which is the most general object type in the sense that every other object type is a subtype of it. A KerML Structure declaration like the following one:
struct Car;
is equivalent to the following Core-layer classifier declaration made with the help of the predefined object type Object:
classifier Car specializes Object;
8.4. Associations
What is called an association between two (or more) related types in UML and SysML, corresponds to the mathematical concept of a relation as a subset of the Cartesian product of the related types. The instances of an association, called links, represent relationships between individuals and correspond to the tuples of a relation.
The following UML class diagram shows an example of an explicit many-to-many association Ownership that is specialized by a one-to-many association SoleOwnership:
Notice how the Ownership association end owners with multiplicity * ("many") is redefined by the SoleOwnership association end owner with multiplicity 0..1 ("at most one"), expressing the fact that any asset is linked to zero or many legal entities as its owners while it is linked to at most one legal entity as its sole owner.
An association between two types represents a function (in the sense of mathematics) if it has a functional (single-valued) association end. An overview about the different cases of functionality of an association is provided in the following table:
Functionality type | Meaning |
---|---|
one-to-one | both functional and inverse functional |
many-to-one | functional |
one-to-many | inverse functional |
many-to-many | neither functional nor inverse functional |
The following tables show an example snapshot population of the classifiers involved in the model shown in the diagram above:
LegalEntity | |
---|---|
id | name |
le1 | Trump |
le2 | Acme Corp |
le3 | Oscorp |
Asset | |
---|---|
id | name |
a1 | Mar-a-Lago |
a2 | Oscorp Tower |
a3 | Rolls-Royce Phantom |
Ownership | |
---|---|
owner | ownedAsset |
le1 | a1 |
le2 | a2 |
le1 | a3 |
le3 | a2 |
SoleOwnership | |
---|---|
owner | ownedAsset |
le1 | a1 |
le1 | a3 |
In the KerML spec, associations are characterized as follows:
Associations are classifiers that classify links between things. At least two owned features of an association must be end features representing its association ends, which identify the things being linked by (at the "ends" of) each link (exactly one thing per end, which might be the same thing). Associations with exactly two association ends are called binary associations. The end features of an association identify the participants in the links that are instances of the association and must have multiplicity 1. Associations can also have features that are not end features, which characterize each instance of the association separately from the things it links.
An association is also a relationship between the types of its association ends, called its related types, which might be the same. Links are between instances of an association's related types. For binary associations, the two related types are identified as the source type and the target type. For associations with more than two association ends (called "n-ary" associations), the first related type is the source type and all the remaining related types are target types.
In the following class diagram, the two UML associations Ownership and SoleOwnership from the class diagram above have been turned into KerML associations as link classifiers with the two ends owner and ownedAsset as their properties (or end features), such that their instances are (owner, ownedAsset) value pairs corresponding to binary links.
Notice that the end properties of KerML associations, here: owner and ownedAsset, since they are always single-valued, have the multiplicity 1. Notice also how the corresponding multiplicities of the original class diagram above, which are now marked in yellow, have moved to the UML association ends at the new KerML association classes. These association ends are called cross features in KerML. For instance, * is the cross multiplicity of Ownership::owner, while 0..1 is the cross multiplicity of SoleOwnership::owner.
Consider a binary association A with end properties e1 typed by E1 and e2 typed by E2. The cross multiplicity of e1 allows expressing how many A links may, or have to, exist for any instance of E2.
The model shown in the class diagram above can be expressed in KerML in the following way:
classifier LegalEntity {...} classifier Asset {...} assoc Ownership { end [*] feature owner : LegalEntity; end [*] feature ownedAsset : Asset; } assoc SoleOwnership specializes Ownership { end [0..1] feature redefines owner; }
The multiplicities specified between the keywords "end" and "feature", like [*] and [0..1] in the example above, represent the cross multiplicities of the KerML association's end properties. The cross multiplicity [*] of Ownership::owner (and Ownership::ownedAsset) expresses the fact that for any instance of LegalEntity (and Asset), there are zero or more Ownership links. The cross multiplicity [0..1] of SoleOwnership::owner expresses the fact that for any instance of Asset, there is at most one SoleOwnership link. The default cross multiplicity is [*], which means that, by default, there are no cardinality constraints.
Notice that the names of the end features of a KerML association declaration should be singular noun phrases since they are always single-valued, that is, they reference exactly one individual.
The keyword feature
, as well as the default cross multiplicity [*], may be omitted from an association end declaration:
assoc Ownership { end owner : LegalEntity; end ownedAsset : Asset; }
The KerML library Links includes the predefined association Link, which is the most general association in the sense that every other association is a subtype of it. A Kernel-layer association declaration made with the keyword "assoc" like the following one:
assoc Employment;
is equivalent to the following Core-layer classifier declaration made with the help of the predefined association Link:
classifier Employment specializes Link;
Implicit Associations Expressed by Reference Properties
A referential feature that has classes (representing occurrence types) as its domain and range establishes an implicit binary association between its domain and range. Such a feature may also be called a reference property. In the following example, the reference property ownedAssets establishes an implicit binary association between LegalEntity and Asset.
class LegalEntity { feature id : String; feature name : String; feature ownedAssets[*] : Asset; } class Asset feature id : String; feature name : String; }
In this example, the implicit association is represented in a unidirectional way with references from LegalEntity to Asset but not vice versa. However, an implicit association can also be represented in a bidirectional way by declaring a pair of mutually inverse reference properties like so:
class LegalEntity { feature id : String; feature name : String; feature ownedAssets[*] : Asset; } class Asset feature id : String; feature name : String; feature owners[*] : LegalEntity inverse of LegalEntity::ownedAssets; }
Notice that without declaring one of the two features ownedAssets and owners to be the inverse of the other, they would formally not represent the same association in a bidirectional way, but rather two different unidirectional associations.
Association Structures
Association Structures are both Associations and Structures, classifying link objects, which are both links and objects. As objects, link objects can be created and destroyed, and their non-end features can change over time. However, the values of the end features of a link object are fixed and cannot change over its lifetime (that is, they are effectively read only).
Example:
assoc struct ExtendedOwnership specializes Ownership { feature revaluations[*] ordered : MonetaryValue; }
The KerML library Objects includes the predefined Association Structure LinkObject, which is the most general Association Structure in the sense that every other Association Structure is a subtype of it. A Kernel-layer Association Structure declaration made with the keyword "assoc struct" like the following one:
assoc struct Employment;
is equivalent to the following Core-layer classifier declaration made with the help of the predefined Association Structure LinkObject:
classifier Employment specializes LinkObject;
8.5. Connectors and Bindings
Connectors are features that are typed by associations, having values that are links. Like an association, a connector has end features, known as its connector ends. Each connector end redefines an association end from each of the associations that type the connector and subsets a feature that becomes a related feature of the connector. Connectors typed by binary associations are called binary connectors.
A connector is also a relationship between its related features. For binary connectors, the two related features are identified as the source feature and the target feature, which might be the same.
These principles are described by the following meta-model, which redefines the range of a Connector feature to be an association:
Notice that, in addition to regular connectors, there are also two special kinds of connectors:
- binding connectors for binding the value of one feature to the value of another feature;
- successions for temporally sequencing behavior steps.
In the following example, a Mounting association between the object types Axle and Wheel classifies links between an axle and a wheel, such that an axle is linked to two wheels, as shown in the following class diagram and the corresponding KerML code below.
While all end properties of an association, here mountingAxle and mountedWheel, have the multiplicity 1, the multiplicities across their respective association lines, marked in yellow, are called their cross multiplicities and are expressed in-between the keyword end and the end property name in the textual notation:
struct Axle {...} struct Wheel {...} assoc Mounting { end [1] mountingAxle : Axle; end [2] mountedWheel : Wheel; }
Notice that the cross multiplicity [2] of the end property Mounting::mountedWheel expresses the constraint that for any instance of Axle, there are exactly two Mounting links connecting the axle to two different wheels. Likewise, the cross multiplicity [1] of the end property Mounting::mountingAxle expresses the constraint that for any instance of Wheel, there is exactly one Mounting link connecting the wheel to an axle. Thus, the two cross multiplicities can be verbalized like so:
- Each Axle is connected to exactly two Wheels.
- Each Wheel is connected to exactly one Axle.
The corresponding connector property mount of the object type WheelAssembly has exactly two values, namely one mountingAxle-mountedWheel link for each of the two wheels of a wheel assembly mounted to the same axle:
struct WheelAssembly { composite feature axle[1] : Axle; composite feature wheels[2] : Wheel; connector mount[2] : Mounting { end mountingAxle references axle; end mountedWheel references wheels; } }
Notice that the related features referenced by connector ends are specified using the keyword references
, denoting a special form of subsetting.
Connectors can be thought of as "instance-specific" associations, because their values (which are links) are each limited to linking things identified via related features on the same instance of the connector's domain.
Any value of a connector property (such as mount) is a link instantiating its typing association (Mounting), for which the participants are values of the related features (axle and wheels) of the connector.
Instead of explicitly declaring connector ends in the body of a connector, they can also simply be listed between parentheses, in which case the connector ends are matched in order to corresponding association ends:
struct WheelAssembly { composite feature axle[1] : Axle; composite feature wheels[2] : Wheel; connector mount[2] : Mounting (axle, wheels); }
A special notation can be used for a binary connector, in which the source-related feature is referenced after the keyword from
, and the target-related feature is referenced after the keyword to
:
struct WheelAssembly { composite feature axle[1] : Axle; composite feature wheels[2] : Wheel; connector mount[2] : Mounting from axle to wheels; }
KerML allows using an even simpler syntax for defining such a connector:
struct HalfAxleAssembly { composite feature halfAxle[1] : HalfAxle; composite feature wheel[1] : Wheel; connector halfAxle to wheel; }
However, since this simplified syntax for defining binary connectors does not specify a name nor an underlying association, it is implied that a connector defined in this way is typed by the most general binary association BinaryLink, which is predefined in the library Links.
Connector ends may also be declared with cross multiplicities. In this case, the given cross multiplicity redefines the cross multiplicity that would otherwise be inherited from the association end corresponding to the connector end.
Bindings
Binding connectors (or simply bindings) are single-valued binary connectors that require their source and target features to have the same values on each instance of their domain. Unlike for a regular single-valued binary connector, the value of a binding is not a link object (an occurrence in space and time), but rather a (kind of abstract) binary link, typically between an output and an input feature. A binding is implicitly typed by the library association SelfLink
, which links things in the modeled universe to themselves.
A binding connector is declared using the keyword binding
by specifying a binding equation, as in the following example:
struct Vehicle { composite feature fuelTank { out feature fuelFlowOut : Fuel; } composite feature engine { in feature fuelFlowIn : Fuel; } binding fuelFlowBinding of fuelTank.fuelFlowOut = engine.fuelFlowIn; }
If no name is needed, the declaration of a binding connector can be simplified by just specifying the binding equation, like so:
binding fuelTank.fuelFlowOut = engine.fuelFlowIn;
8.6. Open Questions
1 Unnamed connector example
In section 7.4.6.2 Connector Declaration, there is the following example containing an unnamed binary connector declaration:
struct AxleAssembly { composite feature axle[1] : Axle; composite feature wheels[2] : Wheel; connector axle to wheels; }
How is an unnamed connector used (e.g., in a path expression)? Doesn't the example specify a single connection only between one of the two wheels and the axle?