Repeatable relationship path specification

TypeScript type: RepeatableRelationshipPathSpecification.

This specification declares a step in a relationship path between a source and target ECInstances. A step can optionally be repeated a number of times to traverse the same relationship recursively. Multiple specifications of this type can be chained together to express complex indirect relationships.

The specification is always used in a context where source class already exists, so it only requires the relationship and direction. The target class can be inferred from the two required attributes or specified with the targetClass attribute. In case of a multi-step path, target of the current step is used as the source of the next step.

Attributes

Name Required? Type Default
relationship Yes SingleSchemaClassSpecification
direction Yes "Forward" | "Backward"
targetClass No SingleSchemaClassSpecification Other end of the relationship
count No number | "*" 1

Attribute: relationship

This attribute specifies the ECRelationship that should be used to traverse to target class.

Type SingleSchemaClassSpecification
Is Required Yes

Attribute: direction

This attribute specifies the direction in which the relationship should be followed:

  • "Forward" - the relationship is traversed from source to target of the relationship.
  • "Backward" - the relationship is traversed from target to source of the relationship.
Type "Forward" | "Backward"
Is Required Yes

Attribute: targetClass

This attribute may be used to specialize the target of the relationship. E.g. when relationship points to a class like bis.Element, this attribute allows specializing it to bis.PhysicalElement or some other bis.Element subclass.

Type SingleSchemaClassSpecification
Is Required No
Default Value Target ECClass of the relationship if the direction is "Forward" or source ECClass if the direction is "Backward"

Attribute: count

When a number is specified, the relationship is traversed recursively the specified number of times.

When it is set to a special value "*", the same relationship is traversed recursively unbounded number of times, starting from zero (the relationship is not followed). On each traversal iteration, Presentation rules engine accumulates all indirectly related ECInstances as defined by the remaining relationship path.

Type number | "*"
Is Required No
Default Value 1

Examples

When the count attribute is omitted or set to 1, the specification works similarly to RelationshipPathSpecification. See its examples section for those simpler cases.

Jumping through the same relationship recursively fixed number of times

// This ruleset defines a specification that returns content for given `bis.Element` instances by
// returning their grandparent property values.
const ruleset: Ruleset = {
  id: "example",
  rules: [{
    ruleType: "Content",
    condition: `SelectedNode.IsOfClass("Element", "BisCore")`,
    specifications: [
      {
        specType: "ContentRelatedInstances",
        relationshipPaths: [{
          relationship: { schemaName: "BisCore", className: "ElementOwnsChildElements" },
          direction: "Backward",
          count: 2,
        }],
      },
    ],
  }],
};

Content of the grand-parent element

Jumping through the relationship recursively unbounded number of times

// This ruleset defines a specification that returns content for all children of the given `bis.Element`.
const ruleset: Ruleset = {
  id: "example",
  rules: [{
    ruleType: "Content",
    condition: `SelectedNode.IsOfClass("Element", "BisCore")`,
    specifications: [
      {
        specType: "ContentRelatedInstances",
        relationshipPaths: [{
          relationship: { schemaName: "BisCore", className: "ElementOwnsChildElements" },
          direction: "Forward",
          count: "*",
        }],
      },
    ],
  }],
};

When the root subject is provided as input, content for all its child elements is returned:

Content of all root subject's child elements

Combining recursive and non-recursive steps

// This ruleset defines a specification that returns content for categories of all elements in
// the given `bis.Model` and their children.
const ruleset: Ruleset = {
  id: "example",
  rules: [{
    ruleType: "Content",
    condition: `SelectedNode.IsOfClass("Model", "BisCore")`,
    specifications: [
      {
        specType: "ContentRelatedInstances",
        relationshipPaths: [[{
          relationship: { schemaName: "BisCore", className: "ModelContainsElements" },
          direction: "Forward",
          targetClass: { schemaName: "BisCore", className: "GeometricElement3d" },
        }, {
          relationship: { schemaName: "BisCore", className: "ElementOwnsChildElements" },
          direction: "Forward",
          targetClass: { schemaName: "BisCore", className: "GeometricElement3d" },
          count: "*",
        }, {
          relationship: { schemaName: "BisCore", className: "GeometricElement3dIsInCategory" },
          direction: "Forward",
        }]],
      },
    ],
  }],
};

When a physical model is provided as input, categories' content of all its elements and their children is returned:

Categories' content of model elements and their children

Combining multiple unbounded recursive steps

// The ruleset contains a three-step relationship path that finds all `bis.GeometricElement3d` elements related to given model
// through the `bis.ModelContainsElements` relationship, then finds all `bis.SpatialCategory` elements related to `bis.GeometricElement3d`
// found in the previous step through `bis.GeometricElement3dIsInCategory` relationship and finds all `bis.SubCategory` elements related
// to `bis.SpatialCategory` found in the previous step through `bis.CategoryOwnsSubCategories` relationship.
// The result includes `bis.GeometricElement3d`, `bis.SpatialCategory` and `bis.SubCategory` elements.
const ruleset: Ruleset = {
  id: "example",
  rules: [{
    ruleType: "Content",
    condition: `SelectedNode.IsOfClass("Model", "BisCore")`,
    specifications: [
      {
        specType: "ContentRelatedInstances",
        relationshipPaths: [[{
          relationship: { schemaName: "BisCore", className: "ModelContainsElements" },
          direction: "Forward",
          targetClass: { schemaName: "BisCore", className: "GeometricElement3d" },
          count: "*",
        }, {
          relationship: { schemaName: "BisCore", className: "GeometricElement3dIsInCategory" },
          direction: "Forward",
          targetClass: { schemaName: "BisCore", className: "SpatialCategory" },
          count: "*",
        }, {
          relationship: { schemaName: "BisCore", className: "CategoryOwnsSubCategories" },
          direction: "Forward",
          count: "*",
        }]],
      },
    ],
  }],
};

Content of multiple recursive relationship steps

Last Updated: 24 January, 2023