3.4. Component references

A “component reference” is an attribute value that specifies a CellML component.

  1. A component reference SHALL be a CellML identifier.

  2. The component identified by a component reference SHALL be determined as follows:

    1. If the component reference is identical to the value of the name attribute of a component element in the same infoset, then it SHALL refer to the component specified by that element.

    2. If the component reference is identical to the value of the name attribute of an import component element in the same infoset, then it SHALL refer to a component from the infoset defined by the import component element (see 3.1 Interpretation of import elements).

      1. The component specified SHALL then be determined by treating the value of the component_ref attribute on the import component element as a component reference within the imported infoset.

      2. If necessary, this rule SHALL be applied recursively.

  3. If no component can be identified using the rules above, then the attribute value SHALL NOT be a valid component reference.

See more

Understanding component references

As with references to units and variables, the term “component reference” refers to places where you need to refer to a component using its name. This is done through the component_ref attribute found in import component and encapsulation elements, as well as the component_1 and component_2 attributes of connection elements.

The complicated part occurs during imports, and involves understanding the scope of a component’s reference. This is really just the appropriate name by which to call it depending on who is doing the calling.

Consider the following example. Here, two families live next door to one another, and within each family use the terms “husband” and “wife” to refer to their own component members. In the local “LeadbetterFamilyModel” and “GoodFamilyModel” model contexts, “husband” and “wife” are the name attributes of the local components. In the wider neighbourhood, however, each person must be referred to by their real-world name: “BarbaraGood”, “TomGood”, “JerryLeadbetter”, and “MargotLeadbetter”. In the “SurbitonNeighbourhood” model context, the real-world names of “BarbaraGood” etc. are treated as name attributes of local component elements (even though they’re imported), but now the “husband” and “wife” terms are component_ref elements, as they are not the context providing the name.

model: SurbitonNeighbourhood
  ├─ component: TomGood <╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐
  ├─ component: BarbaraGood <╴╴╴╴╴╴╴╴╴┐ ╷
  ├─ component: MargotLeadbetter <╴╴╷ ╷ ╷
  └─ component: JerryLeadbetter <╴┐ ╷ ╷ ╷
                                  ╷ ╷ ╷ ╷
                           imported components
                                  ╵ ╵ ╵ ╵
# In LeadbetterFamily.cellml:     ╵ ╵ ╵ ╵
model: LeadbetterFamilyModel      ╵ ╵ ╵ ╵
  ├─ component: husband ╴╴╴╴╴╴╴╴╴╴┘ ╵ ╵ ╵
  └─ component: wife ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘ ╵ ╵
                                      ╵ ╵
# In GoodFamily.cellml:               ╵ ╵
model: GoodFamilyModel                ╵ ╵
  ├─ component: wife ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘ ╵
  └─ component: husband ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘

See CellML syntax

<model name="SurbitonNeighbourhood">

  <!-- Importing two families into the neighbourhood. -->
  <import xlink:href="GoodFamily.cellml">
    <!-- Within the family, the members are called "wife" and "husband", but after
        importing into the neighbourhood, these same components are now referred
        to by the names "BarbaraGood" and "TomGood". -->
    <component name="BarbaraGood" component_ref="wife" />
    <component name="TomGood" component_ref="husband" />
  </import>

  <import xlink:href="LeadbetterFamily.cellml">
    <!-- Even though the component_ref attributes here are the same as above
        (i.e.: "wife" and "husband") they are interpreted within the context
        of the imported model (i.e.: the "TheLeadbetterFamilyUnit" model imported
        from the "LeadbetterFamily.cellml" file), and so refer to separate things.
    -->
    <component name="MargotLeadbetter" component_ref="wife" />
    <component name="JerryLeadbetter" component_ref="husband" />
  </import>

</model>

<!-- Inside the GoodFamily.cellml file: -->
<model name="TheGoodFamilyUnit">
  <component name="husband" />
  <component name="wife" />
</model>

<!-- Inside the LeadbetterFamily.cellml file: -->
<model name="TheLeadbetterFamilyUnit">
  <component name="husband" />
  <component name="wife" />
</model>

Now let’s make things more interesting by adding an encapsulation hierarchy:

model: SurbitonNeighbourhood
  ├─ component: WomenInTheNeighbourhood
  │   ├─ component: BarbaraGood <╴╴╴╴╴╴╴╴╴╴╴┐
  │   └─ component: MargotLeadbetter <╴╴╴╴┐ ╷
  └─ component: MenInTheNeighbourhood     ╷ ╷
      ├─ component: TomGood <╴╴╴╴╴╴╴╴╴╴╴┐ ╷ ╷
      └─ component: JerryLeadbetter <╴┐ ╷ ╷ ╷
                                      ╷ ╷ ╷ ╷
                              imported components
                                      ╵ ╵ ╵ ╵
# In LeadbetterFamily.cellml:         ╵ ╵ ╵ ╵
model: LeadbetterFamilyModel          ╵ ╵ ╵ ╵
  ├─ component: husband ╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘ ╵ ╵ ╵
  └─ component: wife ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┼╴┘ ╵
                                        ╵   ╵
# In GoodFamily.cellml:                 ╵   ╵
model: GoodFamilyModel                  ╵   ╵
  ├─ component: husband ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘   ╵
  └─ component: wife ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘

See CellML syntax

<model name="SurbitonNeighbourhood">
  ...
  <component name="WomenInTheNeighbourhood" />
  <component name="MenInTheNeighbourhood" />

  <!-- Throughout the importing model (i.e.: this model), the imported
      items are referred to by their local name attribute ("BarbaraGood" etc),
      not the name they are called within their imported family units ("wife"). -->
  <encapsulation>
    <component_ref component="WomenInTheNeighbourhood">
      <component_ref component="BarbaraGood" />
      <component_ref component="MargotLeadbetter" />
    </component_ref>
    <component_ref component="MenInTheNeighbourhood">
      <component_ref component="TomGood" />
      <component_ref component="JerryLeadbetter" />
    </component_ref>
  </encapsulation>
</model>

This particular encapsulation structure means that the women (Barbara and Margot) are essentially unable to have any contact with the men (Tom and Jerry) even though their original components in the models from which they were imported were able to access one another.

Note also that these locality-based naming-calling rules will be applied through multiple generations of importing. Since The Good Life is a TV show, there are actors who play the roles of each of the characters. This could be reflected by using another generation of imports within the two family files like this:

  model: SurbitonNeighbourhood
    ├─ component: WomenInTheNeighbourhood
    │   ├─ component: BarbaraGood <╴╴╴╴╴╴╴╴╴╴╴╴╴┐
    │   └─ component: MargotLeadbetter <╴╴╴╴╴╴┐ ╷
    └─ component: MenInTheNeighbourhood       ╷ ╷
        ├─ component: TomGood <╴╴╴╴╴╴╴╴╴╴╴╴╴┐ ╷ ╷
        └─ component: JerryLeadbetter <╴╴╴┐ ╷ ╷ ╷
                                          ╷ ╷ ╷ ╷
                                imported components
                                          ╵ ╵ ╵ ╵
          # In LeadbetterFamily.cellml:   ╵ ╵ ╵ ╵
          model: TheLeadbetterFamilyUnit  ╵ ╵ ╵ ╵
  ┌╴╴╴╴╴╴╴╴> ├─ component: husband ╴╴╴╴╴╴╴┘ ╵ ╵ ╵
  ╷ ┌ ╴╴╴╴╴> └─ component: wife ╴╴╴╴╴╴╴╴╴╴╴╴┼╴┘ ╵
  ╷ ╷                                       ╵   ╵
  ╷ ╷     # In GoodFamily.cellml:           ╵   ╵
  ╷ ╷     model: TheGoodFamilyUnit          ╵   ╵
  ╷ ╷ ┌╴╴╴> ├─ component: husband ╴╴╴╴╴╴╴╴╴╴┘   ╵
  ╷ ╷ ╷ ┌╴> └─ component: wife ╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘
  ╷ ╷ ╷ ╷
imported components
  ╵ ╵ ╵ ╵
  ╵ ╵ ╵ ╵  # In CastOfCharacters.cellml:
  ╵ ╵ ╵ ╵  model:
  ╵ ╵ ╵ └╴╴╴├─ component: FelicityKendal
  ╵ ╵ └╴╴╴╴╴├─ component: RichardBriers
  ╵ └╴╴╴╴╴╴╴├─ component: PenelopeKeith
  └╴╴╴╴╴╴╴╴╴└─ component: PaulEddington

See CellML syntax

<!-- Inside the GoodFamily.cellml file: -->
<model name="TheGoodFamilyUnit">
  <import xlink:href="CastOfCharacters.cellml">
    <component name="husband" component_ref="RichardBriers" />
    <component name="wife" component_ref="FelicityKendal" />
  </import>
</model>

<!-- Inside the LeadbetterFamily.cellml file: -->
<model name="TheLeadbetterFamilyUnit">
  <import xlink:href="CastOfCharacters.cellml">
    <component name="husband" component_ref="PaulEddington" />
    <component name="wife" component_ref="PenelopeKeith" />
  </import>
</model>

Note that in this situation, the original SurbitonNeighbourhood model does not need to change at all. Each of the component references remains correct, as each is isolated in its own scope.