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.api.xml;
20
21 import java.util.List;
22 import java.util.Map;
23
24 import org.apache.maven.api.annotations.Experimental;
25 import org.apache.maven.api.annotations.Immutable;
26 import org.apache.maven.api.annotations.Nonnull;
27 import org.apache.maven.api.annotations.Nullable;
28 import org.apache.maven.api.annotations.ThreadSafe;
29
30 /**
31 * An immutable xml node.
32 *
33 * @since 4.0
34 */
35 @Experimental
36 @ThreadSafe
37 @Immutable
38 public interface XmlNode {
39
40 String CHILDREN_COMBINATION_MODE_ATTRIBUTE = "combine.children";
41
42 String CHILDREN_COMBINATION_MERGE = "merge";
43
44 String CHILDREN_COMBINATION_APPEND = "append";
45
46 /**
47 * This default mode for combining children DOMs during merge means that where element names match, the process will
48 * try to merge the element data, rather than putting the dominant and recessive elements (which share the same
49 * element name) as siblings in the resulting DOM.
50 */
51 String DEFAULT_CHILDREN_COMBINATION_MODE = CHILDREN_COMBINATION_MERGE;
52
53 String SELF_COMBINATION_MODE_ATTRIBUTE = "combine.self";
54
55 String SELF_COMBINATION_OVERRIDE = "override";
56
57 String SELF_COMBINATION_MERGE = "merge";
58
59 String SELF_COMBINATION_REMOVE = "remove";
60
61 /**
62 * In case of complex XML structures, combining can be done based on id.
63 */
64 String ID_COMBINATION_MODE_ATTRIBUTE = "combine.id";
65
66 /**
67 * In case of complex XML structures, combining can be done based on keys.
68 * This is a comma separated list of attribute names.
69 */
70 String KEYS_COMBINATION_MODE_ATTRIBUTE = "combine.keys";
71
72 /**
73 * This default mode for combining a DOM node during merge means that where element names match, the process will
74 * try to merge the element attributes and values, rather than overriding the recessive element completely with the
75 * dominant one. This means that wherever the dominant element doesn't provide the value or a particular attribute,
76 * that value or attribute will be set from the recessive DOM node.
77 */
78 String DEFAULT_SELF_COMBINATION_MODE = SELF_COMBINATION_MERGE;
79
80 @Nonnull
81 String getName();
82
83 @Nullable
84 String getValue();
85
86 @Nonnull
87 Map<String, String> getAttributes();
88
89 @Nullable
90 String getAttribute(@Nonnull String name);
91
92 @Nonnull
93 List<XmlNode> getChildren();
94
95 @Nullable
96 XmlNode getChild(String name);
97
98 @Nullable
99 Object getInputLocation();
100
101 default XmlNode merge(@Nullable XmlNode source) {
102 return merge(source, (Boolean) null);
103 }
104
105 XmlNode merge(@Nullable XmlNode source, @Nullable Boolean childMergeOverride);
106
107 XmlNode clone();
108
109 /**
110 * Merge recessive into dominant and return either {@code dominant}
111 * with merged information or a clone of {@code recessive} if
112 * {@code dominant} is {@code null}.
113 *
114 * @param dominant the node
115 * @param recessive if {@code null}, nothing will happen
116 * @return the merged node
117 */
118 @Nullable
119 static XmlNode merge(@Nullable XmlNode dominant, @Nullable XmlNode recessive) {
120 return merge(dominant, recessive, null);
121 }
122
123 @Nullable
124 static XmlNode merge(
125 @Nullable XmlNode dominant, @Nullable XmlNode recessive, @Nullable Boolean childMergeOverride) {
126 if (recessive == null) {
127 return dominant;
128 }
129 if (dominant == null) {
130 return recessive;
131 }
132 return dominant.merge(recessive, childMergeOverride);
133 }
134 }