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
Core Concepts — Introduction to elements and relationships
Architecture Overview — How pyArchimate organizes packages
Model Class - Hierarchy & Query API Reference — Full Model and Element API reference
Hierarchy Code Examples — Code examples