xee_interpreter/context/
static_context_builder.rs1use ahash::HashMap;
2use iri_string::types::IriAbsoluteString;
3use xee_name::Namespaces;
4use xot::xmlname::OwnedName;
5
6use crate::context;
7
8#[derive(Debug, Clone, Default)]
9pub struct StaticContextBuilder<'a> {
10 variable_names: Vec<OwnedName>,
11 namespaces: HashMap<&'a str, &'a str>,
12 default_element_namespace: &'a str,
13 default_function_namespace: &'a str,
14 static_base_uri: Option<IriAbsoluteString>,
15}
16
17impl<'a> StaticContextBuilder<'a> {
18 pub fn variable_names(
25 &mut self,
26 variable_names: impl IntoIterator<Item = OwnedName>,
27 ) -> &mut Self {
28 self.variable_names = variable_names.into_iter().collect();
29 self
30 }
31
32 pub fn namespaces(
41 &mut self,
42 namespaces: impl IntoIterator<Item = (&'a str, &'a str)>,
43 ) -> &mut Self {
44 for (prefix, uri) in namespaces {
45 self.add_namespace(prefix, uri);
46 }
47 self
48 }
49
50 pub fn add_namespace(&mut self, prefix: &'a str, uri: &'a str) -> &mut Self {
52 if prefix.is_empty() {
53 self.default_element_namespace = uri;
54 } else {
55 self.namespaces.insert(prefix, uri);
56 }
57 self
58 }
59
60 pub fn default_element_namespace(&mut self, default_element_namespace: &'a str) -> &mut Self {
62 self.default_element_namespace = default_element_namespace;
63 self
64 }
65
66 pub fn default_function_namespace(&mut self, default_function_namespace: &'a str) -> &mut Self {
68 self.default_function_namespace = default_function_namespace;
69 self
70 }
71
72 pub fn static_base_uri(&mut self, static_base_uri: Option<IriAbsoluteString>) -> &mut Self {
74 self.static_base_uri = static_base_uri;
75 self
76 }
77
78 pub fn build(&self) -> context::StaticContext {
84 let mut namespaces = Namespaces::default_namespaces();
85 for (prefix, uri) in &self.namespaces {
86 namespaces.insert(prefix.to_string(), uri.to_string());
87 }
88 let default_function_namespace = if !self.default_function_namespace.is_empty() {
89 self.default_function_namespace
90 } else {
91 Namespaces::FN_NAMESPACE
92 };
93 let namespaces = xee_name::Namespaces::new(
94 namespaces,
95 self.default_element_namespace.to_string(),
96 default_function_namespace.to_string(),
97 );
98 let variable_names = self.variable_names.clone().into_iter().collect();
99 context::StaticContext::new(namespaces, variable_names, self.static_base_uri.clone())
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use ahash::HashSet;
106
107 use super::*;
108
109 #[test]
110 fn test_variable_names() {
111 let mut builder = StaticContextBuilder::default();
112 let foo = OwnedName::new("foo".to_string(), "".to_string(), "".to_string());
113 let bar = OwnedName::new("bar".to_string(), "".to_string(), "".to_string());
114 builder.variable_names([foo.clone(), bar.clone()]);
115 assert_eq!(builder.variable_names, vec![foo, bar]);
116 }
117
118 #[test]
119 fn test_default_behavior() {
120 let builder = StaticContextBuilder::default();
121 let static_context = builder.build();
122 assert_eq!(static_context.namespaces().default_element_namespace(), "");
123 assert_eq!(
124 static_context.namespaces().default_function_namespace,
125 Namespaces::FN_NAMESPACE
126 );
127 assert_eq!(static_context.variable_names(), &HashSet::default());
128 assert_eq!(
129 static_context.namespaces().by_prefix("xml"),
130 Some("http://www.w3.org/XML/1998/namespace")
131 );
132 }
133}