Mountain/ApplicationState/State/ConfigurationState/
ConfigurationState.rs

1//! # ConfigurationState Module (ApplicationState)
2//!
3//! ## RESPONSIBILITIES
4//!
5//! Manages configuration and storage state including global configuration,
6//! workspace configuration, and memento storage buffers.
7//!
8//! ## ARCHITECTURAL ROLE
9//!
10//! ConfigurationState is part of the **state organization layer**, representing
11//! all configuration and storage-related state in the application. This
12//! includes:
13//! - Global configuration (merged from all sources)
14//! - Workspace configuration
15//! - Global memento storage (for crash recovery)
16//! - Workspace memento storage
17//!
18//! ## KEY COMPONENTS
19//! - State: Main struct containing configuration and storage fields
20//! - Default: Initialization implementation
21//! - Helper methods: Configuration and storage manipulation utilities
22//!
23//! ## ERROR HANDLING
24//!
25//! - Thread-safe access via `Arc<Mutex<...>>`
26//! - Proper lock error handling with `MapLockError` helpers
27//!
28//! ## LOGGING
29//!
30//! State changes are logged at appropriate levels (debug, info, warn, error).
31//!
32//! ## PERFORMANCE CONSIDERATIONS
33//!
34//! - Lock mutexes briefly and release immediately
35//! - Avoid nested locks to prevent deadlocks
36//! - Use Arc for shared ownership across threads
37//!
38//! ## TODO
39//! - [ ] Add configuration validation invariants
40//! - [ ] Implement configuration change events
41//! - [ ] Add configuration diffing
42
43use std::{
44	collections::HashMap,
45	sync::{Arc, Mutex as StandardMutex},
46};
47
48use log::debug;
49
50use crate::ApplicationState::DTO::MergedConfigurationStateDTO::MergedConfigurationStateDTO;
51
52/// Configuration and storage state.
53#[derive(Clone)]
54pub struct State {
55	/// Merged global configuration from all sources.
56	pub GlobalConfiguration:Arc<StandardMutex<serde_json::Value>>,
57
58	/// Merged workspace configuration from all sources.
59	pub WorkspaceConfiguration:Arc<StandardMutex<serde_json::Value>>,
60
61	/// Global memento storage for crash recovery.
62	pub MementoGlobalStorage:Arc<StandardMutex<HashMap<String, serde_json::Value>>>,
63
64	/// Workspace memento storage for crash recovery.
65	pub MementoWorkspaceStorage:Arc<StandardMutex<HashMap<String, serde_json::Value>>>,
66}
67
68impl Default for State {
69	fn default() -> Self {
70		debug!("[ConfigurationState] Initializing default configuration state...");
71
72		Self {
73			GlobalConfiguration:Arc::new(StandardMutex::new(serde_json::Value::Object(serde_json::Map::new()))),
74			WorkspaceConfiguration:Arc::new(StandardMutex::new(serde_json::Value::Object(serde_json::Map::new()))),
75			MementoGlobalStorage:Arc::new(StandardMutex::new(HashMap::new())),
76			MementoWorkspaceStorage:Arc::new(StandardMutex::new(HashMap::new())),
77		}
78	}
79}
80
81impl State {
82	/// Gets the global configuration.
83	pub fn GetGlobalConfiguration(&self) -> serde_json::Value {
84		self.GlobalConfiguration
85			.lock()
86			.map(|g| g.clone())
87			.unwrap_or(serde_json::Value::Object(serde_json::Map::new()))
88	}
89
90	/// Sets the global configuration.
91	pub fn SetGlobalConfiguration(&self, config:serde_json::Value) {
92		if let Ok(mut guard) = self.GlobalConfiguration.lock() {
93			*guard = config;
94			debug!("[ConfigurationState] Global configuration updated");
95		}
96	}
97
98	/// Gets the workspace configuration.
99	pub fn GetWorkspaceConfiguration(&self) -> serde_json::Value {
100		self.WorkspaceConfiguration
101			.lock()
102			.map(|g| g.clone())
103			.unwrap_or(serde_json::Value::Object(serde_json::Map::new()))
104	}
105
106	/// Sets the workspace configuration.
107	pub fn SetWorkspaceConfiguration(&self, config:serde_json::Value) {
108		if let Ok(mut guard) = self.WorkspaceConfiguration.lock() {
109			*guard = config;
110			debug!("[ConfigurationState] Workspace configuration updated");
111		}
112	}
113
114	/// Gets a value from global configuration at a specific path.
115	pub fn GetGlobalValue(&self, path:&str) -> Option<serde_json::Value> {
116		self.GetGlobalConfiguration().get(path).cloned()
117	}
118
119	/// Sets a value in global configuration at a specific path.
120	/// This implementation uses the MergedConfigurationStateDTO's SetValue
121	/// method which properly handles nested object creation and value
122	/// assignment.
123	pub fn SetGlobalValue(&self, path:&str, value:serde_json::Value) {
124		if let Ok(mut config_guard) = self.GlobalConfiguration.lock() {
125			// Clone the current config for manipulation
126			let current_config = (*config_guard).clone();
127
128			// Create DTO to leverage its SetValue method
129			let mut dto = MergedConfigurationStateDTO { Data:current_config };
130
131			// Use the DTO's SetValue method which handles nested paths properly
132			if let Err(e) = dto.SetValue(path, value) {
133				log::warn!("[ConfigurationState] Failed to set value at path '{}': {}", path, e);
134				return;
135			}
136
137			// Write the updated data back
138			*config_guard = dto.Data;
139
140			debug!("[ConfigurationState] Global configuration value updated at: {}", path);
141		}
142	}
143
144	/// Gets all global memento storage.
145	pub fn GetGlobalMemento(&self) -> HashMap<String, serde_json::Value> {
146		self.MementoGlobalStorage
147			.lock()
148			.ok()
149			.map(|guard| guard.clone())
150			.unwrap_or_default()
151	}
152
153	/// Sets all global memento storage.
154	pub fn SetGlobalMemento(&self, storage:HashMap<String, serde_json::Value>) {
155		if let Ok(mut guard) = self.MementoGlobalStorage.lock() {
156			*guard = storage;
157			debug!("[ConfigurationState] Global memento storage updated ({} keys)", guard.len());
158		}
159	}
160
161	/// Gets a value from global memento storage.
162	pub fn GetGlobalMementoValue(&self, key:&str) -> Option<serde_json::Value> {
163		self.MementoGlobalStorage.lock().ok().and_then(|guard| guard.get(key).cloned())
164	}
165
166	/// Sets a value in global memento storage.
167	pub fn SetGlobalMementoValue(&self, key:String, value:serde_json::Value) {
168		if let Ok(mut guard) = self.MementoGlobalStorage.lock() {
169			guard.insert(key.clone(), value);
170			debug!("[ConfigurationState] Global memento value updated for key: {}", key);
171		}
172	}
173
174	/// Gets all workspace memento storage.
175	pub fn GetWorkspaceMemento(&self) -> HashMap<String, serde_json::Value> {
176		self.MementoWorkspaceStorage
177			.lock()
178			.ok()
179			.map(|guard| guard.clone())
180			.unwrap_or_default()
181	}
182
183	/// Sets all workspace memento storage.
184	pub fn SetWorkspaceMemento(&self, storage:HashMap<String, serde_json::Value>) {
185		if let Ok(mut guard) = self.MementoWorkspaceStorage.lock() {
186			*guard = storage;
187			debug!("[ConfigurationState] Workspace memento storage updated ({} keys)", guard.len());
188		}
189	}
190
191	/// Gets a value from workspace memento storage.
192	pub fn GetWorkspaceMementoValue(&self, key:&str) -> Option<serde_json::Value> {
193		self.MementoWorkspaceStorage
194			.lock()
195			.ok()
196			.and_then(|guard| guard.get(key).cloned())
197	}
198
199	/// Sets a value in workspace memento storage.
200	pub fn SetWorkspaceMementoValue(&self, key:String, value:serde_json::Value) {
201		if let Ok(mut guard) = self.MementoWorkspaceStorage.lock() {
202			guard.insert(key.clone(), value);
203			debug!("[ConfigurationState] Workspace memento value updated for key: {}", key);
204		}
205	}
206
207	/// Clears a value from workspace memento storage.
208	pub fn ClearWorkspaceMementoValue(&self, key:&str) {
209		if let Ok(mut guard) = self.MementoWorkspaceStorage.lock() {
210			guard.remove(key);
211			debug!("[ConfigurationState] Workspace memento value removed for key: {}", key);
212		}
213	}
214
215	/// Clears global memento storage.
216	pub fn ClearGlobalMemento(&self) {
217		if let Ok(mut guard) = self.MementoGlobalStorage.lock() {
218			guard.clear();
219			debug!("[ConfigurationState] Global memento storage cleared");
220		}
221	}
222
223	/// Clears workspace memento storage.
224	pub fn ClearWorkspaceMemento(&self) {
225		if let Ok(mut guard) = self.MementoWorkspaceStorage.lock() {
226			guard.clear();
227			debug!("[ConfigurationState] Workspace memento storage cleared");
228		}
229	}
230}