use std::collections::HashSet;
use cognee_models::DataPoint;
use uuid::Uuid;
use crate::task::Value;
pub use cognee_models::HasDataPoint;
#[derive(Clone, Copy)]
pub struct ProvenanceContext<'a> {
pub pipeline_name: &'a str,
pub task_name: &'a str,
pub user_label: Option<&'a str>,
pub node_set: Option<&'a str>,
pub content_hash: Option<&'a str>,
}
pub fn stamp_tree(
root: &mut dyn HasDataPoint,
ctx: &ProvenanceContext<'_>,
visited: &mut HashSet<Uuid>,
) {
let dp_id = root.data_point().id;
if !visited.insert(dp_id) {
return;
}
{
let dp = root.data_point_mut();
if dp.source_pipeline.is_none() {
dp.source_pipeline = Some(ctx.pipeline_name.to_string());
}
if dp.source_task.is_none() {
dp.source_task = Some(ctx.task_name.to_string());
}
if dp.source_user.is_none()
&& let Some(u) = ctx.user_label
{
dp.source_user = Some(u.to_string());
}
}
let current_node_set = match root.data_point().source_node_set.as_deref() {
Some(v) => Some(v.to_string()),
None => ctx.node_set.map(|s| s.to_string()),
};
if root.data_point().source_node_set.is_none()
&& let Some(v) = ctx.node_set
{
root.data_point_mut().source_node_set = Some(v.to_string());
}
let current_hash = match root.data_point().source_content_hash.as_deref() {
Some(v) => Some(v.to_string()),
None => ctx.content_hash.map(|s| s.to_string()),
};
if root.data_point().source_content_hash.is_none()
&& let Some(v) = ctx.content_hash
{
root.data_point_mut().source_content_hash = Some(v.to_string());
}
let child_ctx = ProvenanceContext {
pipeline_name: ctx.pipeline_name,
task_name: ctx.task_name,
user_label: ctx.user_label,
node_set: current_node_set.as_deref(),
content_hash: current_hash.as_deref(),
};
root.for_each_child_mut(&mut |child| {
stamp_tree(child, &child_ctx, visited);
});
}
pub fn extract_node_set_from_value(value: &dyn Value) -> Option<String> {
downcast_to_datapoint(value).and_then(|dp| dp.source_node_set.clone())
}
pub fn extract_content_hash_from_value(value: &dyn Value) -> Option<String> {
use cognee_models::Data;
if let Some(d) = value.as_any().downcast_ref::<Data>()
&& !d.content_hash.is_empty()
{
return Some(d.content_hash.clone());
}
downcast_to_datapoint(value).and_then(|dp| dp.source_content_hash.clone())
}
fn downcast_to_datapoint(value: &dyn Value) -> Option<&DataPoint> {
use cognee_models::{Document, DocumentChunk, EdgeType, Entity, EntityType};
if let Some(d) = value.as_any().downcast_ref::<Document>() {
return Some(&d.base);
}
if let Some(d) = value.as_any().downcast_ref::<DocumentChunk>() {
return Some(&d.base);
}
if let Some(d) = value.as_any().downcast_ref::<Entity>() {
return Some(&d.base);
}
if let Some(d) = value.as_any().downcast_ref::<EntityType>() {
return Some(&d.base);
}
if let Some(d) = value.as_any().downcast_ref::<EdgeType>() {
return Some(&d.base);
}
None
}
pub fn stamp_tree_dyn(
value: &mut dyn Value,
ctx: &ProvenanceContext<'_>,
visited: &mut HashSet<Uuid>,
) -> bool {
use cognee_models::{Document, DocumentChunk, EdgeType, Entity, EntityType};
let any = value.as_any_mut();
if let Some(d) = any.downcast_mut::<Document>() {
stamp_tree(d, ctx, visited);
return true;
}
if let Some(d) = any.downcast_mut::<DocumentChunk>() {
stamp_tree(d, ctx, visited);
return true;
}
if let Some(d) = any.downcast_mut::<Entity>() {
stamp_tree(d, ctx, visited);
return true;
}
if let Some(d) = any.downcast_mut::<EntityType>() {
stamp_tree(d, ctx, visited);
return true;
}
if let Some(d) = any.downcast_mut::<EdgeType>() {
stamp_tree(d, ctx, visited);
return true;
}
if let Some(items) = any.downcast_mut::<Vec<Document>>() {
for item in items.iter_mut() {
stamp_tree(item, ctx, visited);
}
return true;
}
if let Some(items) = any.downcast_mut::<Vec<DocumentChunk>>() {
for item in items.iter_mut() {
stamp_tree(item, ctx, visited);
}
return true;
}
if let Some(items) = any.downcast_mut::<Vec<Entity>>() {
for item in items.iter_mut() {
stamp_tree(item, ctx, visited);
}
return true;
}
if let Some(items) = any.downcast_mut::<Vec<EntityType>>() {
for item in items.iter_mut() {
stamp_tree(item, ctx, visited);
}
return true;
}
if let Some(items) = any.downcast_mut::<Vec<EdgeType>>() {
for item in items.iter_mut() {
stamp_tree(item, ctx, visited);
}
return true;
}
false
}