maven_rs/pom/editor/
build.rs

1use edit_xml::Element;
2
3use crate::{
4    editor::XMLEditorError,
5    editor::utils::{add_or_update_item, get_all_children_of_element},
6    pom::build::Plugin,
7};
8
9use super::PomEditor;
10impl PomEditor {
11    /// Creates a new build editor
12    ///
13    /// If no build element is present, it will create one
14    /// # Note.
15    /// This function will hold a mutable reference to the PomEditor.
16    /// I would recommend using this function within a scope. To prevent borrowing issues.
17    pub fn get_or_create_build_element(&mut self) -> BuildEditor<'_> {
18        BuildEditor::new(self)
19    }
20    /// Checks if the build element is present in the pom file
21    ///
22    /// If the build element is present, it will return Some(BuildEditor) else it will return None
23    pub fn get_build_element_or_none(&mut self) -> Option<BuildEditor<'_>> {
24        if self.has_build() {
25            return Some(BuildEditor::new(self));
26        }
27        None
28    }
29    pub fn has_build(&self) -> bool {
30        let root = self.root();
31        root.find(&self.document, "build").is_some()
32    }
33    pub fn delete_build(&mut self) -> Result<bool, XMLEditorError> {
34        let root = self.root();
35        let element = root.find(&self.document, "build");
36        if let Some(element) = element {
37            element.detach(&mut self.document)?;
38            Ok(true)
39        } else {
40            Ok(false)
41        }
42    }
43}
44/// Allows for editing the build section of a pom file
45#[derive(Debug)]
46pub struct BuildEditor<'a> {
47    parent: &'a mut PomEditor,
48    build_element: Element,
49}
50macro_rules! top_level_getter_setter {
51    (
52        $set:ident, $get:ident, $name:literal
53    ) => {
54        pub fn $set(&mut self, value: &str) {
55            let element = crate::editor::utils::get_or_create_top_level_element(
56                $name,
57                &mut self.parent.document,
58                self.build_element,
59            );
60            element.set_text_content(&mut self.parent.document, value);
61        }
62        pub fn $get(&self) -> Option<String> {
63            let element = self.build_element.find(&self.parent.document, $name);
64            return element.map(|x| x.text_content(&self.parent.document));
65        }
66    };
67}
68impl<'a> BuildEditor<'a> {
69    top_level_getter_setter!(
70        set_source_directory,
71        get_source_directory,
72        "sourceDirectory"
73    );
74    top_level_getter_setter!(set_final_name, get_final_name, "finalName");
75    top_level_getter_setter!(set_directory, get_directory, "directory");
76    top_level_getter_setter!(set_default_goal, get_default_goal, "defaultGoal");
77
78    pub(super) fn new(parent: &'a mut PomEditor) -> Self {
79        let root = parent.root();
80        let build_element = crate::editor::utils::get_or_create_top_level_element(
81            "build",
82            &mut parent.document,
83            root,
84        );
85        Self {
86            parent,
87            build_element,
88        }
89    }
90    /// Gets all the plugins in the build section
91    pub fn get_plugins(&self) -> Result<Vec<Plugin>, XMLEditorError> {
92        let Some(plugins) = self.build_element.find(&self.parent.document, "plugins") else {
93            return Ok(vec![]);
94        };
95        let result = get_all_children_of_element::<Plugin>(&self.parent.document, plugins)?;
96        Ok(result.into_iter().map(|(depend, _)| depend).collect())
97    }
98    /// Adds or updates a plugin in the build section
99    pub fn add_or_update_plugin(
100        &mut self,
101        plugin: Plugin,
102    ) -> Result<Option<Plugin>, XMLEditorError> {
103        let plugins = self.build_element.find(&self.parent.document, "plugins");
104        add_or_update_item(
105            &mut self.parent.document,
106            plugins,
107            self.build_element,
108            plugin,
109        )
110    }
111}
112
113#[cfg(test)]
114mod tests {
115    use crate::{
116        pom::editor::{PomEditor, build::Plugin},
117        types::Property,
118    };
119
120    #[test]
121    pub fn test_plugins() -> anyhow::Result<()> {
122        let mut editor = PomEditor::new_with_group_and_artifact("dev.wyatt-herkamp", "test");
123        {
124            let mut build_editor = editor.get_or_create_build_element();
125            build_editor.set_source_directory("src/main/java");
126            build_editor.set_final_name("test");
127            let plugin = Plugin {
128                group_id: Some("org.apache.maven.plugins".to_string()),
129                artifact_id: "maven-compiler-plugin".to_string(),
130                version: Some(Property::Literal("3.8.1".to_string())),
131            };
132            build_editor.add_or_update_plugin(plugin.clone())?;
133            let plugins = build_editor.get_plugins()?;
134            assert_eq!(plugins.len(), 1);
135            assert_eq!(plugins[0], plugin);
136        }
137        let value = editor.write_to_str()?;
138        println!("{}", value);
139
140        Ok(())
141    }
142
143    #[test]
144    pub fn test_create_and_delete() -> anyhow::Result<()> {
145        let mut editor = PomEditor::new_with_group_and_artifact("dev.wyatt-herkamp", "test");
146
147        assert!(editor.get_build_element_or_none().is_none());
148
149        assert!(!editor.has_build());
150
151        assert!(!editor.delete_build()?);
152
153        {
154            let mut build_editor = editor.get_or_create_build_element();
155            build_editor.set_source_directory("src/main/java");
156            build_editor.set_final_name("test");
157            assert_eq!(
158                build_editor.get_source_directory(),
159                Some("src/main/java".to_string())
160            );
161            assert_eq!(build_editor.get_final_name(), Some("test".to_string()));
162
163            assert!(build_editor.get_plugins()?.is_empty());
164        }
165
166        let value = editor.write_to_str()?;
167
168        let mut editor = PomEditor::load_from_str(&value)?;
169
170        assert!(editor.has_build());
171        {
172            let build_editor = editor.get_build_element_or_none();
173
174            assert!(build_editor.is_some());
175        }
176        editor.delete_build()?;
177
178        assert!(!editor.has_build());
179
180        Ok(())
181    }
182}