33import json
44from typing import Any , Iterable , Optional , Union
55
6- from pydantic import BaseModel , Field
6+ from pydantic import BaseModel , Field , field_validator
77
88from dve .core_engine .configuration .v1 import V1EngineConfig , _LinkageConfig
99from dve .core_engine .type_hints import EntityName , ErrorCode , ErrorMessage
@@ -16,8 +16,18 @@ class HierarchyNode(BaseModel):
1616 """Stores entity hierarchy information"""
1717
1818 entity_name : str
19- children : Optional [list ["ChildHierarchyNode" ]] = Field (default_factory = list )
20-
19+ children : Optional [list ["HierarchyNode" ]] = Field (default_factory = list )
20+ mandatory : Optional [bool ] = False
21+ join_fields : Optional [dict [str , str ]] = Field (default_factory = dict )
22+ no_valid_records_error_code : Optional [ErrorCode ] = "NoValidRecords"
23+ no_valid_records_error_message : Optional [ErrorMessage ] = (
24+ "parent record removed as no valid child records"
25+ )
26+ missing_parent_id_error_code : Optional [ErrorCode ] = "MissingParentRecord"
27+ missing_parent_id_error_message : Optional [ErrorMessage ] = (
28+ "Records removed due to no valid parent record"
29+ )
30+
2131 def get_descendents (self ) -> list [str ]:
2232 """Recursively list all descendents of the node"""
2333 descendents = []
@@ -58,19 +68,6 @@ def as_dict(self) -> dict[str, dict[str, Any]]:
5868 return {self .entity_name : ret_dict }
5969
6070
61- class ChildHierarchyNode (HierarchyNode ):
62- """Stores child entity hierarchy information"""
63-
64- join_fields : dict [str , str ]
65- mandatory : Optional [bool ] = False
66- no_valid_records_error_code : Optional [ErrorCode ] = "NoValidRecords"
67- no_valid_records_error_message : Optional [ErrorMessage ] = (
68- "parent record removed as no valid child records"
69- )
70- orphaned_records_error_code : Optional [ErrorCode ] = "OrphanedRecords"
71- orphaned_records_error_message : Optional [ErrorMessage ] = "Orphaned records removed"
72-
73-
7471class EntityHierarchy :
7572 """Determines and stores entity hierarchy information from config"""
7673
@@ -82,11 +79,24 @@ def determine_trees(
8279 all_datasets : Iterable [str ], entity_relationships : dict [str , _LinkageConfig ]
8380 ) -> dict [EntityName , HierarchyNode ]:
8481 """Determine the entity hierarchy trees and store as HierarchyNodes"""
82+ root_entities : dict [str , _LinkageConfig ] = dict (filter (lambda x : x [1 ].is_root_entity ,
83+ entity_relationships .items ()))
8584 top_level_parents : dict [EntityName , HierarchyNode ] = {
86- entity_name : HierarchyNode (entity_name = entity_name )
87- for entity_name in all_datasets
88- if entity_name not in entity_relationships
85+ entity_name : HierarchyNode (entity_name = entity_name ,
86+ ** config .model_dump (exclude = {"parent_entity" ,
87+ "missing_parent_id_error_code" ,
88+ "missing_parent_id_error_message" }),
89+ missing_parent_id_error_code = None ,
90+ missing_parent_id_error_message = None )
91+ for entity_name , config in root_entities .items ()
8992 }
93+
94+ if default_roots := [ entity_name for entity_name in all_datasets
95+ if not entity_name in entity_relationships ]:
96+ for entity_name in default_roots :
97+ top_level_parents [entity_name ] = HierarchyNode (entity_name = entity_name ,
98+ missing_parent_id_error_code = None ,
99+ missing_parent_id_error_message = None )
90100
91101 for name , linkage_detail in entity_relationships .items ():
92102 for main_entity , parent_node in top_level_parents .items ():
@@ -96,7 +106,7 @@ def determine_trees(
96106 ):
97107 parent_node .add_child_node (
98108 linkage_detail .parent_entity ,
99- ChildHierarchyNode (
109+ HierarchyNode (
100110 entity_name = name , ** linkage_detail .model_dump (exclude = {"parent_entity" })
101111 ),
102112 )
0 commit comments