8. Property Values and Property Value Management Tool (PVMT) support

capellambse provides access to property values and property value groups, as well as the additional information maintained by the Property Value Management Tool (PVMT) extension.

Let’s first take a look at how to work with basic property values.

[1]:
import capellambse

model = capellambse.MelodyModel(
    "../../../tests/data/melodymodel/5_0/Melody Model Test.aird"
)

Model objects can own property values and PV groups. To access those, use the property_values and property_value_groups attributes respectively:

[2]:
obj = model.search("LogicalComponent").by_name("Whomping Willow")
[3]:
obj.property_values
[3]:
  1. IntegerPropertyValue "cars_defeated": 1 (a928fa22-cef7-4357-9b87-675a432f6591)
[4]:
obj.property_values[0]
[4]:

cars_defeated (org.polarsys.capella.core.data.capellacore:IntegerPropertyValue)

applied_property_value_groups

(Empty list)

applied_property_values

(Empty list)

constraints

(Empty list)

description
diagrams

(Empty list)

enumerations

(Empty list)

filtering_criteria

(Empty list)

layerLogicalArchitecture "Logical Architecture" (853cb005-cba0-489b-8fe3-bb694ad4543b)
namecars_defeated
parentLogicalComponent "Whomping Willow" (3bdd4fa2-5646-44a1-9fa6-80c68433ddb7)
progress_statusNOT_SET
property_value_groups

(Empty list)

property_values

(Empty list)

pvmtProperty Value Management for IntegerPropertyValue "cars_defeated": 1 (a928fa22-cef7-4357-9b87-675a432f6591)
requirements

(Empty list)

summaryNone
traces

(Empty list)

uuida928fa22-cef7-4357-9b87-675a432f6591
validation<capellambse.extensions.validation._validate.ElementValidation object at 0x720dec0f03b0>
value1
xtypeorg.polarsys.capella.core.data.capellacore:IntegerPropertyValue
[5]:
obj.property_value_groups
[5]:
  1. PropertyValueGroup "Stats" (81bcc3d3-24d2-411e-a296-9943029acfd9)

8.1. dict-like access to property values

In addition to standard attribute-based access, these property value-related attributes can also behave like dicts in some cases. Here the dict key equates to the name of a property value or group, and the dict value equates to either the value of a property value object, or a list of PV objects in the group (which again can behave dict-like).

This significantly shortens the way to a specific value. For comparison, this would be the “usual” attribute-based way of accessing it:

[6]:
obj.property_value_groups.by_name("Stats").property_values.by_name("WIS").value
[6]:
150

And here is the same again, leveraging the dict-like behavior:

[7]:
obj.property_value_groups["Stats"]["WIS"]
[7]:
150

This of course also works for ungrouped property values:

[8]:
obj.property_values["cars_defeated"]
[8]:
1
[9]:
obj.property_value_groups["Stats"]
[9]:
  1. IntegerPropertyValue "HP": 8000 (0e95950d-272f-4b50-b68d-ee8fed002c94)
  2. IntegerPropertyValue "STR": 42 (32be6f26-4b33-4861-b501-3bfce3df94cb)
  3. IntegerPropertyValue "AGI": 0 (addb1e4a-9ecc-411c-b7ef-b76388e5840d)
  4. IntegerPropertyValue "WIS": 150 (7c8c9c21-86b9-4dba-9c7c-cd9db2f09c11)
  5. IntegerPropertyValue "INT": 12 (647a5565-a1de-4e15-ab21-eb628eea413c)
[10]:
obj.property_value_groups["Stats"]["WIS"]
[10]:
150

These property values can also be written to:

[11]:
obj.property_value_groups["Stats"]["INT"] = 18
obj.property_value_groups["Stats"]
[11]:
  1. IntegerPropertyValue "HP": 8000 (0e95950d-272f-4b50-b68d-ee8fed002c94)
  2. IntegerPropertyValue "STR": 42 (32be6f26-4b33-4861-b501-3bfce3df94cb)
  3. IntegerPropertyValue "AGI": 0 (addb1e4a-9ecc-411c-b7ef-b76388e5840d)
  4. IntegerPropertyValue "WIS": 150 (7c8c9c21-86b9-4dba-9c7c-cd9db2f09c11)
  5. IntegerPropertyValue "INT": 18 (647a5565-a1de-4e15-ab21-eb628eea413c)

9. Property Value Management (PVMT)

Property values become much more powerful when using the Property Value Management Tool extension. This extension groups property values into domains and groups, and allows to automatically apply certain groups based on specific conditions. These conditions may include the object class, the architectural layer, and other already applied property values.

Metadata about the defined domains and groups is stored in a package named “EXTENSIONS” at the root level of the model, which is conveniently accessible as model.pvmt. The package will automatically be created if it does not exist yet.

[12]:
model.pvmt
[12]:

EXTENSIONS (org.polarsys.capella.core.data.capellacore:PropertyValuePkg)

applied_property_value_groups

(Empty list)

applied_property_values

(Empty list)

constraints

(Empty list)

description
diagrams

(Empty list)

domains
  1. ManagedDomain "DarkMagic" (3763dd54-a878-446a-9330-b5d9c7121865)
filtering_criteria

(Empty list)

nameEXTENSIONS
parent<capellambse.model.MelodyModel object at 0x720df69da180>
progress_statusNOT_SET
property_value_groups

(Empty list)

property_values

(Empty list)

pvmtProperty Value Management for PropertyValuePkg "EXTENSIONS" (fdbeb3b8-e1e2-4c6d-aff4-bccb1b9f437f)
requirements

(Empty list)

summaryNone
traces

(Empty list)

uuidfdbeb3b8-e1e2-4c6d-aff4-bccb1b9f437f
validation<capellambse.extensions.validation._validate.ElementValidation object at 0x720dec2e55b0>
xtypeorg.polarsys.capella.core.data.capellacore:PropertyValuePkg

From there, we can easily enumerate the defined domains:

[13]:
model.pvmt.domains
[13]:
  1. ManagedDomain "DarkMagic" (3763dd54-a878-446a-9330-b5d9c7121865)

And see which groups are defined in that domain:

[14]:
domain = model.pvmt.domains["DarkMagic"]
domain.groups
[14]:
  1. ManagedGroup "DarkMagic.Power" (1e241678-282c-46f3-abbd-e0cf34e743ee)
  2. ManagedGroup "DarkMagic.Power Level" (a0cb5a23-955e-43d6-a633-2c4e66991364)
[15]:
group = domain.groups["Power Level"]
group
[15]:

Power Level (org.polarsys.capella.core.data.capellacore:PropertyValueGroup)

applied_property_value_groups

(Empty list)

applied_property_values

(Empty list)

constraints

(Empty list)

diagrams

(Empty list)

filtering_criteria

(Empty list)

fullnameDarkMagic.Power Level
namePower Level
parentPropertyValuePkg "DarkMagic" (3763dd54-a878-446a-9330-b5d9c7121865)
progress_statusNOT_SET
property_value_groups

(Empty list)

property_values
  1. EnumerationPropertyValue "Skill": EnumerationPropertyLiteral "TheOneWhoShallNotBeNamed" (4da42696-28e2-4f90-bfb6-90ba1fc52d01) (7367c731-aabb-4807-9d74-7ef2c6482ec9)
pvmtProperty Value Management for PropertyValueGroup "Power Level" (a0cb5a23-955e-43d6-a633-2c4e66991364)
requirements

(Empty list)

selectorSelectorRules(raw='[PROPERTY]DarkMagic.Power.Max<10000.0[/PROPERTY]\n[ARCHITECTURE]LOGICAL[/ARCHITECTURE]')
summaryNone
traces

(Empty list)

uuida0cb5a23-955e-43d6-a633-2c4e66991364
validation<capellambse.extensions.validation._validate.ElementValidation object at 0x720dec0f1850>
xtypeorg.polarsys.capella.core.data.capellacore:PropertyValueGroup

Group definitions also have a selector, which contains rules that determine the applicable model elements.

The current ruleset can be introspected by reading the attributes of the selector:

[16]:
print(group.selector.classes)
print(group.selector.layers)
print(group.selector.properties)
()
(<class 'capellambse.model.layers.la.LogicalArchitecture'>,)
(('DarkMagic.Power.Max', '<', '10000.0'),)

The ManagedGroup object provides some helper methods that interpret this selector:

[17]:
?group.find_applicable
Signature: group.find_applicable() -> 'c.ElementList'
Docstring: Find all elements in the model that this group applies to.
File:      ~/devspace/capellambse/capellambse/extensions/pvmt/_config.py
Type:      method
[18]:
group.find_applicable()
[18]:
  1. LogicalComponent "Harry J. Potter" (a8c46457-a702-41c4-a971-c815c4c5a674)
  2. LogicalComponent "Prof. A. P. W. B. Dumbledore" (08e02248-504d-4ed8-a295-c7682a614f66)
  3. LogicalComponent "R. Weasley" (ff7b8672-84db-4b93-9fea-22a410907fb1)
  4. LogicalComponent "Prof. S. Snape" (6f463eed-c77b-4568-8078-beec0536f243)
[19]:
?group.applies_to
Signature: group.applies_to(obj: 'c.ModelObject') -> 'bool'
Docstring: Determine whether this group applies to a model element.
File:      ~/devspace/capellambse/capellambse/extensions/pvmt/_config.py
Type:      method
[20]:
dumbledore = model.search("LogicalComponent").by_name(
    "Prof. A. P. W. B. Dumbledore"
)
group.applies_to(dumbledore)
[20]:
True

And finally, a group can be applied to an element with the apply method. If the group was already applied earlier, the existing group instance will be returned:

[21]:
group.apply(dumbledore)
[21]:

DarkMagic.Power Level (org.polarsys.capella.core.data.capellacore:PropertyValueGroup)

applied_property_value_groups
  1. PropertyValueGroup "Power Level" (a0cb5a23-955e-43d6-a633-2c4e66991364)
applied_property_values

(Empty list)

constraints

(Empty list)

description
diagrams

(Empty list)

filtering_criteria

(Empty list)

layerLogicalArchitecture "Logical Architecture" (853cb005-cba0-489b-8fe3-bb694ad4543b)
nameDarkMagic.Power Level
parentLogicalComponent "Prof. A. P. W. B. Dumbledore" (08e02248-504d-4ed8-a295-c7682a614f66)
progress_statusNOT_SET
property_value_groups

(Empty list)

property_values
  1. EnumerationPropertyValue "Skill": EnumerationPropertyLiteral "Mighty" (1e5efe87-d919-4bd0-af2b-7c976ef9da96) (ba86dc67-296c-472e-8057-b660d5491532)
pvmtProperty Value Management for PropertyValueGroup "DarkMagic.Power Level" (6cf12387-7187-4b91-9efe-8fedb8a148cb)
requirements

(Empty list)

summaryNone
traces

(Empty list)

uuid6cf12387-7187-4b91-9efe-8fedb8a148cb
validation<capellambse.extensions.validation._validate.ElementValidation object at 0x720dec24dcd0>
values
  1. EnumerationPropertyValue "Skill": EnumerationPropertyLiteral "Mighty" (1e5efe87-d919-4bd0-af2b-7c976ef9da96) (ba86dc67-296c-472e-8057-b660d5491532)
xtypeorg.polarsys.capella.core.data.capellacore:PropertyValueGroup

Each model element can have several property value groups applied to it. PVMT-managed groups can be easily inspected by using the element’s pvmt attribute:

[22]:
dumbledore.pvmt
[22]:

Property Value Management

Owner: LogicalComponent "Prof. A. P. W. B. Dumbledore" (08e02248-504d-4ed8-a295-c7682a614f66)

ManagedGroup "DarkMagic.Power" (1e241678-282c-46f3-abbd-e0cf34e743ee)
Min800.00.0
Max1600.010000.0
ManagedGroup "DarkMagic.Power Level" (a0cb5a23-955e-43d6-a633-2c4e66991364)
SkillEnumerationPropertyLiteral "Mighty" (1e5efe87-d919-4bd0-af2b-7c976ef9da96)EnumerationPropertyLiteral "TheOneWhoShallNotBeNamed" (4da42696-28e2-4f90-bfb6-90ba1fc52d01)
PropertyValueDefault

The groupdefs attribute will give access to the definitions of all groups that apply to this element:

[23]:
dumbledore.pvmt.groupdefs
[23]:
  1. ManagedGroup "DarkMagic.Power" (1e241678-282c-46f3-abbd-e0cf34e743ee)
  2. ManagedGroup "DarkMagic.Power Level" (a0cb5a23-955e-43d6-a633-2c4e66991364)

On the other hand, the applied_groups attribute will yield the group instances that are currently applied to the object.

Note: This list may be missing some groups from groupdefs. These can be applied using the group definition’s apply method (see above).

[24]:
dumbledore.pvmt.applied_groups
[24]:
  1. PropertyValueGroup "DarkMagic.Power" (42dc9aeb-a06d-4012-8bc6-02fb06f94cdc)
  2. PropertyValueGroup "DarkMagic.Power Level" (6cf12387-7187-4b91-9efe-8fedb8a148cb)

Property values can also be accessed using convenient dict-like semantics.

With keys like “Domain.Group”, an applied group instance will be returned, where the group is applied first if needed:

[25]:
dumbledore.pvmt["DarkMagic.Power"]
[25]:

DarkMagic.Power (org.polarsys.capella.core.data.capellacore:PropertyValueGroup)

applied_property_value_groups
  1. PropertyValueGroup "Power" (1e241678-282c-46f3-abbd-e0cf34e743ee)
applied_property_values

(Empty list)

constraints

(Empty list)

description
diagrams

(Empty list)

filtering_criteria

(Empty list)

layerLogicalArchitecture "Logical Architecture" (853cb005-cba0-489b-8fe3-bb694ad4543b)
nameDarkMagic.Power
parentLogicalComponent "Prof. A. P. W. B. Dumbledore" (08e02248-504d-4ed8-a295-c7682a614f66)
progress_statusNOT_SET
property_value_groups

(Empty list)

property_values
  1. FloatPropertyValue "Min": 800.0 (68b3e1b8-2d5a-432a-bf56-a8d3ad6b1742)
  2. FloatPropertyValue "Max": 1600.0 (defd6bbb-0209-47a6-b195-0e86f6210417)
pvmtProperty Value Management for PropertyValueGroup "DarkMagic.Power" (42dc9aeb-a06d-4012-8bc6-02fb06f94cdc)
requirements

(Empty list)

summaryNone
traces

(Empty list)

uuid42dc9aeb-a06d-4012-8bc6-02fb06f94cdc
validation<capellambse.extensions.validation._validate.ElementValidation object at 0x720df5da19d0>
values
  1. FloatPropertyValue "Min": 800.0 (68b3e1b8-2d5a-432a-bf56-a8d3ad6b1742)
  2. FloatPropertyValue "Max": 1600.0 (defd6bbb-0209-47a6-b195-0e86f6210417)
xtypeorg.polarsys.capella.core.data.capellacore:PropertyValueGroup

Keys may also contain a Property, in which case the value of that property is returned directly. This is similar to the basic property values shown in the first part of this notebook. However, like in the case without a Property, the group will first be applied if needed. Newly applied groups have all their properties set to the default values from the group definition.

[26]:
dumbledore.pvmt["DarkMagic.Power.Max"]
[26]:
1600.0

This latter style also supports directly setting individual properties.

[27]:
dumbledore.pvmt["DarkMagic.Power.Max"] = 9000
dumbledore.pvmt["DarkMagic.Power.Max"]
[27]:
9000.0