use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use serde_json::{Value, json};
use anyhow::{Result, anyhow};
#[derive(Debug, Clone)]
pub struct WorkflowContext {
data: Arc<Mutex<Value>>,
}
impl WorkflowContext {
pub fn new() -> Self {
Self {
data: Arc::new(Mutex::new(json!({}))),
}
}
pub fn set(&self, path: String, value: Value) -> Result<()> {
let mut data = self.data.lock()
.map_err(|_| anyhow!("Failed to acquire context lock"))?;
let parts: Vec<&str> = path.split('.').collect();
let (last_key, parent_parts) = parts.split_last()
.ok_or_else(|| anyhow!("Cannot set a value with an empty path"))?;
let mut current = &mut *data;
for part in parent_parts {
current = current.as_object_mut()
.ok_or_else(|| anyhow!(format!("Path part '{}' is not an object", part)))?
.entry(part.to_string())
.or_insert_with(|| json!({}));
}
if let Some(obj) = current.as_object_mut() {
obj.insert(last_key.to_string(), value);
} else {
return Err(anyhow!("Final path segment is not an object"));
}
Ok(())
}
pub fn resolve_path(&self, path: &str) -> Result<Option<Value>> {
let parts: Vec<&str> = path.split('.').collect();
if parts.is_empty() {
return Ok(None);
}
let data = self.data.lock()
.map_err(|_| anyhow!("Failed to acquire context lock"))?;
let pointer = format!("/{}", parts.join("/"));
Ok(data.pointer(&pointer).cloned())
}
pub fn get_as_value(&self) -> Result<Value> {
let data = self.data.lock()
.map_err(|_| anyhow!("Failed to acquire context lock"))?;
Ok(data.clone())
}
}