Skip to content

Navigating a reflexive association

Leon Starr edited this page Nov 6, 2023 · 6 revisions

A reflexive association starts and ends on the same class. So navigation involves an originating instance set that yields another instance set on the same class.

An asymmetric reflexive association has a verb phrase on each side (Folder contains/is contained in). That is because the role differs depending on an instance’s perspective with the multiplicity and conditionality on each side being potentially, but not necessarily, different. By contrast, a symmetric reflexive association (Territory/is adjacent to) has only one verb phrase since there is no distinction in perspective and, consequently, only one multiplicity and conditionality that is the same, by definition, from either perpsective.

Since an asymmetric reflexive association may be accessed in two directions to reach instances of the same class, it is essential to specify the relationship phrase in the desired direction. It is not enough to only specify the relationship name (Rnumber).

Assume, for example, that a number of aircraft are following one another in a holding pattern. Starting from some instance of Aircraft, to the one it follows, this action assigns that instance:

follow ac .= /R3/is following/Aircraft

Note that the class name at the end isn’t really necessary to resolve the path. All you need is a relationship name and the phrase in the appropriate direction.

Also note that the .= assignment operator is used since at most one instance can be selected on R3 which is a 0..1:0..1 reflexive association.

If the reflexive association is symmetric, there is only one relationship phrase so there is no need to specify it. The relationship name is adequate. In the Risk game example we have the Territory is adjacent to (many to many) symmetric reflexive association. So you could write:

neighbors ..= /is adjacent to/

Now let’s say that you want to find the nearest Aircraft in sequence at a higher altitude.

higher follow ac .= /OR3/is following/~/( ITS.Altitude > )

Note that we are hopping across an ordinal association as indicated by the “O” in the relationship name. (Instead of relying entirely on referential attributes to formalize the order, some attribute of type Ordinal, a numerical ordering type, sequences the instances). But you don’t have to worry about this detail other than using the correct relationship name for our purposes here.

The repeated hop symbol /~/indicates continued traversal until either the criteria that follows is met or there are no more links to hop or a link back to the local instance is encountered. This last case prevents a cycle of references from being traversed endlessly.

The selection predicate will often compare an attribute of the referenced class with the same attribute of the local instance. To avoid confusion, the attribute of the referenced instance is prefaced with the keyword ITS, with that of the local instance optionally left implicit. In the above example, the criteria reads: “with a greater altitude than the local instance”.

Now let’s say that we want the next aircraft whose altitude is near the local instance’s altitude within some higher/lower delta.

same level follow ac .= /OR3/is following/~/( (ITS.Altitude - Altitude).abs <= delta )

You can see why the ITS keyword was important since we are subtracting the local instance’s Altitude and we need to distinguish the two.

Note the use of the abs operation to get the absolute value of the difference. We use the dot notation instead of the more familiar abs() notation. It helps clarify that we are not performing a selection on some class named “abs”.

Rather than closest, to find the leading aircraft that is the furthest number of hops away on OR3, use the repeated hop to end /~| symbol.

leading higher follow ac .= /OR3/is following/~|( ITS.Altitude > )

Here we traverse to the furthest rather than the nearest instance away that matches the filter criteria.

Alternatively, you can compare to the local attribute eliminating the need for the ITS keyword:

leading higher follow ac .= /OR3/is following/~|( Altitude <= )

Combined navigation and selection

You can hop around narrowing selection quite a bit in a single line. Consider the following action language that selects one or more elevator Shafts best suited to service a floor call.

in service shafts ..= /R1/Shaft( In service )
best cabin .= in service shafts/R2/Cabin(1,
    ^-Estimated travel delay( To floor : in.calling floor, Calling dir: ^dir )
)

=>> best cabin/R2/Shaft

In the example above, we hop to all Shafts whose In service attribute is true and save them in the in service shafts instance set variable. Then we hop to all related **Cabins ** sorting for the least returned value from the Estimated travel delay method invoked on each Cabin instance and assign one of them. The associated Shaft instance is then returned.

Introduction

Model semantics

Flows (as Variables)

Constants and literals

Structure of an activity

Accessing the class model

Data flow


Grammar and parsing notes

Components

Clone this wiki locally