Skip to main content

Mountain/ApplicationState/State/FeatureState/Documents/
DocumentState.rs

1//! # DocumentState Module (ApplicationState)
2//!
3//! ## RESPONSIBILITIES
4//! Manages open documents state including document metadata, content, and
5//! version tracking.
6//!
7//! ## ARCHITECTURAL ROLE
8//! DocumentState is part of the **FeatureState** module, representing
9//! open documents state organized by document URI.
10//!
11//! ## KEY COMPONENTS
12//! - DocumentState: Main struct containing open documents map
13//! - Default: Initialization implementation
14//! - Helper methods: Document manipulation utilities
15//!
16//! ## ERROR HANDLING
17//! - Thread-safe access via `Arc<Mutex<...>>`
18//! - Proper lock error handling with `MapLockError` helpers
19//!
20//! ## LOGGING
21//! State changes are logged at appropriate levels (debug, info, warn, error).
22//!
23//! ## PERFORMANCE CONSIDERATIONS
24//! - Lock mutexes briefly and release immediately
25//! - Avoid nested locks to prevent deadlocks
26//! - Use Arc for shared ownership across threads
27//!
28//! ## TODO
29//! - [ ] Add document validation invariants
30//! - [ ] Implement document lifecycle events
31//! - [ ] Add document metrics collection
32
33use std::{
34	collections::HashMap,
35	sync::{Arc, Mutex as StandardMutex},
36};
37
38use crate::{ApplicationState::DTO::DocumentStateDTO::DocumentStateDTO, dev_log};
39
40/// Open documents state containing documents by URI.
41#[derive(Clone)]
42pub struct DocumentState {
43	/// Open documents organized by URI.
44	pub OpenDocuments:Arc<StandardMutex<HashMap<String, DocumentStateDTO>>>,
45}
46
47impl Default for DocumentState {
48	fn default() -> Self {
49		dev_log!("model", "[DocumentState] Initializing default document state...");
50
51		Self { OpenDocuments:Arc::new(StandardMutex::new(HashMap::new())) }
52	}
53}
54
55impl DocumentState {
56	/// Gets all open documents.
57	pub fn GetAll(&self) -> HashMap<String, DocumentStateDTO> {
58		self.OpenDocuments.lock().ok().map(|guard| guard.clone()).unwrap_or_default()
59	}
60
61	/// Gets a document by its URI.
62	pub fn Get(&self, uri:&str) -> Option<DocumentStateDTO> {
63		self.OpenDocuments.lock().ok().and_then(|guard| guard.get(uri).cloned())
64	}
65
66	/// Adds or updates a document.
67	pub fn AddOrUpdate(&self, uri:String, document:DocumentStateDTO) {
68		if let Ok(mut guard) = self.OpenDocuments.lock() {
69			guard.insert(uri, document);
70
71			dev_log!("model", "[DocumentState] Document added/updated");
72		}
73	}
74
75	/// Removes a document by its URI.
76	pub fn Remove(&self, uri:&str) {
77		if let Ok(mut guard) = self.OpenDocuments.lock() {
78			guard.remove(uri);
79
80			dev_log!("model", "[DocumentState] Document removed: {}", uri);
81		}
82	}
83
84	/// Clears all open documents.
85	pub fn Clear(&self) {
86		if let Ok(mut guard) = self.OpenDocuments.lock() {
87			guard.clear();
88
89			dev_log!("model", "[DocumentState] All documents cleared");
90		}
91	}
92
93	/// Gets the count of open documents.
94	pub fn Count(&self) -> usize { self.OpenDocuments.lock().ok().map(|guard| guard.len()).unwrap_or(0) }
95
96	/// Checks if a document exists.
97	pub fn Contains(&self, uri:&str) -> bool {
98		self.OpenDocuments
99			.lock()
100			.ok()
101			.map(|guard| guard.contains_key(uri))
102			.unwrap_or(false)
103	}
104
105	/// Gets all document URIs.
106	pub fn GetURIs(&self) -> Vec<String> {
107		self.OpenDocuments
108			.lock()
109			.ok()
110			.map(|guard| guard.keys().cloned().collect())
111			.unwrap_or_default()
112	}
113}