1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.api.xml;
20
21 import java.io.IOException;
22 import java.io.Serializable;
23 import java.io.StringWriter;
24 import java.util.List;
25 import java.util.ListIterator;
26 import java.util.Map;
27 import java.util.Objects;
28 import java.util.function.Function;
29
30 import org.apache.maven.api.annotations.Experimental;
31 import org.apache.maven.api.annotations.Immutable;
32 import org.apache.maven.api.annotations.Nonnull;
33 import org.apache.maven.api.annotations.Nullable;
34 import org.apache.maven.api.annotations.ThreadSafe;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 @Experimental
53 @ThreadSafe
54 @Immutable
55 public interface XmlNode {
56
57 @Deprecated(since = "4.0.0", forRemoval = true)
58 String CHILDREN_COMBINATION_MODE_ATTRIBUTE = XmlService.CHILDREN_COMBINATION_MODE_ATTRIBUTE;
59
60 @Deprecated(since = "4.0.0", forRemoval = true)
61 String CHILDREN_COMBINATION_MERGE = XmlService.CHILDREN_COMBINATION_MERGE;
62
63 @Deprecated(since = "4.0.0", forRemoval = true)
64 String CHILDREN_COMBINATION_APPEND = XmlService.CHILDREN_COMBINATION_APPEND;
65
66
67
68
69
70
71 @Deprecated(since = "4.0.0", forRemoval = true)
72 String DEFAULT_CHILDREN_COMBINATION_MODE = XmlService.DEFAULT_CHILDREN_COMBINATION_MODE;
73
74 @Deprecated(since = "4.0.0", forRemoval = true)
75 String SELF_COMBINATION_MODE_ATTRIBUTE = XmlService.SELF_COMBINATION_MODE_ATTRIBUTE;
76
77 @Deprecated(since = "4.0.0", forRemoval = true)
78 String SELF_COMBINATION_OVERRIDE = XmlService.SELF_COMBINATION_OVERRIDE;
79
80 @Deprecated(since = "4.0.0", forRemoval = true)
81 String SELF_COMBINATION_MERGE = XmlService.SELF_COMBINATION_MERGE;
82
83 @Deprecated(since = "4.0.0", forRemoval = true)
84 String SELF_COMBINATION_REMOVE = XmlService.SELF_COMBINATION_REMOVE;
85
86
87
88
89 @Deprecated(since = "4.0.0", forRemoval = true)
90 String ID_COMBINATION_MODE_ATTRIBUTE = XmlService.ID_COMBINATION_MODE_ATTRIBUTE;
91
92
93
94
95
96 @Deprecated(since = "4.0.0", forRemoval = true)
97 String KEYS_COMBINATION_MODE_ATTRIBUTE = XmlService.KEYS_COMBINATION_MODE_ATTRIBUTE;
98
99
100
101
102
103
104
105 @Deprecated(since = "4.0.0", forRemoval = true)
106 String DEFAULT_SELF_COMBINATION_MODE = XmlService.DEFAULT_SELF_COMBINATION_MODE;
107
108
109
110
111
112
113 @Nonnull
114 String name();
115
116
117
118
119
120
121 @Nonnull
122 String namespaceUri();
123
124
125
126
127
128
129 @Nonnull
130 String prefix();
131
132
133
134
135
136
137 @Nullable
138 String value();
139
140
141
142
143
144
145 @Nonnull
146 Map<String, String> attributes();
147
148
149
150
151
152
153
154
155 @Nullable
156 String attribute(@Nonnull String name);
157
158
159
160
161
162
163 @Nonnull
164 List<XmlNode> children();
165
166
167
168
169
170
171
172 @Nullable
173 XmlNode child(String name);
174
175
176
177
178
179
180
181 @Nullable
182 Object inputLocation();
183
184
185 @Deprecated(since = "4.0.0", forRemoval = true)
186 @Nonnull
187 default String getName() {
188 return name();
189 }
190
191 @Deprecated(since = "4.0.0", forRemoval = true)
192 @Nonnull
193 default String getNamespaceUri() {
194 return namespaceUri();
195 }
196
197 @Deprecated(since = "4.0.0", forRemoval = true)
198 @Nonnull
199 default String getPrefix() {
200 return prefix();
201 }
202
203 @Deprecated(since = "4.0.0", forRemoval = true)
204 @Nullable
205 default String getValue() {
206 return value();
207 }
208
209 @Deprecated(since = "4.0.0", forRemoval = true)
210 @Nonnull
211 default Map<String, String> getAttributes() {
212 return attributes();
213 }
214
215 @Deprecated(since = "4.0.0", forRemoval = true)
216 @Nullable
217 default String getAttribute(@Nonnull String name) {
218 return attribute(name);
219 }
220
221 @Deprecated(since = "4.0.0", forRemoval = true)
222 @Nonnull
223 default List<XmlNode> getChildren() {
224 return children();
225 }
226
227 @Deprecated(since = "4.0.0", forRemoval = true)
228 @Nullable
229 default XmlNode getChild(String name) {
230 return child(name);
231 }
232
233 @Deprecated(since = "4.0.0", forRemoval = true)
234 @Nullable
235 default Object getInputLocation() {
236 return inputLocation();
237 }
238
239
240
241
242 @Deprecated(since = "4.0.0", forRemoval = true)
243 default XmlNode merge(@Nullable XmlNode source) {
244 return XmlService.merge(this, source);
245 }
246
247
248
249
250 @Deprecated(since = "4.0.0", forRemoval = true)
251 default XmlNode merge(@Nullable XmlNode source, @Nullable Boolean childMergeOverride) {
252 return XmlService.merge(this, source, childMergeOverride);
253 }
254
255
256
257
258
259
260
261
262
263
264
265
266 @Deprecated(since = "4.0.0", forRemoval = true)
267 @Nullable
268 static XmlNode merge(@Nullable XmlNode dominant, @Nullable XmlNode recessive) {
269 return XmlService.merge(dominant, recessive, null);
270 }
271
272 @Nullable
273 static XmlNode merge(
274 @Nullable XmlNode dominant, @Nullable XmlNode recessive, @Nullable Boolean childMergeOverride) {
275 return XmlService.merge(dominant, recessive, childMergeOverride);
276 }
277
278
279
280
281
282
283
284
285 static XmlNode newInstance(String name) {
286 return newBuilder().name(name).build();
287 }
288
289
290
291
292
293
294
295
296
297 static XmlNode newInstance(String name, String value) {
298 return newBuilder().name(name).value(value).build();
299 }
300
301
302
303
304
305
306
307
308
309 static XmlNode newInstance(String name, List<XmlNode> children) {
310 return newBuilder().name(name).children(children).build();
311 }
312
313
314
315
316
317
318
319
320
321
322
323
324 static XmlNode newInstance(
325 String name, String value, Map<String, String> attrs, List<XmlNode> children, Object location) {
326 return newBuilder()
327 .name(name)
328 .value(value)
329 .attributes(attrs)
330 .children(children)
331 .inputLocation(location)
332 .build();
333 }
334
335
336
337
338
339
340 static Builder newBuilder() {
341 return new Builder();
342 }
343
344
345
346
347
348
349
350
351 class Builder {
352 private String name;
353 private String value;
354 private String namespaceUri;
355 private String prefix;
356 private Map<String, String> attributes;
357 private List<XmlNode> children;
358 private Object inputLocation;
359
360
361
362
363
364
365
366
367
368
369 public Builder name(String name) {
370 this.name = name;
371 return this;
372 }
373
374
375
376
377
378
379
380 public Builder value(String value) {
381 this.value = value;
382 return this;
383 }
384
385
386
387
388
389
390
391 public Builder namespaceUri(String namespaceUri) {
392 this.namespaceUri = namespaceUri;
393 return this;
394 }
395
396
397
398
399
400
401
402 public Builder prefix(String prefix) {
403 this.prefix = prefix;
404 return this;
405 }
406
407
408
409
410
411
412
413
414
415 public Builder attributes(Map<String, String> attributes) {
416 this.attributes = attributes;
417 return this;
418 }
419
420
421
422
423
424
425
426
427
428 public Builder children(List<XmlNode> children) {
429 this.children = children;
430 return this;
431 }
432
433
434
435
436
437
438
439
440
441 public Builder inputLocation(Object inputLocation) {
442 this.inputLocation = inputLocation;
443 return this;
444 }
445
446
447
448
449
450
451
452 public XmlNode build() {
453 return new Impl(prefix, namespaceUri, name, value, attributes, children, inputLocation);
454 }
455
456 private record Impl(
457 String prefix,
458 String namespaceUri,
459 @Nonnull String name,
460 String value,
461 @Nonnull Map<String, String> attributes,
462 @Nonnull List<XmlNode> children,
463 Object inputLocation)
464 implements XmlNode, Serializable {
465
466 private Impl {
467
468 prefix = prefix == null ? "" : prefix;
469 namespaceUri = namespaceUri == null ? "" : namespaceUri;
470 name = Objects.requireNonNull(name);
471 attributes = ImmutableCollections.copy(attributes);
472 children = ImmutableCollections.copy(children);
473 }
474
475 @Override
476 public String attribute(@Nonnull String name) {
477 return attributes.get(name);
478 }
479
480 @Override
481 public XmlNode child(String name) {
482 if (name != null) {
483 ListIterator<XmlNode> it = children.listIterator(children.size());
484 while (it.hasPrevious()) {
485 XmlNode child = it.previous();
486 if (name.equals(child.name())) {
487 return child;
488 }
489 }
490 }
491 return null;
492 }
493
494 @Override
495 public boolean equals(Object o) {
496 if (this == o) {
497 return true;
498 }
499 if (o == null || getClass() != o.getClass()) {
500 return false;
501 }
502 Impl that = (Impl) o;
503 return Objects.equals(this.name, that.name)
504 && Objects.equals(this.value, that.value)
505 && Objects.equals(this.attributes, that.attributes)
506 && Objects.equals(this.children, that.children);
507 }
508
509 @Override
510 public int hashCode() {
511 return Objects.hash(name, value, attributes, children);
512 }
513
514 @Override
515 public String toString() {
516 try {
517 StringWriter writer = new StringWriter();
518 XmlService.write(this, writer);
519 return writer.toString();
520 } catch (IOException e) {
521 return toStringObject();
522 }
523 }
524
525 private String toStringObject() {
526 StringBuilder sb = new StringBuilder();
527 sb.append("XmlNode[");
528 boolean w = false;
529 w = addToStringField(sb, prefix, o -> !o.isEmpty(), "prefix", w);
530 w = addToStringField(sb, namespaceUri, o -> !o.isEmpty(), "namespaceUri", w);
531 w = addToStringField(sb, name, o -> !o.isEmpty(), "name", w);
532 w = addToStringField(sb, value, o -> !o.isEmpty(), "value", w);
533 w = addToStringField(sb, attributes, o -> !o.isEmpty(), "attributes", w);
534 w = addToStringField(sb, children, o -> !o.isEmpty(), "children", w);
535 w = addToStringField(sb, inputLocation, Objects::nonNull, "inputLocation", w);
536 sb.append("]");
537 return sb.toString();
538 }
539
540 private static <T> boolean addToStringField(
541 StringBuilder sb, T o, Function<T, Boolean> p, String n, boolean w) {
542 if (!p.apply(o)) {
543 if (w) {
544 sb.append(", ");
545 } else {
546 w = true;
547 }
548 sb.append(n).append("='").append(o).append('\'');
549 }
550 return w;
551 }
552 }
553 }
554 }