1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.maven.cling.invoker.mvnup.goals;
20
21 import eu.maveniverse.domtrip.Document;
22 import eu.maveniverse.domtrip.Editor;
23 import eu.maveniverse.domtrip.Element;
24 import eu.maveniverse.domtrip.maven.PomEditor;
25
26 import static eu.maveniverse.domtrip.maven.MavenPomElements.Elements.ARTIFACT_ID;
27 import static eu.maveniverse.domtrip.maven.MavenPomElements.Elements.DEPENDENCY;
28 import static eu.maveniverse.domtrip.maven.MavenPomElements.Elements.GROUP_ID;
29 import static eu.maveniverse.domtrip.maven.MavenPomElements.Elements.PLUGIN;
30 import static eu.maveniverse.domtrip.maven.MavenPomElements.Elements.VERSION;
31
32 /**
33 * Utility class for XML operations on Maven POM files.
34 *
35 * <p>This class provides convenience methods that delegate to:
36 * <ul>
37 * <li>{@link eu.maveniverse.domtrip.maven.PomEditor} - DomTrip's PomEditor</li>
38 * <li>{@link eu.maveniverse.domtrip.Element} - DomTrip's Element API</li>
39 * </ul>
40 *
41 * <p>These methods are kept for convenience and backward compatibility.
42 * For more advanced operations, consider using ExtendedPomEditor or DomTrip directly.
43 *
44 * <h2>Using DomTrip Directly</h2>
45 * <p>Many operations can be performed directly using DomTrip's Element API:
46 * <pre>{@code
47 * // Find child element
48 * Element child = parent.child("version").orElse(null);
49 *
50 * // Check if child exists
51 * boolean hasVersion = parent.child("version").isPresent();
52 *
53 * // Get child text content
54 * String version = parent.child("version")
55 * .map(Element::textContent)
56 * .orElse(null);
57 *
58 * // Get trimmed text content
59 * String trimmedVersion = parent.child("version")
60 * .map(Element::textContentTrimmed)
61 * .orElse(null);
62 *
63 * // Set text content (fluent API)
64 * element.textContent("4.0.0");
65 * }</pre>
66 *
67 * <h2>When to Use DomUtils</h2>
68 * <p>Use DomUtils methods when you need:
69 * <ul>
70 * <li>Maven-specific element ordering (insertNewElement, insertContentElement)</li>
71 * <li>High-level helpers (addGAVElements, createDependency, createPlugin)</li>
72 * <li>Null-safe operations (updateElementContent, removeElement)</li>
73 * <li>Update-or-create patterns (updateOrCreateChildElement)</li>
74 * </ul>
75 *
76 * @see eu.maveniverse.domtrip.Element
77 * @see eu.maveniverse.domtrip.Editor
78 * @see eu.maveniverse.domtrip.maven.PomEditor
79 */
80 public class DomUtils {
81
82 private DomUtils() {
83 // Utility class
84 }
85
86 /**
87 * Inserts a new child element to the given parent element with proper Maven POM ordering.
88 *
89 * @param name the name of the new element
90 * @param parent the parent element
91 * @return the new element
92 *
93 */
94 public static Element insertNewElement(String name, Element parent) {
95 PomEditor editor = new PomEditor(parent.document());
96 return editor.insertMavenElement(parent, name);
97 }
98
99 /**
100 * Inserts a new content element with the given name and text content.
101 *
102 * @param parent the parent element
103 * @param name the name of the new element
104 * @param content the text content
105 * @return the new element
106 *
107 */
108 public static Element insertContentElement(Element parent, String name, String content) {
109 PomEditor editor = new PomEditor(parent.document());
110 return editor.insertMavenElement(parent, name, content);
111 }
112
113 /**
114 * Finds a child element by name under the specified parent.
115 *
116 * @param parent the parent element
117 * @param name the child element name to find
118 * @return the child element if found, null otherwise
119 *
120 */
121 public static Element findChildElement(Element parent, String name) {
122 return parent.child(name).orElse(null);
123 }
124
125 /**
126 * Serializes a domtrip Document to XML string with preserved formatting.
127 *
128 * @param document the domtrip Document
129 * @return the XML string with preserved formatting
130 *
131 */
132 public static String toXml(Document document) {
133 Editor editor = new Editor(document);
134 return editor.toXml();
135 }
136
137 /**
138 * Removes an element from its parent.
139 *
140 * @param element the element to remove
141 *
142 */
143 public static void removeElement(Element element) {
144 Editor editor = new Editor(element.document());
145 editor.removeElement(element);
146 }
147
148 /**
149 * Convenience method to add GAV (groupId, artifactId, version) elements to a parent.
150 *
151 * @param parent the parent element (e.g., dependency or plugin)
152 * @param groupId the groupId value
153 * @param artifactId the artifactId value
154 * @param version the version value (can be null to skip)
155 *
156 */
157 public static void addGAVElements(Element parent, String groupId, String artifactId, String version) {
158 insertContentElement(parent, GROUP_ID, groupId);
159 insertContentElement(parent, ARTIFACT_ID, artifactId);
160 if (version != null && !version.isEmpty()) {
161 insertContentElement(parent, VERSION, version);
162 }
163 }
164
165 /**
166 * Convenience method to create a dependency element with GAV.
167 *
168 * @param dependenciesElement the dependencies parent element
169 * @param groupId the groupId value
170 * @param artifactId the artifactId value
171 * @param version the version value (can be null)
172 * @return the created dependency element
173 *
174 */
175 public static Element createDependency(
176 Element dependenciesElement, String groupId, String artifactId, String version) {
177 Element dependency = insertNewElement(DEPENDENCY, dependenciesElement);
178 addGAVElements(dependency, groupId, artifactId, version);
179 return dependency;
180 }
181
182 /**
183 * Convenience method to create a plugin element with GAV.
184 *
185 * @param pluginsElement the plugins parent element
186 * @param groupId the groupId value
187 * @param artifactId the artifactId value
188 * @param version the version value (can be null)
189 * @return the created plugin element
190 *
191 */
192 public static Element createPlugin(Element pluginsElement, String groupId, String artifactId, String version) {
193 Element plugin = insertNewElement(PLUGIN, pluginsElement);
194 addGAVElements(plugin, groupId, artifactId, version);
195 return plugin;
196 }
197
198 /**
199 * Updates or creates a child element with the given content.
200 *
201 * @param parent the parent element
202 * @param childName the child element name
203 * @param content the content to set
204 * @return the updated or created element
205 *
206 */
207 public static Element updateOrCreateChildElement(Element parent, String childName, String content) {
208 PomEditor editor = new PomEditor(parent.document());
209 return editor.updateOrCreateChildElement(parent, childName, content);
210 }
211 }