mf_model/
node_factory.rs

1use std::collections::HashMap;
2
3use serde_json::Value;
4
5use crate::{
6    error::{error_helpers::schema_error, PoolResult},
7    id_generator::IdGenerator,
8    mark::Mark,
9    mark_definition::MarkDefinition,
10    node::Node,
11    node_definition::{NodeDefinition, NodeTree},
12    schema::Schema,
13    types::NodeId,
14};
15
16/// 工厂负责基于 [`Schema`] 生成各类节点,复用 [`NodeType`] 的编译信息。
17#[derive(Clone)]
18pub struct NodeFactory<'schema> {
19    schema: &'schema Schema,
20}
21
22impl<'schema> NodeFactory<'schema> {
23    /// 创建新的工厂实例,保存对 [`Schema`] 的只读引用。
24    pub fn new(schema: &'schema Schema) -> Self {
25        Self { schema }
26    }
27
28    /// 暴露内部引用,便于调用方读取原始 Schema。
29    pub fn schema(&self) -> &'schema Schema {
30        self.schema
31    }
32
33    /// 按类型名称创建单节点。
34    pub fn create_node(
35        &self,
36        type_name: &str,
37        id: Option<NodeId>,
38        attrs: Option<&HashMap<String, Value>>,
39        content: Vec<NodeId>,
40        marks: Option<Vec<Mark>>,
41    ) -> PoolResult<Node> {
42        let node_type = self.schema.nodes.get(type_name).ok_or_else(|| {
43            schema_error(&format!("无法在 schema 中找到节点类型: {type_name}"))
44        })?;
45
46        Ok(Self::instantiate_node(node_type, id, attrs, content, marks))
47    }
48
49    /// 获取节点类型定义引用,便于上层读取配置。
50    pub fn node_definition(
51        &self,
52        type_name: &str,
53    ) -> Option<&NodeDefinition> {
54        self.schema.nodes.get(type_name)
55    }
56
57    /// 按类型名称创建标记。
58    pub fn create_mark(
59        &self,
60        type_name: &str,
61        attrs: Option<&HashMap<String, Value>>,
62    ) -> PoolResult<Mark> {
63        let mark_def = self.schema.marks.get(type_name).ok_or_else(|| {
64            schema_error(&format!("无法在 schema 中找到标记类型: {type_name}"))
65        })?;
66
67        Ok(Self::instantiate_mark(mark_def, attrs))
68    }
69
70    /// 获取标记类型定义引用。
71    pub fn mark_definition(
72        &self,
73        type_name: &str,
74    ) -> Option<&MarkDefinition> {
75        self.schema.marks.get(type_name)
76    }
77
78    /// 以顶级节点为根构建整棵子树。
79    pub fn create_top_node(
80        &self,
81        id: Option<NodeId>,
82        attrs: Option<&HashMap<String, Value>>,
83        content: Vec<Node>,
84        marks: Option<Vec<Mark>>,
85    ) -> PoolResult<NodeTree> {
86        let top_node_type = self
87            .schema
88            .top_node_type
89            .as_ref()
90            .ok_or_else(|| schema_error("未找到顶级节点类型定义"))?;
91
92        self.create_tree_with_type(top_node_type, id, attrs, content, marks)
93    }
94
95    /// 为指定类型构建并填充子树。
96    pub fn create_tree(
97        &self,
98        type_name: &str,
99        id: Option<NodeId>,
100        attrs: Option<&HashMap<String, Value>>,
101        content: Vec<Node>,
102        marks: Option<Vec<Mark>>,
103    ) -> PoolResult<NodeTree> {
104        let node_type = self.schema.nodes.get(type_name).ok_or_else(|| {
105            schema_error(&format!("无法在 schema 中找到节点类型: {type_name}"))
106        })?;
107
108        self.create_tree_with_type(node_type, id, attrs, content, marks)
109    }
110
111    /// 暴露给 [`NodeDefinition`] 的内部构建逻辑。
112    pub(crate) fn create_tree_with_type(
113        &self,
114        node_type: &NodeDefinition,
115        id: Option<NodeId>,
116        attrs: Option<&HashMap<String, Value>>,
117        content: Vec<Node>,
118        marks: Option<Vec<Mark>>,
119    ) -> PoolResult<NodeTree> {
120        let id: NodeId = id.unwrap_or_else(IdGenerator::get_id);
121        let computed_attrs = node_type.compute_attrs(attrs);
122        let computed_marks = node_type.compute_marks(marks);
123
124        let mut filled_nodes: Vec<NodeTree> = Vec::new();
125        let mut final_content_ids: Vec<NodeId> = Vec::new();
126
127        if let Some(content_match) = &node_type.content_match {
128            if let Some(matched) =
129                content_match.match_fragment(&content, self.schema)
130            {
131                if let Some(needed_type_names) =
132                    matched.fill(&content, true, self.schema)
133                {
134                    for type_name in needed_type_names {
135                        if let Some(existing_node) =
136                            content.iter().find(|n| n.r#type == type_name)
137                        {
138                            let attrs_map: HashMap<String, Value> =
139                                existing_node
140                                    .attrs
141                                    .attrs
142                                    .iter()
143                                    .map(|(k, v)| (k.clone(), v.clone()))
144                                    .collect();
145                            let marks_vec: Vec<Mark> =
146                                existing_node.marks.iter().cloned().collect();
147                            let child_type = self
148                                .schema
149                                .nodes
150                                .get(&type_name)
151                                .ok_or_else(|| {
152                                    schema_error(&format!(
153                                        "无法在 schema 中找到节点类型: {type_name}"
154                                    ))
155                                })?;
156
157                            let child_tree = self.create_tree_with_type(
158                                child_type,
159                                Some(existing_node.id.clone()),
160                                Some(&attrs_map),
161                                vec![],
162                                Some(marks_vec),
163                            )?;
164                            let child_id = child_tree.0.id.clone();
165                            final_content_ids.push(child_id);
166                            filled_nodes.push(child_tree);
167                        } else {
168                            let child_type = self
169                                .schema
170                                .nodes
171                                .get(&type_name)
172                                .ok_or_else(|| {
173                                    schema_error(&format!(
174                                        "无法在 schema 中找到节点类型: {type_name}"
175                                    ))
176                                })?;
177
178                            let child_tree = self.create_tree_with_type(
179                                child_type,
180                                None,
181                                None,
182                                vec![],
183                                None,
184                            )?;
185                            let child_id = child_tree.0.id.clone();
186                            final_content_ids.push(child_id);
187                            filled_nodes.push(child_tree);
188                        }
189                    }
190                }
191            }
192        }
193
194        let node = Node::new(
195            &id,
196            node_type.name.clone(),
197            computed_attrs,
198            final_content_ids,
199            computed_marks,
200        );
201
202        Ok(NodeTree(node, filled_nodes))
203    }
204
205    fn instantiate_node(
206        node_type: &NodeDefinition,
207        id: Option<NodeId>,
208        attrs: Option<&HashMap<String, Value>>,
209        content: Vec<NodeId>,
210        marks: Option<Vec<Mark>>,
211    ) -> Node {
212        let id: NodeId = id.unwrap_or_else(IdGenerator::get_id);
213        let attrs = node_type.compute_attrs(attrs);
214        let marks = node_type.compute_marks(marks);
215
216        Node::new(&id, node_type.name.clone(), attrs, content, marks)
217    }
218
219    pub(crate) fn instantiate_mark(
220        mark_def: &MarkDefinition,
221        attrs: Option<&HashMap<String, Value>>,
222    ) -> Mark {
223        Mark { r#type: mark_def.name.clone(), attrs: mark_def.compute_attrs(attrs) }
224    }
225}