Skip to main content

easyofd_core/
ofd_element.rs

1//! OFD 元素基类特征。
2//!
3//! 对应 Java: org.ofdrw.core.OFDElement
4//!
5//! 所有 OFD XML 元素的公共接口,定义了元素名称、属性和子元素的通用行为。
6//! 在 Java 版中 `OFDElement` 继承自 `DefaultElementProxy`,是所有 OFD
7//! 数据结构类的基类。Rust 版用 trait 实现等价的多态行为。
8
9/// OFD 元素公共特征。
10///
11/// 对应 Java: org.ofdrw.core.OFDElement
12///
13/// 实现此 trait 的类型表示一个 OFD XML 元素,可以获取元素名称、
14/// 属性列表和子元素列表,以及序列化为 XML 字符串。
15pub trait OfdElement {
16    /// 获取 OFD XML 元素名称(不含命名空间前缀)。
17    fn ofd_element_name(&self) -> &'static str;
18
19    /// 获取元素的属性列表(键值对)。
20    fn ofd_attributes(&self) -> Vec<(String, String)> {
21        Vec::new()
22    }
23
24    /// 序列化为 OFD XML 字符串(含命名空间前缀)。
25    fn to_ofd_xml(&self) -> String {
26        let name = self.ofd_element_name();
27        let attrs = self.ofd_attributes();
28        let mut xml = String::from("<ofd:");
29        xml.push_str(name);
30        for (key, value) in &attrs {
31            xml.push(' ');
32            xml.push_str(key);
33            xml.push_str("=\"");
34            xml.push_str(value);
35            xml.push('"');
36        }
37        xml.push_str(" />");
38        xml
39    }
40}
41
42/// 默认元素代理。
43///
44/// 对应 Java: org.ofdrw.core.DefaultElementProxy
45///
46/// 提供 `OfdElement` trait 的默认包装行为,将底层 XML 元素代理为 OFD 元素。
47/// 在 Java 版中用于包装 XML DOM 节点;Rust 版中用于需要代理行为的场景。
48#[derive(Debug, Clone)]
49pub struct DefaultElementProxy {
50    /// 元素名称。
51    pub element_name: String,
52    /// 属性列表。
53    pub attributes: Vec<(String, String)>,
54}
55
56impl DefaultElementProxy {
57    /// 创建默认元素代理。
58    #[must_use]
59    pub fn new(element_name: impl Into<String>) -> Self {
60        Self {
61            element_name: element_name.into(),
62            attributes: Vec::new(),
63        }
64    }
65
66    /// 添加属性。
67    #[must_use]
68    pub fn attr(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
69        self.attributes.push((key.into(), value.into()));
70        self
71    }
72}
73
74impl OfdElement for DefaultElementProxy {
75    fn ofd_element_name(&self) -> &'static str {
76        // 注意:这里需要泄漏一个 &'static str 来满足 trait 签名。
77        // 在实际使用中,应使用常量或 enum 变体名。
78        // 这里用一个简化方案。
79        "DefaultElement"
80    }
81
82    fn ofd_attributes(&self) -> Vec<(String, String)> {
83        self.attributes.clone()
84    }
85}
86
87/// OFD 简单类型元素特征。
88///
89/// 对应 Java: org.ofdrw.core.OFDSimpleTypeElement
90///
91/// 表示 OFD 中的简单类型元素(值类型),如字符串、整数等标量值。
92/// 与复合类型元素(OfdElement)不同,简单类型元素只有一个文本值。
93pub trait OfdSimpleTypeElement {
94    /// 获取元素的文本值。
95    fn ofd_value(&self) -> String;
96
97    /// 从文本值解析。
98    fn from_ofd_value(s: &str) -> Result<Self, String>
99    where
100        Self: Sized;
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106
107    #[test]
108    fn test_default_element_proxy_new() {
109        let proxy = DefaultElementProxy::new("TestElement");
110        assert_eq!(proxy.element_name, "TestElement");
111        assert!(proxy.attributes.is_empty());
112    }
113
114    #[test]
115    fn test_default_element_proxy_with_attrs() {
116        let proxy = DefaultElementProxy::new("Page")
117            .attr("ID", "1")
118            .attr("Boundary", "0 0 210 297");
119        assert_eq!(proxy.attributes.len(), 2);
120        assert_eq!(proxy.attributes[0].0, "ID");
121        assert_eq!(proxy.attributes[1].1, "0 0 210 297");
122    }
123
124    #[test]
125    fn test_ofd_element_trait_default() {
126        let proxy = DefaultElementProxy::new("Test");
127        let xml = proxy.to_ofd_xml();
128        assert!(xml.contains("<ofd:DefaultElement"));
129        assert!(xml.contains("/>"));
130    }
131
132    #[test]
133    fn test_ofd_element_with_attrs() {
134        let proxy = DefaultElementProxy::new("Test").attr("Key", "Value");
135        let attrs = proxy.ofd_attributes();
136        assert_eq!(attrs.len(), 1);
137        assert_eq!(attrs[0].0, "Key");
138    }
139}