77from typing_extensions import Literal
88
99from dve .core_engine .backends .base .reference_data import ReferenceConfig , ReferenceConfigUnion
10- from dve .core_engine .backends .metadata .contract import ChildHierarchyNode , DataContractMetadata , HierarchyNode , ReaderConfig
10+ from dve .core_engine .backends .metadata .contract import DataContractMetadata , ReaderConfig
1111from dve .core_engine .backends .metadata .rules import AbstractStep , Rule , RuleMetadata
1212from dve .core_engine .configuration .base import BaseEngineConfig
1313from dve .core_engine .configuration .v1 .filters import (
2020 BusinessFilterSpecConfig ,
2121 BusinessRuleSpecConfig ,
2222)
23+ from dve .core_engine .configuration .v1 .hierarchy import HierarchyNode , ChildHierarchyNode
2324from dve .core_engine .configuration .v1 .steps import StepConfigUnion
2425from dve .core_engine .message import DataContractErrorDetail
2526from dve .core_engine .type_hints import EntityName , ErrorCategory , ErrorType , TemplateVariables
@@ -90,6 +91,8 @@ class _LinkageConfig(BaseModel):
9091 """The name of the parent entity"""
9192 join_fields : JoinFields
9293 """The fields that can be used to link back to the parent entity"""
94+ mandatory : Optional [bool ] = False
95+ """If the entity is a child, is it a mandatory field of the parent"""
9396
9497
9598class _SchemaConfig (BaseModel ):
@@ -123,7 +126,6 @@ class _ModelConfig(_SchemaConfig):
123126 """Reader configuration options for the model."""
124127 aliases : dict [FieldName , FieldName ] = Field (default_factory = dict )
125128 """An alias field name mapping."""
126- linkage_details : Optional [_LinkageConfig ] = None
127129
128130
129131class _RuleStoreConfig (BaseModel ):
@@ -189,6 +191,8 @@ class V1EngineConfig(BaseEngineConfig):
189191 default_factory = dict
190192 )
191193 """Rule store rules from the loaded rule stores."""
194+ entity_relationships : dict [EntityName , _LinkageConfig ] = Field (default_factory = dict )
195+ """The parent-child relationships linking the defined entities"""
192196
193197 @validate_call
194198 def _update_rule_store (self , rule_store : dict [RuleName , BusinessComponentSpecConfigUnion ]):
@@ -341,8 +345,7 @@ def get_contract_metadata(self) -> DataContractMetadata:
341345 reader_metadata = reader_metadata ,
342346 validators = validators ,
343347 reporting_fields = reporting_fields ,
344- cache_originals = self .contract .cache_originals ,
345- linkage_hierarchy = self .determine_entity_hierarchy ()
348+ cache_originals = self .contract .cache_originals
346349 )
347350
348351 def load_error_message_info (self , uri ):
@@ -365,20 +368,22 @@ def get_rule_metadata(self) -> RuleMetadata:
365368 reference_data_config = self .get_reference_data_config (),
366369 )
367370
368- def determine_entity_hierarchy (self ) -> list [ HierarchyNode ]:
371+ def get_entity_hierarchy (self ) -> dict [ str , HierarchyNode ]:
369372 """Determine the linkage hierarchy using contact config"""
370- linkage_hierarchy = {name : model_conf .linkage_details for name , model_conf in self .contract .datasets .items ()}
371- top_level_parents = {}
372- for name , linkage_detail in linkage_hierarchy .items ():
373- if not linkage_detail :
374- top_level_parents [name ] = HierarchyNode (entity_name = name )
375- continue
373+ top_level_parents = {
374+ entity_name : HierarchyNode (entity_name = entity_name )
375+ for entity_name in self .contract .datasets
376+ if not entity_name in self .entity_relationships
377+ }
378+
379+ for name , linkage_detail in self .entity_relationships .items ():
376380 for main_entity , details in top_level_parents .items ():
377381 if (linkage_detail .parent_entity == main_entity
378382 or linkage_detail .parent_entity in details .get_descendents ()):
379383 top_level_parents [main_entity ].add_child_node (linkage_detail .parent_entity ,
380384 ChildHierarchyNode (entity_name = name ,
381- join_fields = linkage_detail .join_fields ))
385+ join_fields = linkage_detail .join_fields ,
386+ mandatory = linkage_detail .mandatory ))
382387 break
383388 else :
384389 raise EntityNotFoundError (f"Can't find parent entity { linkage_detail .parent_entity } defined to establish hierarchy for { name } - please ensure it is defined above any child entities in the dischema." )
0 commit comments