mf_model/
node_definition.rs

1use super::attrs::Attrs;
2use super::content::ContentMatch;
3use super::mark::Mark;
4use super::mark_definition::MarkDefinition;
5use super::node::Node;
6use super::schema::{compute_attrs, Attribute, AttributeSpec, Schema};
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9use std::collections::HashMap;
10use std::fmt::{self, Debug};
11
12#[derive(Clone, Debug, Serialize, Deserialize)]
13pub struct NodeTree(pub Node, pub Vec<NodeTree>);
14
15impl NodeTree {
16    pub fn into_parts(self) -> (Node, Vec<NodeTree>) {
17        match self {
18            NodeTree(node, children) => (node, children),
19        }
20    }
21    pub fn from(
22        node: Node,
23        childs: Vec<Node>,
24    ) -> Self {
25        NodeTree(
26            node,
27            childs.into_iter().map(|n| NodeTree(n, vec![])).collect(),
28        )
29    }
30}
31/// 用于描述节点类型的行为规则和属性约束,通过[Schema](super::schema::Schema)进行统一管理
32#[derive(Clone, PartialEq, Eq)]
33pub struct NodeDefinition {
34    /// 节点类型的唯一标识符(例如:"dw", "dxgc")
35    pub name: String,
36    /// 节点类型的详细配置规范
37    pub spec: NodeSpec,
38    /// 节点类型的描述信息
39    pub desc: String,
40    /// 节点所属的逻辑分组
41    pub groups: Vec<String>,
42    /// 节点支持的属性集合(属性名 -> 属性定义)
43    pub attrs: HashMap<String, Attribute>,
44    /// 节点属性的默认值集合
45    pub default_attrs: HashMap<String, Value>,
46    /// 内容匹配规则,定义允许的子节点结构
47    pub content_match: Option<ContentMatch>,
48    /// 允许附加的Mark类型集合
49    pub mark_set: Option<Vec<MarkDefinition>>,
50}
51impl Debug for NodeDefinition {
52    fn fmt(
53        &self,
54        f: &mut fmt::Formatter<'_>,
55    ) -> fmt::Result {
56        f.debug_struct("NodeType")
57            .field("name", &self.name)
58            .field("spec", &self.spec)
59            .field("desc", &self.desc)
60            .field("groups", &self.groups)
61            .field("attrs", &self.attrs)
62            .field("default_attrs", &self.default_attrs)
63            .field("mark_set", &self.mark_set)
64            .finish()
65    }
66}
67
68impl NodeDefinition {
69    /// 将原始节点规范编译为可用的节点类型集合
70    ///
71    /// # 参数
72    /// - `nodes`: 节点名称到[NodeSpec]的映射
73    ///
74    /// # 返回值
75    /// 返回[HashMap]<String, [NodeType]> 类型节点集合
76    pub fn compile(
77        nodes: HashMap<String, NodeSpec>
78    ) -> HashMap<String, NodeDefinition> {
79        let mut result = HashMap::new();
80
81        // First create all node types without content_match
82        for (name, spec) in &nodes {
83            result.insert(
84                name.clone(),
85                NodeDefinition::new(name.clone(), spec.clone()),
86            );
87        }
88
89        // Then set up content_match for each node type
90        let result_clone = result.clone();
91        for (_, node_type) in result.iter_mut() {
92            if let Some(content) = &node_type.spec.content {
93                node_type.content_match =
94                    Some(ContentMatch::parse(content.clone(), &result_clone));
95            }
96        }
97
98        result
99    }
100    /// 创建新的节点类型实例
101    ///
102    /// # 参数
103    /// - `name`: 节点类型名称  
104    /// - `spec`: 节点规范定义  
105    ///
106    /// # 注意
107    /// 自动从spec中推导默认属性和内容匹配规则
108    pub fn new(
109        name: String,
110        spec: NodeSpec,
111    ) -> Self {
112        let attrs = spec.attrs.as_ref().map_or_else(HashMap::new, |attrs| {
113            attrs
114                .iter()
115                .map(|(name, spec)| {
116                    (name.clone(), Attribute::new(spec.clone()))
117                })
118                .collect()
119        });
120
121        let default_attrs = attrs
122            .iter()
123            .filter_map(|(name, attr)| {
124                match (&attr.has_default, &attr.default) {
125                    (true, Some(v)) => Some((name.clone(), v.clone())),
126                    _ => None,
127                }
128            })
129            .collect();
130
131        NodeDefinition {
132            name,
133            spec,
134            desc: "".to_string(),
135            groups: vec![],
136            attrs,
137            default_attrs,
138            content_match: None,
139            mark_set: None,
140        }
141    }
142    /// 验证节点内容是否符合类型约束
143    ///
144    /// # 参数
145    /// - `content`: 子节点切片  
146    /// - `schema`: 当前使用的文档模式  
147    ///
148    /// # 返回值
149    /// 返回`true`表示内容合法,`false`表示不合法
150    pub fn check_content(
151        &self,
152        content: &[Node],
153        schema: &Schema,
154    ) -> bool {
155        if let Some(content_match) = &self.content_match {
156            if let Some(result) = content_match.match_fragment(content, schema)
157            {
158                if !result.valid_end {
159                    return false;
160                }
161            }
162        }
163        true
164    }
165    /// 验证节点属性是否符合规范
166    ///
167    /// # 参数
168    /// - `values`: 待验证的属性集合  
169    ///
170    /// # Panics
171    /// 当遇到以下情况会panic:  
172    /// - 包含未定义的属性  
173    /// - 缺少必须的属性
174    pub fn check_attrs(
175        &self,
176        values: &Attrs,
177    ) {
178        for (key, _value) in values.attrs.iter() {
179            if !self.attrs.contains_key(key) {
180                panic!("节点 {} 属性 {}没有定义", self.name, key);
181            }
182        }
183        for (key, value) in &self.attrs {
184            if value.is_required() && !&values.contains_key(key) {
185                panic!("节点 {} 属性 {} 没有值,这个属性必填", self.name, key);
186            }
187        }
188    }
189
190    /// 检查节点是否包含必须的属性
191    pub fn has_required_attrs(&self) -> bool {
192        self.attrs.values().any(|attr: &Attribute| attr.is_required())
193    }
194
195    pub(crate) fn compute_marks(
196        &self,
197        marks: Option<Vec<Mark>>,
198    ) -> Vec<Mark> {
199        match (&self.mark_set, marks) {
200            (Some(def), Some(marks)) => def
201                .iter()
202                .filter_map(|mark_type| {
203                    marks.iter().find(|m| m.r#type == mark_type.name).cloned()
204                })
205                .collect(),
206            (None, Some(marks)) => marks,
207            _ => vec![],
208        }
209    }
210
211    pub(crate) fn compute_attrs(
212        &self,
213        attrs: Option<&HashMap<String, Value>>,
214    ) -> Attrs {
215        match attrs {
216            Some(attr) => compute_attrs(&self.attrs, Some(attr)),
217            None => compute_attrs(&self.attrs, Some(&self.default_attrs)),
218        }
219    }
220}
221
222/// 定义节点类型的约束规范
223///
224/// 用于配置节点类型的元数据和行为规则,通过[NodeType::compile]转换为可用类型
225#[derive(Clone, PartialEq, Debug, Eq, Default)]
226pub struct NodeSpec {
227    /// 内容约束表达式(例如:"*")
228    pub content: Option<String>,
229    // 允许附加的Mark类型表达式(例如:"color")
230    pub marks: Option<String>,
231    /// 所属的逻辑分组
232    pub group: Option<String>,
233    /// 类型描述信息
234    pub desc: Option<String>,
235    /// 属性规范定义(属性名 -> 属性规范)
236    pub attrs: Option<HashMap<String, AttributeSpec>>,
237}