lewp/submodule/
mod.rs

1//! Traits and data structures for modules that have submodules.
2use {
3    crate::{
4        fh::{ComponentInformation, ComponentType, Level},
5        module::{Module, ModulePtr, Modules, RuntimeInformation},
6        LewpError,
7        LewpErrorKind,
8    },
9    lewp_html::Nodes,
10    std::rc::Rc,
11};
12
13/// Enables management of submodules.
14pub trait SubModule: Module {
15    /// Returns a reference to the submodules.
16    fn submodules(&self) -> &Modules;
17
18    /// Returns a mutable reference to the submodules.
19    fn submodules_mut(&mut self) -> &mut Modules;
20
21    /// Appends the given module as a submodule.
22    fn append_module(&mut self, module: ModulePtr) -> Result<(), LewpError> {
23        if self.id() == module.borrow().id() {
24            return Err(LewpError {
25                kind: LewpErrorKind::LoopDetection,
26                message: format!(
27                    "Circular reference found in module with id '{}'.",
28                    self.id()
29                ),
30                source_component: self.component_information(),
31            });
32        }
33        self.submodules_mut().push(module);
34        Ok(())
35    }
36
37    /// Renders all submodules to the parent view.
38    fn render_submodules(&self, parent_module_view: &mut Nodes) {
39        for module in self.submodules() {
40            parent_module_view.append(&mut module.borrow().render());
41        }
42    }
43
44    /// Renders the given submodule to the parent view.
45    ///
46    /// Parameters:
47    ///
48    /// **idx**: The index of the module in [Self::submodules].
49    fn render_submodule(
50        &self,
51        idx: usize,
52        parent_module_view: &mut Nodes,
53    ) -> Result<(), LewpError> {
54        let module = match self.submodules().get(idx) {
55            Some(m) => m.borrow(),
56            None => {
57                return Err(LewpError {
58                    kind: LewpErrorKind::Render,
59                    message: format!(
60                        "Could not find module with index {}.",
61                        idx
62                    ),
63                    source_component: self.component_information(),
64                });
65            }
66        };
67        parent_module_view.append(&mut module.render());
68        Ok(())
69    }
70
71    /// Renders the first submodule with the given [id](crate::module::Module::id).
72    ///
73    /// Parameters:
74    ///
75    /// **id**: The unique identifier of the module.
76    fn render_submodule_id(
77        &self,
78        id: &str,
79        parent_module_view: &mut Nodes,
80    ) -> Result<(), LewpError> {
81        for module in self.submodules() {
82            let module = module.borrow();
83            if module.id() != id {
84                continue;
85            }
86            parent_module_view.append(&mut module.render());
87            return Ok(());
88        }
89        Err(LewpError {
90            kind: LewpErrorKind::Render,
91            message:
92                "Module could not be found in the submodules during rendering."
93                    .to_string(),
94            source_component: self.component_information(),
95        })
96    }
97
98    /// Renders all submodules with the given [id](crate::module::Module::id).
99    ///
100    /// Parameters:
101    ///
102    /// **id**: The unique identifier of the modules to be rendered.
103    fn render_submodule_id_all(
104        &self,
105        id: &str,
106        parent_module_view: &mut Nodes,
107    ) -> Result<(), LewpError> {
108        for module in self.submodules() {
109            let module = module.borrow();
110            if module.id() != id {
111                continue;
112            }
113            parent_module_view.append(&mut module.render());
114        }
115        Ok(())
116    }
117
118    /// Runs all submodules in order as they are returned in [Self::submodules].
119    fn run_submodules(
120        &mut self,
121        runtime_information: Rc<RuntimeInformation>,
122    ) -> Result<(), LewpError> {
123        for module in self.submodules() {
124            let mut module = module.borrow_mut();
125            module.run(runtime_information.clone())?;
126            runtime_information.increase_execution_count(module.id());
127        }
128        Ok(())
129    }
130
131    /// Runs the given submodule.
132    ///
133    /// Parameters:
134    ///
135    /// **idx**: The index of the module in [Self::submodules].
136    fn run_submodule(&mut self, idx: usize) -> Result<(), LewpError> {
137        let submodules = self.submodules();
138        let mut module = match submodules.get(idx) {
139            Some(m) => m.borrow_mut(),
140            None => {
141                return Err(LewpError {
142                    kind: LewpErrorKind::Runtime,
143                    message: format!(
144                        "Could not run submodule with index {}",
145                        idx
146                    ),
147                    source_component: self.component_information(),
148                });
149            }
150        };
151        module.run(Rc::new(RuntimeInformation::new()))?;
152        Ok(())
153    }
154
155    /// Runs the first submodule with the given [id](crate::module::Module::id).
156    ///
157    /// Parameters:
158    ///
159    /// **id**: The unique identifier of the module.
160    fn run_submodule_id(&mut self, id: &str) -> Result<(), LewpError> {
161        for module in self.submodules() {
162            let mut module = module.borrow_mut();
163            if module.id() != id {
164                continue;
165            }
166            module.run(Rc::new(RuntimeInformation::new()))?;
167            return Ok(());
168        }
169        Err(LewpError {
170            kind: LewpErrorKind::ModuleNotFound,
171            message: "Could not find module in submodules register."
172                .to_string(),
173            source_component: self.component_information(),
174        })
175    }
176
177    /// Runs all submodules with the given [id](crate::module::Module::id).
178    ///
179    /// Parameters:
180    ///
181    /// **id**: The unique identifier of the modules to be run.
182    fn run_submodule_id_all(&mut self, id: &str) -> Result<(), LewpError> {
183        for module in self.submodules() {
184            let mut module = module.borrow_mut();
185            if module.id() != id {
186                continue;
187            }
188            module.run(Rc::new(RuntimeInformation::new()))?;
189        }
190        Ok(())
191    }
192
193    /// Returns the meta information for this submodule.
194    fn component_information(&self) -> Rc<ComponentInformation> {
195        Rc::new(ComponentInformation {
196            id: self.id().to_string(),
197            level: Level::Module,
198            kind: ComponentType::Module,
199        })
200    }
201}