mf_core/
extension_manager.rs

1use std::sync::Arc;
2use std::time::Instant;
3
4use mf_model::schema::Schema;
5use mf_state::{ops::GlobalResourceManager, plugin::Plugin};
6
7use crate::{
8    helpers::get_schema_by_resolved_extensions::get_schema_by_resolved_extensions,
9    metrics, types::Extensions, ForgeResult, XmlSchemaParser,
10};
11/// 扩展管理器
12pub struct ExtensionManager {
13    plugins: Vec<Arc<Plugin>>,
14    schema: Arc<Schema>,
15    op_fns: Vec<
16        Arc<dyn Fn(&GlobalResourceManager) -> ForgeResult<()> + Send + Sync>,
17    >,
18}
19/// ExtensionManager构建器
20///
21/// 提供灵活的方式来配置和创建ExtensionManager,支持多种扩展来源
22#[derive(Default)]
23pub struct ExtensionManagerBuilder {
24    extensions: Vec<Extensions>,
25    xml_files: Vec<String>,
26    xml_contents: Vec<String>,
27}
28
29impl ExtensionManagerBuilder {
30    /// 创建新的构建器
31    pub fn new() -> Self {
32        Self::default()
33    }
34
35    /// 添加代码定义的扩展
36    ///
37    /// # 参数
38    /// * `extension` - 要添加的扩展
39    ///
40    /// # 示例
41    /// ```rust
42    /// use mf_core::{ExtensionManagerBuilder, types::Extensions, node::Node};
43    /// use mf_model::node_type::NodeSpec;
44    ///
45    /// let node = Node::create("custom_node", NodeSpec::default());
46    /// let manager = ExtensionManagerBuilder::new()
47    ///     .add_extension(Extensions::N(node))
48    ///     .build()?;
49    /// ```
50    pub fn add_extension(mut self, extension: Extensions) -> Self {
51        self.extensions.push(extension);
52        self
53    }
54
55    /// 批量添加代码定义的扩展
56    ///
57    /// # 参数
58    /// * `extensions` - 要添加的扩展列表
59    pub fn add_extensions(mut self, extensions: Vec<Extensions>) -> Self {
60        self.extensions.extend(extensions);
61        self
62    }
63
64    /// 添加XML文件路径
65    ///
66    /// # 参数
67    /// * `xml_file_path` - XML schema文件路径
68    ///
69    /// # 示例
70    /// ```rust
71    /// use mf_core::ExtensionManagerBuilder;
72    ///
73    /// let manager = ExtensionManagerBuilder::new()
74    ///     .add_xml_file("./schemas/base-nodes.xml")
75    ///     .add_xml_file("./schemas/custom-marks.xml")
76    ///     .build()?;
77    /// ```
78    pub fn add_xml_file<P: AsRef<str>>(mut self, xml_file_path: P) -> Self {
79        self.xml_files.push(xml_file_path.as_ref().to_string());
80        self
81    }
82
83    /// 批量添加XML文件路径
84    ///
85    /// # 参数
86    /// * `xml_file_paths` - XML schema文件路径列表
87    pub fn add_xml_files<P: AsRef<str>>(mut self, xml_file_paths: &[P]) -> Self {
88        for path in xml_file_paths {
89            self.xml_files.push(path.as_ref().to_string());
90        }
91        self
92    }
93
94    /// 添加XML内容字符串
95    ///
96    /// # 参数
97    /// * `xml_content` - XML schema内容
98    ///
99    /// # 示例
100    /// ```rust
101    /// use mf_core::ExtensionManagerBuilder;
102    ///
103    /// let xml = r#"
104    /// <?xml version="1.0" encoding="UTF-8"?>
105    /// <schema>
106    ///   <nodes>
107    ///     <node name="custom">
108    ///       <desc>自定义节点</desc>
109    ///     </node>
110    ///   </nodes>
111    /// </schema>
112    /// "#;
113    ///
114    /// let manager = ExtensionManagerBuilder::new()
115    ///     .add_xml_content(xml)
116    ///     .build()?;
117    /// ```
118    pub fn add_xml_content<S: AsRef<str>>(mut self, xml_content: S) -> Self {
119        self.xml_contents.push(xml_content.as_ref().to_string());
120        self
121    }
122
123    /// 批量添加XML内容字符串
124    ///
125    /// # 参数
126    /// * `xml_contents` - XML schema内容列表
127    pub fn add_xml_contents<S: AsRef<str>>(mut self, xml_contents: &[S]) -> Self {
128        for content in xml_contents {
129            self.xml_contents.push(content.as_ref().to_string());
130        }
131        self
132    }
133
134    /// 构建ExtensionManager
135    ///
136    /// # 返回值
137    /// * `ForgeResult<ExtensionManager>` - 构建的ExtensionManager实例或错误
138    pub fn build(self) -> ForgeResult<ExtensionManager> {
139        let start_time = Instant::now();
140        let mut all_extensions = self.extensions;
141
142        // 解析XML文件
143        for xml_file in &self.xml_files {
144            let extensions = XmlSchemaParser::parse_multi_file_to_extensions(xml_file)
145                .map_err(|e| crate::error::error_utils::config_error(
146                    format!("解析XML文件 {} 失败: {}", xml_file, e)
147                ))?;
148            all_extensions.extend(extensions);
149        }
150
151        // 解析XML内容
152        for xml_content in &self.xml_contents {
153            let extensions = XmlSchemaParser::parse_to_extensions(xml_content)
154                .map_err(|e| crate::error::error_utils::config_error(
155                    format!("解析XML内容失败: {}", e)
156                ))?;
157            all_extensions.extend(extensions);
158        }
159
160        metrics::xml_parsing_duration(start_time.elapsed());
161
162        // 创建ExtensionManager
163        ExtensionManager::new(&all_extensions)
164    }
165}
166
167impl ExtensionManager {
168    /// 创建ExtensionManager构建器
169    ///
170    /// # 示例
171    /// ```rust
172    /// use mf_core::ExtensionManager;
173    ///
174    /// let manager = ExtensionManager::builder()
175    ///     .add_xml_file("./schemas/main.xml")
176    ///     .build()?;
177    /// ```
178    pub fn builder() -> ExtensionManagerBuilder {
179        ExtensionManagerBuilder::new()
180    }
181
182    pub fn new(extensions: &Vec<Extensions>) -> ForgeResult<Self> {
183        let start_time = Instant::now();
184        let schema = Arc::new(get_schema_by_resolved_extensions(extensions)?);
185        let mut plugins = vec![];
186        let mut op_fns = vec![];
187        let mut extension_count = 0;
188        let mut plugin_count = 0;
189        for extension in extensions {
190            if let Extensions::E(extension) = extension {
191                extension_count += 1;
192                for plugin in extension.get_plugins() {
193                    plugin_count += 1;
194                    plugins.push(plugin.clone());
195                }
196                for op_fn in extension.get_op_fns() {
197                    op_fns.push(op_fn.clone());
198                }
199            }
200        }
201
202        metrics::extensions_loaded(extension_count);
203        metrics::plugins_loaded(plugin_count);
204        metrics::extension_manager_creation_duration(start_time.elapsed());
205
206        Ok(ExtensionManager { schema, plugins, op_fns })
207    }
208
209    /// 从XML文件创建ExtensionManager(便捷方法)
210    ///
211    /// # 参数
212    /// * `xml_file_path` - XML schema文件路径
213    ///
214    /// # 返回值
215    /// * `ForgeResult<Self>` - 返回ExtensionManager实例或错误
216    ///
217    /// # 示例
218    /// ```rust
219    /// use mf_core::ExtensionManager;
220    ///
221    /// let manager = ExtensionManager::from_xml_file("./schemas/main.xml")?;
222    /// ```
223    pub fn from_xml_file(xml_file_path: &str) -> ForgeResult<Self> {
224        Self::builder()
225            .add_xml_file(xml_file_path)
226            .build()
227    }
228
229    /// 从XML字符串创建ExtensionManager(便捷方法)
230    ///
231    /// # 参数
232    /// * `xml_content` - XML schema内容字符串
233    ///
234    /// # 返回值
235    /// * `ForgeResult<Self>` - 返回ExtensionManager实例或错误
236    ///
237    /// # 示例
238    /// ```rust
239    /// use mf_core::ExtensionManager;
240    ///
241    /// let xml = r#"
242    /// <?xml version="1.0" encoding="UTF-8"?>
243    /// <schema top_node="doc">
244    ///   <nodes>
245    ///     <node name="doc">
246    ///       <content>paragraph+</content>
247    ///     </node>
248    ///   </nodes>
249    /// </schema>
250    /// "#;
251    ///
252    /// let manager = ExtensionManager::from_xml_string(xml)?;
253    /// ```
254    pub fn from_xml_string(xml_content: &str) -> ForgeResult<Self> {
255        Self::builder()
256            .add_xml_content(xml_content)
257            .build()
258    }
259
260    /// 从多个XML文件创建ExtensionManager(便捷方法)
261    ///
262    /// # 参数
263    /// * `xml_file_paths` - XML schema文件路径列表
264    ///
265    /// # 返回值
266    /// * `ForgeResult<Self>` - 返回ExtensionManager实例或错误
267    ///
268    /// # 示例
269    /// ```rust
270    /// use mf_core::ExtensionManager;
271    ///
272    /// let files = vec![
273    ///     "./schemas/base-nodes.xml",
274    ///     "./schemas/formatting-marks.xml",
275    ///     "./schemas/custom-extensions.xml"
276    /// ];
277    ///
278    /// let manager = ExtensionManager::from_xml_files(&files)?;
279    /// ```
280    pub fn from_xml_files(xml_file_paths: &[&str]) -> ForgeResult<Self> {
281        Self::builder()
282            .add_xml_files(xml_file_paths)
283            .build()
284    }
285
286    /// 从Extensions和XML文件混合创建ExtensionManager(便捷方法)
287    ///
288    /// # 参数
289    /// * `extensions` - 已有的Extensions列表
290    /// * `xml_file_paths` - 额外的XML schema文件路径列表
291    ///
292    /// # 返回值
293    /// * `ForgeResult<Self>` - 返回ExtensionManager实例或错误
294    ///
295    /// # 示例
296    /// ```rust
297    /// use mf_core::{ExtensionManager, types::Extensions};
298    ///
299    /// let existing_extensions = vec![/* ... */];
300    /// let xml_files = vec!["./schemas/additional.xml"];
301    ///
302    /// let manager = ExtensionManager::from_mixed_sources(
303    ///     &existing_extensions,
304    ///     &xml_files
305    /// )?;
306    /// ```
307    pub fn from_mixed_sources(
308        extensions: &[Extensions],
309        xml_file_paths: &[&str]
310    ) -> ForgeResult<Self> {
311        Self::builder()
312            .add_extensions(extensions.to_vec())
313            .add_xml_files(xml_file_paths)
314            .build()
315    }
316    pub fn get_op_fns(
317        &self
318    ) -> &Vec<
319        Arc<dyn Fn(&GlobalResourceManager) -> ForgeResult<()> + Send + Sync>,
320    > {
321        &self.op_fns
322    }
323
324    pub fn get_schema(&self) -> Arc<Schema> {
325        self.schema.clone()
326    }
327    pub fn get_plugins(&self) -> &Vec<Arc<Plugin>> {
328        &self.plugins
329    }
330
331    /// 动态添加扩展并重新构建schema
332    ///
333    /// # 参数
334    /// * `new_extensions` - 要添加的新扩展列表
335    ///
336    /// # 返回值
337    /// * `ForgeResult<()>` - 成功或错误
338    ///
339    /// # 示例
340    /// ```rust
341    /// use mf_core::{ExtensionManager, types::Extensions, node::Node};
342    /// use mf_model::node_type::NodeSpec;
343    ///
344    /// let mut manager = ExtensionManager::new(&vec![])?;
345    ///
346    /// let new_node = Node::create("dynamic_node", NodeSpec::default());
347    /// manager.add_extensions(vec![Extensions::N(new_node)])?;
348    /// ```
349    pub fn add_extensions(&mut self, new_extensions: Vec<Extensions>) -> ForgeResult<()> {
350        // 获取当前所有扩展
351        let mut all_extensions = Vec::new();
352
353        // 从当前schema重建扩展列表(这是一个简化的实现)
354        // 在实际应用中,你可能需要保存原始的扩展列表
355        for (name, node_type) in &self.schema.nodes {
356            let node = crate::node::Node::create(name, node_type.spec.clone());
357            all_extensions.push(Extensions::N(node));
358        }
359
360        for (name, mark_type) in &self.schema.marks {
361            let mark = crate::mark::Mark::new(name, mark_type.spec.clone());
362            all_extensions.push(Extensions::M(mark));
363        }
364
365        // 添加新扩展
366        all_extensions.extend(new_extensions);
367
368        // 重新构建ExtensionManager
369        let new_manager = Self::new(&all_extensions)?;
370
371        // 更新当前实例
372        self.schema = new_manager.schema;
373        self.plugins = new_manager.plugins;
374        self.op_fns = new_manager.op_fns;
375
376        Ok(())
377    }
378
379    /// 动态添加XML文件扩展
380    ///
381    /// # 参数
382    /// * `xml_file_path` - XML schema文件路径
383    ///
384    /// # 返回值
385    /// * `ForgeResult<()>` - 成功或错误
386    pub fn add_xml_file(&mut self, xml_file_path: &str) -> ForgeResult<()> {
387        let extensions = XmlSchemaParser::parse_multi_file_to_extensions(xml_file_path)
388            .map_err(|e| crate::error::error_utils::config_error(
389                format!("解析XML文件 {} 失败: {}", xml_file_path, e)
390            ))?;
391
392        self.add_extensions(extensions)
393    }
394
395    /// 动态添加XML内容扩展
396    ///
397    /// # 参数
398    /// * `xml_content` - XML schema内容
399    ///
400    /// # 返回值
401    /// * `ForgeResult<()>` - 成功或错误
402    pub fn add_xml_content(&mut self, xml_content: &str) -> ForgeResult<()> {
403        let extensions = XmlSchemaParser::parse_to_extensions(xml_content)
404            .map_err(|e| crate::error::error_utils::config_error(
405                format!("解析XML内容失败: {}", e)
406            ))?;
407
408        self.add_extensions(extensions)
409    }
410}
411
412#[cfg(test)]
413mod tests {
414    use super::*;
415
416    #[test]
417    fn test_extension_manager_from_xml_string() {
418        let xml = r#"
419        <?xml version="1.0" encoding="UTF-8"?>
420        <schema top_node="doc">
421          <nodes>
422            <node name="doc" group="block">
423              <desc>文档根节点</desc>
424              <content>paragraph+</content>
425            </node>
426            <node name="paragraph" group="block">
427              <desc>段落节点</desc>
428              <content>text*</content>
429              <marks>strong</marks>
430            </node>
431            <node name="text">
432              <desc>文本节点</desc>
433            </node>
434          </nodes>
435          <marks>
436            <mark name="strong" group="formatting">
437              <desc>粗体标记</desc>
438              <spanning>true</spanning>
439            </mark>
440          </marks>
441        </schema>
442        "#;
443
444        let result = ExtensionManager::from_xml_string(xml);
445        assert!(result.is_ok());
446
447        let manager = result.unwrap();
448        let schema = manager.get_schema();
449
450        // 验证schema结构
451        assert_eq!(schema.nodes.len(), 3);
452        assert_eq!(schema.marks.len(), 1);
453        assert!(schema.nodes.contains_key("doc"));
454        assert!(schema.nodes.contains_key("paragraph"));
455        assert!(schema.nodes.contains_key("text"));
456        assert!(schema.marks.contains_key("strong"));
457    }
458
459    #[test]
460    fn test_extension_manager_from_xml_files() {
461        // 创建临时目录和文件进行测试
462        let temp_dir = std::env::temp_dir().join("extension_manager_test");
463        std::fs::create_dir_all(&temp_dir).unwrap();
464
465        // 创建基础节点文件
466        let base_nodes_content = r#"
467        <?xml version="1.0" encoding="UTF-8"?>
468        <schema>
469          <nodes>
470            <node name="doc" group="block">
471              <desc>文档根节点</desc>
472              <content>paragraph+</content>
473            </node>
474            <node name="paragraph" group="block">
475              <desc>段落节点</desc>
476              <content>text*</content>
477            </node>
478            <node name="text">
479              <desc>文本节点</desc>
480            </node>
481          </nodes>
482        </schema>
483        "#;
484
485        let base_nodes_path = temp_dir.join("base-nodes.xml");
486        std::fs::write(&base_nodes_path, base_nodes_content).unwrap();
487
488        // 创建标记文件
489        let marks_content = r#"
490        <?xml version="1.0" encoding="UTF-8"?>
491        <schema>
492          <marks>
493            <mark name="strong" group="formatting">
494              <desc>粗体标记</desc>
495              <spanning>true</spanning>
496            </mark>
497            <mark name="em" group="formatting">
498              <desc>斜体标记</desc>
499              <spanning>true</spanning>
500            </mark>
501          </marks>
502        </schema>
503        "#;
504
505        let marks_path = temp_dir.join("marks.xml");
506        std::fs::write(&marks_path, marks_content).unwrap();
507
508        // 测试从多个文件创建ExtensionManager
509        let files = vec![
510            base_nodes_path.to_str().unwrap(),
511            marks_path.to_str().unwrap(),
512        ];
513
514        let result = ExtensionManager::from_xml_files(&files);
515        assert!(result.is_ok());
516
517        let manager = result.unwrap();
518        let schema = manager.get_schema();
519
520        // 验证合并后的schema
521        assert_eq!(schema.nodes.len(), 3); // doc, paragraph, text
522        assert_eq!(schema.marks.len(), 2); // strong, em
523
524        // 清理临时文件
525        std::fs::remove_dir_all(&temp_dir).unwrap();
526    }
527
528    #[test]
529    fn test_extension_manager_builder_mixed_sources() {
530        use crate::node::Node;
531        use crate::mark::Mark;
532        use mf_model::node_type::NodeSpec;
533        use mf_model::mark_type::MarkSpec;
534
535        // 创建代码定义的扩展
536        let code_node = Node::create("code_node", NodeSpec::default());
537        let code_mark = Mark::new("code_mark", MarkSpec::default());
538
539        let xml_content = r#"
540        <?xml version="1.0" encoding="UTF-8"?>
541        <schema>
542          <nodes>
543            <node name="xml_node" group="block">
544              <desc>XML定义的节点</desc>
545            </node>
546          </nodes>
547          <marks>
548            <mark name="xml_mark" group="formatting">
549              <desc>XML定义的标记</desc>
550            </mark>
551          </marks>
552        </schema>
553        "#;
554
555        // 使用Builder模式混合不同来源的扩展
556        let result = ExtensionManager::builder()
557            .add_extension(Extensions::N(code_node))
558            .add_extension(Extensions::M(code_mark))
559            .add_xml_content(xml_content)
560            .build();
561
562        if let Err(ref e) = result {
563            println!("Error: {:?}", e);
564        }
565        assert!(result.is_ok());
566
567        let manager = result.unwrap();
568        let schema = manager.get_schema();
569
570        // 验证混合后的schema
571        assert_eq!(schema.nodes.len(), 2); // code_node, xml_node
572        assert_eq!(schema.marks.len(), 2); // code_mark, xml_mark
573
574        assert!(schema.nodes.contains_key("code_node"));
575        assert!(schema.nodes.contains_key("xml_node"));
576        assert!(schema.marks.contains_key("code_mark"));
577        assert!(schema.marks.contains_key("xml_mark"));
578    }
579
580    #[test]
581    fn test_dynamic_extension_addition() {
582        use crate::node::Node;
583        use mf_model::node_type::NodeSpec;
584
585        // 创建初始的ExtensionManager
586        let xml_content = r#"
587        <?xml version="1.0" encoding="UTF-8"?>
588        <schema>
589          <nodes>
590            <node name="initial_node">
591              <desc>初始节点</desc>
592            </node>
593          </nodes>
594        </schema>
595        "#;
596
597        let mut manager = ExtensionManager::from_xml_string(xml_content).unwrap();
598
599        // 验证初始状态
600        assert_eq!(manager.get_schema().nodes.len(), 1);
601        assert!(manager.get_schema().nodes.contains_key("initial_node"));
602
603        // 动态添加新的扩展
604        let new_node = Node::create("dynamic_node", NodeSpec::default());
605        let result = manager.add_extensions(vec![Extensions::N(new_node)]);
606        assert!(result.is_ok());
607
608        // 验证添加后的状态
609        assert_eq!(manager.get_schema().nodes.len(), 2);
610        assert!(manager.get_schema().nodes.contains_key("initial_node"));
611        assert!(manager.get_schema().nodes.contains_key("dynamic_node"));
612
613        // 动态添加XML内容
614        let additional_xml = r#"
615        <?xml version="1.0" encoding="UTF-8"?>
616        <schema>
617          <nodes>
618            <node name="xml_dynamic_node">
619              <desc>动态添加的XML节点</desc>
620            </node>
621          </nodes>
622        </schema>
623        "#;
624
625        let result = manager.add_xml_content(additional_xml);
626        assert!(result.is_ok());
627
628        // 验证最终状态
629        assert_eq!(manager.get_schema().nodes.len(), 3);
630        assert!(manager.get_schema().nodes.contains_key("initial_node"));
631        assert!(manager.get_schema().nodes.contains_key("dynamic_node"));
632        assert!(manager.get_schema().nodes.contains_key("xml_dynamic_node"));
633    }
634}