Model Class - Hierarchy & Query API Referenceο
Note
βοΈ New to this topic? Start with Element Hierarchies to understand how hierarchies work before exploring the full API reference.
The Model class provides comprehensive methods for managing element hierarchies, querying relationships, and organizing elements into parent-child structures with full round-trip XML preservation.
Hierarchy Management Methodsο
Creating Relationshipsο
- add_child(parent_uuid: str, child_uuid: str) Noneο
Add a parent-child relationship between two elements.
- Parameters:
parent_uuid β UUID of parent element
child_uuid β UUID of child element
- Raises:
KeyError β If parent or child UUID not in model
ValueError β If child already has parent, cycle would be created, or max depth exceeded
Features: - Automatic cycle detection prevents invalid hierarchies - Max depth limit (default 5 levels) prevents pathological nesting - Synchronizes bidirectional maps (parentβchildren and childβparent)
Example:
process = model.add(ArchiType.BusinessProcess, 'Order Management') func = model.add(ArchiType.BusinessFunction, 'Order Entry') service = model.add(ArchiType.BusinessService, 'Form Service') # Create hierarchy model.add_child(process.uuid, func.uuid) model.add_child(func.uuid, service.uuid)
- remove_child(parent_uuid: str, child_uuid: str) Noneο
Remove a parent-child relationship (orphan the child).
- Parameters:
parent_uuid β UUID of parent element
child_uuid β UUID of child element
- Raises:
KeyError β If parent or child UUID not in model
ValueError β If child is not actually a child of parent
Example:
model.remove_child(process.uuid, func.uuid) # func is now orphaned (no parent)
Basic Hierarchy Queriesο
- get_parent(elem_uuid: str) Element | Noneο
Get the parent element of a given element.
- Parameters:
elem_uuid β Element UUID
- Returns:
Parent Element or None if root
- Return type:
Optional[Element]
Example:
parent = model.get_parent(func.uuid) if parent: print(f"Parent: {parent.name}") else: print("Element is at root level")
- get_children(elem_uuid: str) list[Element]ο
Get all direct children of a given element.
- Parameters:
elem_uuid β Element UUID
- Returns:
List of child Elements (empty if no children)
- Return type:
list[Element]
Example:
children = model.get_children(process.uuid) for child in children: print(f"Child: {child.name}")
Root and Leaf Queriesο
Ancestry and Depth Methodsο
- get_ancestors(elem_uuid: str) list[Element]ο
Get all ancestors of an element from the element itself to the root.
- Parameters:
elem_uuid β Element UUID
- Returns:
List of Elements [elem, parent, grandparent, β¦, root]
- Return type:
list[Element]
Example:
ancestors = model.get_ancestors(service.uuid) # Returns: [service, func, process] for ancestor in ancestors: print(f"Ancestor: {ancestor.name}")
- get_descendants(elem_uuid: str) list[Element]ο
Get all descendants of an element in breadth-first order.
- Parameters:
elem_uuid β Element UUID
- Returns:
List of descendant Elements (excludes the element itself)
- Return type:
list[Element]
Example:
descendants = model.get_descendants(process.uuid) # Returns all elements under process at any depth for desc in descendants: print(f"Descendant: {desc.name}")
- get_depth(elem_uuid: str) intο
Get the nesting depth of an element (0 = root).
- Parameters:
elem_uuid β Element UUID
- Returns:
Depth level
- Return type:
int
Example:
depth = model.get_depth(service.uuid) if depth == 0: print("Root element") else: print(f"Depth: {depth}")
Advanced Query Methodsο
Sibling Queriesο
- get_siblings(elem_uuid: str) list[Element]ο
Get all sibling elements (elements with same parent).
- Parameters:
elem_uuid β UUID of element to find siblings for
- Returns:
List of sibling Elements (excludes elem_uuid itself)
- Return type:
list[Element]
- Raises:
KeyError β If element UUID not in model
Example:
# Create multiple functions under process func1 = model.add(ArchiType.BusinessFunction, 'Order Entry') func2 = model.add(ArchiType.BusinessFunction, 'Order Review') model.add_child(process.uuid, func1.uuid) model.add_child(process.uuid, func2.uuid) # Get siblings of func1 siblings = model.get_siblings(func1.uuid) # Returns: [func2]
Path-Based Hierarchy Queriesο
- find_by_hierarchy_path(path: str) list[Element]ο
Find elements by hierarchy path with wildcard support.
- Parameters:
path β Hierarchy path string starting with β/β, levels separated by β/β
- Returns:
List of matching Elements
- Return type:
list[Element]
Path Format: - Absolute paths:
/Root,/Parent/Child/Grandchild- Wildcard suffix:/Parent/Child/*(matches all children of Child) - Wildcard in path:/Parent/*/Grandchild(matches any Child)Examples:
# Get specific element by path results = model.find_by_hierarchy_path('/Order Management') # Returns: [order_management_elem] # Get all children at specific depth results = model.find_by_hierarchy_path('/Order Management/Order Entry') # Returns: [order_entry_elem] # Get all grandchildren (wildcard) results = model.find_by_hierarchy_path('/Order Management/*') # Returns: [func1, func2, func3, ...] # Get deep descendants (wildcard in middle) results = model.find_by_hierarchy_path('/Order Management/*/Services') # Returns all Services under any function in Order Management
Performance Characteristicsο
Time Complexity:
add_child(): O(depth) - performs cycle detectionget_parent(): O(1) - direct map lookupget_children(): O(n) - where n = number of childrenget_ancestors(): O(depth) - walks parent chainget_descendants(): O(m) - where m = number of descendants (BFS)get_siblings(): O(n) - where n = number of siblingsfind_by_hierarchy_path(): O(m) - where m = elements matching path
Performance on Large Models:
Cycle detection: <1ms (max depth 5)
All queries: <10ms on 1000+ element models
Memory: ~100 bytes per parent-child relationship
Round-Trip Preservationο
All hierarchy relationships are automatically preserved during XML export/import:
import tempfile, os
from pyArchimate import Model, ArchiType
# Create model with hierarchy
m = Model('round-trip-test')
process = m.add(ArchiType.BusinessProcess, 'Process')
func = m.add(ArchiType.BusinessFunction, 'Function')
m.add_child(process.uuid, func.uuid)
# Export to XML
with tempfile.NamedTemporaryFile(suffix='.archimate', delete=False) as f:
tmp_path = f.name
m.write(tmp_path)
# Import from XML
m2 = Model('reloaded')
m2.read(tmp_path)
os.unlink(tmp_path)
# Hierarchy is preserved exactly
process2 = m2.elems_dict[process.uuid]
func2 = m2.elems_dict[func.uuid]
parent = m2.get_parent(func2.uuid)
print(f"Parent preserved: {parent.uuid == process2.uuid}")
print(f"Child name: {func2.name}")
Parent preserved: True
Child name: Function
Constraints and Limitsο
Depth Limit: Maximum nesting depth is 5 levels (configurable) - Prevents stack overflow on deep traversals - Suitable for most enterprise architectures
Single Parent: Each element can have at most one parent - Creates tree structures (not DAGs) - Simplifies hierarchy management and visualization
Cycle Prevention: Automatic validation prevents circular relationships - add_child() rejects any relationship that would create a cycle - Ensures hierarchy validity at all times
See Alsoο
Element Hierarchies: Complete hierarchy usage guide
Hierarchy Code Examples: Working code examples
Element Class API Reference: Element class API reference