context_weaver/core/processors/
mod.rs

1use std::{collections::{HashMap, HashSet}, sync::{Arc, RwLock}};
2use log::{debug, error, trace, warn};
3use serde::de::DeserializeOwned;
4use serde_json::Value;
5use crate::{ParserError, WorldInfoNode, WorldInfoProcessor};
6use std::fmt::Debug;
7
8pub struct WorldInfoRegistry<P: PluginBridge + 'static> {
9    processor_factories: RwLock<HashMap<String, Box<dyn WorldInfoProcessorFactory<P>>>>,
10    plugin_bridge: Arc<P>,
11    variables: HashMap<String, serde_json::Value>,
12    activation_stack: HashSet<String>
13}
14
15pub struct ScopedRegistry<'a, P: PluginBridge + 'static> {
16    inner: &'a mut WorldInfoRegistry<P>,
17    allowed_scopes: &'a [String],
18    scope_id: String
19}
20
21impl <'a, P: PluginBridge + 'static> ScopedRegistry<'a, P> {
22    pub fn instantiate_processor(&self, name: &str, props: &serde_json::Value) -> Option<Box<dyn WorldInfoNode>> {
23        self.inner.instantiate_processor(name, props)
24    }
25}
26
27pub trait VariableResolver {
28    /// Gets a variable's value, potentially checking a loop context first.
29    fn get_variable(&self, name: &str, loop_context: Option<&HashMap<String, Value>>) -> Result<Value, ParserError>;
30    /// Inserts a new variable. Loop context is not relevant here.
31    fn insert_variable(&mut self, name: &str, value: Value) -> Result<(), ParserError>;
32    /// Updates an existing variable. Loop context is not relevant here.
33    fn update_variable(&mut self, name: &str, value: Value) -> Result<(), ParserError>;
34    /// Resolves implicit scopes (e.g., `entry:foo` -> `<scope_id>:foo`).
35    fn resolve_scope(&self, name: &str) -> Result<(String, String), ParserError>;
36}
37
38pub trait ActivationResolver {
39    fn push_activation(&mut self, id: &str) -> Result<(), ParserError>;
40}
41
42impl<'a, P: PluginBridge> VariableResolver for ScopedRegistry<'a, P> {
43    fn get_variable(&self, full_name: &str, loop_context: Option<&HashMap<String, Value>>) -> Result<Value, ParserError> {
44        trace!("ScopedRegistry::get_variable: full_name='{}', loop_context is {}", full_name, if loop_context.is_some() { "Some" } else { "None" });
45
46        // Check loop context first for unscoped or potentially local-scoped variables
47        if let Some(context) = loop_context {
48            if !full_name.contains(':') { // Unscoped name check
49                if let Some(value) = context.get(full_name) {
50                    debug!("Found variable '{}' in loop context (unscoped)", full_name);
51                    return Ok(value.clone());
52                }
53                // If not in loop context, fall through to default scope resolution below
54                trace!("Variable '{}' not found in loop context (unscoped), proceeding to registry lookup.", full_name);
55            } else {
56                // Scoped name check: See if it resolves to local scope and exists in context
57                match self.resolve_scope(full_name) {
58                    Ok((ref scope, ref name)) if scope == &self.scope_id => {
59                        // Resolved scope matches the current local scope_id
60                        if let Some(value) = context.get(name) {
61                            debug!("Found variable '{}:{}' (resolved to local) in loop context", scope, name);
62                            return Ok(value.clone());
63                        }
64                        trace!("Variable '{}:{}' (resolved to local) not found in loop context, proceeding to registry lookup.", scope, name);
65                    }
66                    Ok((scope, name)) => {
67                        // Resolved to a non-local scope, ignore loop context
68                        trace!("Variable '{}:{}' resolved to non-local scope, ignoring loop context.", scope, name);
69                    }
70                    Err(_) => {
71                        // If resolve_scope fails (e.g., invalid format), fall through to registry lookup which will also likely fail
72                        trace!("Could not resolve scope for '{}', proceeding to registry lookup.", full_name);
73                    }
74                }
75            }
76        } else {
77            trace!("No loop context provided for variable lookup '{}'.", full_name);
78        }
79
80        // Proceed with normal registry lookup if not found in loop context or context not applicable
81        let (scope, name) = self.resolve_scope(full_name)?;
82        trace!("Registry lookup: Resolved scope='{}', name='{}'", scope, name);
83        if !self.allowed_scopes.contains(&scope) {
84            error!("Permission denied for scope '{}' trying to access variable '{}'", scope, name);
85            return Err(ParserError::InsufficientPermissions(
86                format!("No access to scope `{}`", scope)
87            ));
88        }
89        let key = format!("{}:{}", scope, name);
90        trace!("Looking up key '{}' in inner variables", key);
91        self.inner.variables // Assuming inner is the WorldInfoRegistry
92            .get(&key)
93            .cloned()
94            .ok_or_else(|| {
95                warn!("Variable '{}' not found in registry (key: '{}')", name, key);
96                ParserError::UndefinedVariable(name) // Use the resolved name part
97            })
98    }
99
100    // insert_variable, update_variable, resolve_scope remain the same as provided in the prompt
101    // ... (rest of ScopedRegistry impl VariableResolver) ...
102     fn resolve_scope(&self, name: &str) -> Result<(String, String), ParserError> {
103        let (scope, name_part) = name.split_once(':').ok_or_else(|| {
104            // If no colon, assume it's meant to be local within this scope
105            trace!("Resolving unscoped name '{}' as local to scope '{}'", name, self.scope_id);
106            (self.scope_id.clone(), name.to_string())
107        })
108        .map_err(|_| ParserError::Evaluation(format!("Invalid variable name: {}", name)))?;
109
110        match scope {
111            // Treat "entry" and "local" explicitly as the current scope_id
112            "entry" | "local" => Ok((self.scope_id.clone(), name_part.to_string())),
113            // Other scopes are passed through as is
114            _ => Ok((scope.to_string(), name_part.to_string()))
115        }
116    }
117
118    fn insert_variable(&mut self, full_name: &str, value: Value) -> Result<(), ParserError> {
119        let (scope, name) = self.resolve_scope(full_name)?;
120        let key = format!("{}:{}", scope, name);
121        trace!("ScopedRegistry::insert_variable: key='{}'", key);
122
123        match scope.as_str() {
124            "global" => {
125                if self.inner.variables.contains_key(&key) {
126                    Err(ParserError::VariableAlreadyExists(name))
127                } else {
128                    self.inner.variables.insert(key, value); // Directly access inner registry
129                    Ok(())
130                }
131            }
132            _ => {
133                // Check if the resolved scope is allowed for insertion
134                if !self.allowed_scopes.contains(&scope) {
135                    error!("Permission denied to insert into scope '{}' for variable '{}'", scope, name);
136                    Err(ParserError::InsufficientPermissions(
137                        format!("No permission to insert into scope `{}`", scope)
138                    ))
139                } else if self.inner.variables.contains_key(&key) {
140                    error!("Variable '{}' already exists in scope '{}'", name, scope);
141                    Err(ParserError::VariableAlreadyExists(name))
142                } else {
143                    debug!("Inserting variable '{}' into scope '{}'", name, scope);
144                    self.inner.variables.insert(key, value);
145                    Ok(())
146                }
147            }
148        }
149    }
150
151    fn update_variable(&mut self, full_name: &str, value: Value) -> Result<(), ParserError> {
152        let (scope, name) = self.resolve_scope(full_name)?;
153        trace!("ScopedRegistry::update_variable: scope='{}', name='{}'", scope, name);
154
155        // Allow updating global scope, but check permissions for others
156        if scope != "global" && !self.allowed_scopes.contains(&scope) {
157            error!("Permission denied to update variable in scope '{}' for variable '{}'", scope, name);
158            return Err(ParserError::InsufficientPermissions(
159                format!("No permission to update in scope `{}`", scope)
160            ));
161        }
162
163        let key = format!("{}:{}", scope, name);
164        if let Some(slot) = self.inner.variables.get_mut(&key) {
165            debug!("Updating variable '{}' in scope '{}'", name, scope);
166            *slot = value;
167            Ok(())
168        } else {
169            error!("Attempted to update undefined variable '{}' in scope '{}'", name, scope);
170            Err(ParserError::UndefinedVariable(name))
171        }
172    }
173}
174
175impl<P: PluginBridge + 'static> VariableResolver for WorldInfoRegistry<P> {
176    // WorldInfoRegistry ignores loop context as it represents the global state
177    fn get_variable(&self, name: &str, _loop_context: Option<&HashMap<String, Value>>) -> Result<Value, ParserError> {
178        trace!("WorldInfoRegistry::get_variable: name='{}', loop_context ignored", name);
179        let (scope, name_part) = self.resolve_scope(name)?; // Use name_part to avoid shadowing
180        let key = format!("{}:{}", scope, name_part);
181        trace!("WorldInfoRegistry lookup: key='{}'", key);
182        self.variables
183            .get(&key)
184            .cloned()
185            .ok_or_else(|| {
186                warn!("WorldInfoRegistry: Variable '{}' (key: '{}') not found.", name_part, key);
187                ParserError::UndefinedVariable(name_part)
188            })
189    }
190
191    // insert_variable, update_variable, resolve_scope remain the same as provided
192    // ... (rest of WorldInfoRegistry impl VariableResolver) ...
193
194     fn insert_variable(&mut self, name: &str, value: Value) -> Result<(), ParserError> {
195        let (scope, name_part) = self.resolve_scope(name)?;
196        let key = format!("{}:{}", scope, name_part);
197        trace!("WorldInfoRegistry::insert_variable: key='{}'", key);
198
199        if self.variables.contains_key(&key) {
200            error!("WorldInfoRegistry: Variable '{}' already exists in scope '{}'", name_part, scope);
201            Err(ParserError::VariableAlreadyExists(name_part))
202        } else {
203            debug!("WorldInfoRegistry: Inserting variable '{}' into scope '{}'", name_part, scope);
204            self.variables.insert(key, value);
205            Ok(())
206        }
207    }
208
209    fn update_variable(&mut self, name: &str, value: Value) -> Result<(), ParserError> {
210        let (scope, name_part) = self.resolve_scope(name)?;
211        let key = format!("{}:{}", scope, name_part);
212        trace!("WorldInfoRegistry::update_variable: key='{}'", key);
213
214        if let Some(slot) = self.variables.get_mut(&key) {
215            debug!("WorldInfoRegistry: Updating variable '{}' in scope '{}'", name_part, scope);
216            *slot = value;
217            Ok(())
218        } else {
219            error!("WorldInfoRegistry: Attempted to update undefined variable '{}' in scope '{}'", name_part, scope);
220            Err(ParserError::UndefinedVariable(name_part))
221        }
222    }
223
224     fn resolve_scope(&self, name: &str) -> Result<(String, String), ParserError> {
225        // WorldInfoRegistry can only resolve global scope directly
226        let (scope, name_part) = name.split_once(':').ok_or_else(|| {
227            error!("WorldInfoRegistry::resolve_scope: Unscoped variable access attempted: '{}'. Only 'global:' scope allowed.", name);
228            ParserError::InsufficientPermissions(format!("WorldInfoRegistry cannot access unscoped variable: {}. Use 'global:' prefix.", name))
229        })?;
230
231        match scope {
232            "global" => Ok(("global".to_string(), name_part.to_string())),
233            _ => {
234                error!("WorldInfoRegistry::resolve_scope: Non-global scope access attempted: '{}:{}'. Only 'global:' scope allowed.", scope, name_part);
235                Err(ParserError::InsufficientPermissions(format!("WorldInfoRegistry cannot access scope '{}'. Use 'global:' prefix.", scope)))
236            }
237        }
238    }
239}
240
241impl<P: PluginBridge + 'static> ActivationResolver for ScopedRegistry<'_, P> {
242    fn push_activation(&mut self, id: &str) -> Result<(), ParserError> {
243        self.inner.push_activation(id)
244    }
245}
246
247impl <P: PluginBridge + 'static> ActivationResolver for WorldInfoRegistry<P> {
248    fn push_activation(&mut self, id: &str) -> Result<(), ParserError> {
249        self.activation_stack.insert(id.to_string());
250        Ok(())
251    }
252}
253
254impl<P: PluginBridge + 'static> WorldInfoRegistry<P> {
255    pub fn new(plugin_bridge: Arc<P>) -> Self {
256        Self {
257            processor_factories: RwLock::new(HashMap::new()),
258            plugin_bridge,
259            variables: HashMap::new(),
260            activation_stack: HashSet::new()
261        }
262    }
263
264    pub fn register_processor(&self, name: &str, factory: Box<dyn WorldInfoProcessorFactory<P>>) {
265        self.processor_factories.write().unwrap().insert(name.to_string(), factory);
266    }
267
268    pub fn register_plugin_processor(&self, author: &str, name: &str) {
269        self.register_processor(format!("weaver.plugin.{}.{}", author, name).as_str(), Box::new(plugin::PluginProcessorFactory));
270    }
271
272    pub fn instantiate_processor(&self, name: &str, props: &serde_json::Value) -> Option<Box<dyn WorldInfoNode>> {
273        let registry = self.processor_factories.read().unwrap();
274        registry.get(name).map(|factory| factory.create(props, &self.plugin_bridge) as Box<dyn WorldInfoNode>)
275    }
276
277    pub fn plugin_bridge(&self) -> &P {
278        &self.plugin_bridge
279    }
280
281    /// Used for initial variable registration
282    /// 
283    /// This method bypasses scope checks
284    pub fn register_variable(&mut self, var: String, value: serde_json::Value) {
285        self.variables.insert(var, value);
286    }
287
288    pub(crate) fn scoped_registry<'a>(&'a mut self, allowed_scopes: &'a [String], scope_id: String) -> ScopedRegistry<'a, P> {
289        ScopedRegistry { inner: self, allowed_scopes, scope_id }
290    }
291
292    /// Returns a copy of the activation stack, clearing it in the process
293    pub(crate) fn activation_stack(&mut self) -> HashSet<String> {
294        let stack = self.activation_stack.clone();
295        self.activation_stack.clear();
296        stack
297    }
298}
299
300// Define the factory trait
301pub trait WorldInfoProcessorFactory<P: PluginBridge + 'static>: Send + Sync + 'static {
302    fn create(&self, properties: &serde_json::Value, bridge: &Arc<P>) -> Box<dyn WorldInfoProcessor>;
303}
304
305pub trait PluginBridge: Clone + Debug {
306    type PluginId: Copy + DeserializeOwned + Debug;
307    fn invoke_plugin(&self, plugin_id: Self::PluginId, properties: serde_json::Value) -> Result<String, crate::WorldInfoError>;
308}
309
310// Declare submodules
311pub mod wildcard;
312pub mod rng;
313pub mod plugin;
314
315// Re-export processors and factories
316pub use wildcard::{WildcardProcessor, WildcardProcessorFactory};
317pub use rng::{RngProcessor, RngProcessorFactory};