Element Hierarchies

Note

🔧 Intermediate / Architecture — Learn how to organize elements into parent-child hierarchies and query relationships within them.

What Is a Hierarchy?

A hierarchy (or composite structure) is a parent-child relationship between elements of the same type. Hierarchies allow you to:

  • Organize complex systems into sub-systems

  • Represent nested processes or services

  • Group related elements for readability

For example, a business process can have sub-processes, which can have further sub-processes (up to a typical depth limit of 5 levels in ArchiMate).

The relationship type for parent-child composition is RelationType.ComposedOf.

Creating Hierarchies

Adding a child element

Use the add_child method on an element:

from pyArchimate import Model, ArchiType, RelationType

model = Model(name="Processes")

# Create a parent process
parent = model.add_element(
    name="Order Management",
    element_type=ArchiType.BusinessProcess
)

# Add a child process
child = model.add_element(
    name="Receive Order",
    element_type=ArchiType.BusinessProcess
)

# Create the parent-child relationship
model.add_child(parent=parent, child=child)

Maximum nesting depth

ArchiMate typically restricts hierarchy depth to 5 levels. When adding a child, check that the nesting depth doesn’t exceed this limit:

from pyArchimate import Model, ArchiType

model = Model(name="Nested Processes")
elements = []

# Create 5-level deep hierarchy
for i in range(5):
    elem = model.add_element(
        name=f"Level {i}",
        element_type=ArchiType.BusinessProcess
    )
    elements.append(elem)
    if i > 0:
        model.add_child(parent=elements[i-1], child=elem)

# Attempting to add a 6th level child should be validated
level6 = model.add_element(
    name="Level 6",
    element_type=ArchiType.BusinessProcess
)
# Check depth before adding
if elements[-1].get_depth() < 5:
    model.add_child(parent=elements[-1], child=level6)

Querying Hierarchies

Get parent

Retrieve the parent of an element:

child_elem = model.get_element("child_id")
parent = child_elem.get_parent()

Get children

Retrieve direct children of an element:

parent_elem = model.get_element("parent_id")
children = parent_elem.get_children()

Get ancestors

Retrieve all ancestors up the hierarchy:

elem = model.get_element("some_id")
ancestors = elem.get_ancestors()  # [parent, grandparent, ...]

Get descendants

Retrieve all descendants down the hierarchy:

elem = model.get_element("root_id")
descendants = elem.get_descendants()  # All children, grandchildren, etc.

Get depth

Get the depth of an element in the hierarchy (root level = 0):

elem = model.get_element("some_id")
depth = elem.get_depth()

Find by hierarchy path

Query elements using a path-like syntax with wildcards:

# Find all processes at depth 2
results = model.find_by_hierarchy_path("Level 0/Level 1/*")

# Find elements matching a pattern
results = model.find_by_hierarchy_path("*/Receive*")

Removing Hierarchies

Remove a child

Remove a parent-child relationship:

parent = model.get_element("parent_id")
child = model.get_element("child_id")
model.remove_child(parent=parent, child=child)

Orphaning behavior

When you remove a parent-child relationship, the child element remains in the model but loses its parent (becomes an “orphan”):

model.remove_child(parent=parent, child=child)
assert child.get_parent() is None  # Child is now orphaned
assert child in model.elements  # But still exists in the model

Round-Trip Preservation

When you read and write a model, hierarchies are preserved in all supported formats:

# Read a model with hierarchies
model = Model.read("original.archimate")

# Modify the model
# ...

# Write back - hierarchies are preserved
model.write("modified.archimate")

The ComposedOf relationship type is preserved during round-trip, ensuring your hierarchy structure survives export and re-import cycles.

Practical Example: Decomposing a Service

Here’s a practical example of building a multi-level service decomposition:

from pyArchimate import Model, ArchiType

model = Model(name="Service Decomposition")

# Create the top-level service
payment_service = model.add_element(
    name="Payment Service",
    element_type=ArchiType.ApplicationService
)

# Add sub-services (level 2)
payment_processing = model.add_element(
    name="Payment Processing",
    element_type=ArchiType.ApplicationService
)
fraud_detection = model.add_element(
    name="Fraud Detection",
    element_type=ArchiType.ApplicationService
)

model.add_child(parent=payment_service, child=payment_processing)
model.add_child(parent=payment_service, child=fraud_detection)

# Add sub-sub-services (level 3)
card_auth = model.add_element(
    name="Card Authorization",
    element_type=ArchiType.ApplicationService
)
model.add_child(parent=payment_processing, child=card_auth)

# Query the hierarchy
print(f"Payment Service has {len(payment_service.get_children())} direct children")
print(f"Payment Service has {len(payment_service.get_descendants())} total descendants")

# Write to file (hierarchy preserved)
model.write("service_hierarchy.archimate")

See Also