19
19
import org .codehaus .plexus .util .xml .pull .XmlSerializer ;
20
20
21
21
import java .io .IOException ;
22
- import java .util .Arrays ;
23
22
import java .util .HashMap ;
24
- import java .util .Iterator ;
25
23
import java .util .Map ;
26
24
27
25
/** @author Jason van Zyl */
@@ -52,6 +50,14 @@ public class Xpp3DomUtils
52
50
* @since 3.0.22
53
51
*/
54
52
public static final String ID_COMBINATION_MODE_ATTRIBUTE = "combine.id" ;
53
+
54
+ /**
55
+ * In case of complex XML structures, combining can be done based on keys.
56
+ * This is a comma separated list of attribute names.
57
+ *
58
+ * @Since 3.4.0
59
+ */
60
+ public static final String KEYS_COMBINATION_MODE_ATTRIBUTE = "combine.keys" ;
55
61
56
62
/**
57
63
* This default mode for combining a DOM node during merge means that where element names match, the process will
@@ -106,6 +112,8 @@ public void writeToSerializer( String namespace, XmlSerializer serializer, Xpp3D
106
112
* <ol type="i">
107
113
* <li> if 'combine.id' is set and there is a corresponding dominant child (matched by value of 'combine.id'),
108
114
* merge the two.</li>
115
+ * <li> if 'combine.keys' is set and there is a corresponding dominant child (matched by value of key elements),
116
+ * merge the two.</li>
109
117
* <li> if mergeChildren == true and there is a corresponding dominant child (matched by element name),
110
118
* merge the two.</li>
111
119
* <li> otherwise, add the recessive child as a new child on the dominant root node.</li>
@@ -167,6 +175,7 @@ private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boole
167
175
for ( Xpp3Dom recessiveChild : children )
168
176
{
169
177
String idValue = recessiveChild .getAttribute ( ID_COMBINATION_MODE_ATTRIBUTE );
178
+ String keysValue = recessiveChild .getAttribute ( KEYS_COMBINATION_MODE_ATTRIBUTE );
170
179
171
180
Xpp3Dom childDom = null ;
172
181
if ( isNotEmpty ( idValue ) )
@@ -181,6 +190,32 @@ private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boole
181
190
}
182
191
}
183
192
}
193
+ else if ( isNotEmpty ( keysValue ) )
194
+ {
195
+ String [] keys = keysValue .split ( "," );
196
+ Map <String , String > recessiveKeyValues = new HashMap <String , String >( keys .length );
197
+ for ( String key : keys )
198
+ {
199
+ recessiveKeyValues .put ( key , recessiveChild .getChild ( key ).getValue () );
200
+ }
201
+
202
+ for ( Xpp3Dom dominantChild : dominant .getChildren () )
203
+ {
204
+ Map <String , String > dominantKeyValues = new HashMap <String , String >( keys .length );
205
+ for ( String key : keys )
206
+ {
207
+ dominantKeyValues .put ( key , dominantChild .getChild ( key ).getValue () );
208
+ }
209
+
210
+ if ( recessiveKeyValues .equals ( dominantKeyValues ) )
211
+ {
212
+ childDom = dominantChild ;
213
+ // we have a match, so don't append but merge
214
+ mergeChildren = true ;
215
+ }
216
+ }
217
+
218
+ }
184
219
else
185
220
{
186
221
childDom = dominant .getChild ( recessiveChild .getName () );
0 commit comments