data_modelling_core/export/
knowledge.rs1use crate::export::ExportError;
6use crate::models::knowledge::{KnowledgeArticle, KnowledgeIndex};
7
8pub struct KnowledgeExporter;
10
11impl KnowledgeExporter {
12 pub fn new() -> Self {
14 Self
15 }
16
17 pub fn export(&self, article: &KnowledgeArticle) -> Result<String, ExportError> {
27 let yaml = article.to_yaml().map_err(|e| {
28 ExportError::SerializationError(format!("Failed to serialize knowledge article: {}", e))
29 })?;
30
31 #[cfg(feature = "schema-validation")]
33 {
34 use crate::validation::schema::validate_knowledge_internal;
35 validate_knowledge_internal(&yaml).map_err(ExportError::ValidationError)?;
36 }
37
38 Ok(yaml)
39 }
40
41 pub fn export_without_validation(
46 &self,
47 article: &KnowledgeArticle,
48 ) -> Result<String, ExportError> {
49 article.to_yaml().map_err(|e| {
50 ExportError::SerializationError(format!("Failed to serialize knowledge article: {}", e))
51 })
52 }
53
54 pub fn export_index(&self, index: &KnowledgeIndex) -> Result<String, ExportError> {
64 index.to_yaml().map_err(|e| {
65 ExportError::SerializationError(format!("Failed to serialize knowledge index: {}", e))
66 })
67 }
68
69 pub fn export_to_directory(
81 &self,
82 articles: &[KnowledgeArticle],
83 dir_path: &std::path::Path,
84 workspace_name: &str,
85 ) -> Result<usize, ExportError> {
86 if !dir_path.exists() {
88 std::fs::create_dir_all(dir_path)
89 .map_err(|e| ExportError::IoError(format!("Failed to create directory: {}", e)))?;
90 }
91
92 let mut count = 0;
93 for article in articles {
94 let filename = article.filename(workspace_name);
95 let path = dir_path.join(&filename);
96 let yaml = self.export(article)?;
97 std::fs::write(&path, yaml).map_err(|e| {
98 ExportError::IoError(format!("Failed to write {}: {}", filename, e))
99 })?;
100 count += 1;
101 }
102
103 Ok(count)
104 }
105
106 pub fn export_domain_to_directory(
119 &self,
120 articles: &[KnowledgeArticle],
121 dir_path: &std::path::Path,
122 workspace_name: &str,
123 domain: &str,
124 ) -> Result<usize, ExportError> {
125 let filtered: Vec<&KnowledgeArticle> = articles
126 .iter()
127 .filter(|a| a.domain.as_deref() == Some(domain))
128 .collect();
129
130 let domain_dir = dir_path.join(domain);
132 if !domain_dir.exists() {
133 std::fs::create_dir_all(&domain_dir)
134 .map_err(|e| ExportError::IoError(format!("Failed to create directory: {}", e)))?;
135 }
136
137 let mut count = 0;
138 for article in filtered {
139 let filename = article.filename(workspace_name);
140 let path = domain_dir.join(&filename);
141 let yaml = self.export(article)?;
142 std::fs::write(&path, yaml).map_err(|e| {
143 ExportError::IoError(format!("Failed to write {}: {}", filename, e))
144 })?;
145 count += 1;
146 }
147
148 Ok(count)
149 }
150}
151
152impl Default for KnowledgeExporter {
153 fn default() -> Self {
154 Self::new()
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161 use crate::models::knowledge::KnowledgeStatus;
162
163 #[test]
164 fn test_export_knowledge_article() {
165 let article = KnowledgeArticle::new(
166 1,
167 "Data Classification Guide",
168 "This guide explains data classification.",
169 "Data classification is essential for governance.",
170 "data-governance@example.com",
171 )
172 .with_status(KnowledgeStatus::Published);
173
174 let exporter = KnowledgeExporter::new();
175 let result = exporter.export_without_validation(&article);
176 assert!(result.is_ok());
177 let yaml = result.unwrap();
178 assert!(yaml.contains("title: Data Classification Guide"));
179 assert!(yaml.contains("status: published"));
180 }
181
182 #[test]
183 fn test_export_knowledge_index() {
184 let index = KnowledgeIndex::new();
185 let exporter = KnowledgeExporter::new();
186 let result = exporter.export_index(&index);
187 assert!(result.is_ok());
188 let yaml = result.unwrap();
189 assert!(yaml.contains("schemaVersion"));
190 assert!(yaml.contains("nextNumber: 1"));
191 }
192}