Skip to content

Commit 8722586

Browse files
author
Robert Scholte
committed
#16 Merge doesn't support exploded Map
Introduce combine.id
1 parent 57071aa commit 8722586

File tree

2 files changed

+87
-8
lines changed

2 files changed

+87
-8
lines changed

src/main/java/org/codehaus/plexus/util/xml/Xpp3DomUtils.java

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ public class Xpp3DomUtils
4242
public static final String SELF_COMBINATION_OVERRIDE = "override";
4343

4444
public static final String SELF_COMBINATION_MERGE = "merge";
45+
46+
/**
47+
* In case of complex XML structures, combining can be done based on id.
48+
*
49+
* @since 3.0.22
50+
*/
51+
public static final String ID_COMBINATION_MODE_ATTRIBUTE = "combine.id";
4552

4653
/**
4754
* This default mode for combining a DOM node during merge means that where element names
@@ -71,7 +78,7 @@ public void writeToSerializer( String namespace, XmlSerializer serializer, Xpp3D
7178
* 1. if the recessive DOM is null, there is nothing to do...return.
7279
*
7380
* 2. Determine whether the dominant node will suppress the recessive one (flag=mergeSelf).
74-
*
81+
*
7582
* A. retrieve the 'combine.self' attribute on the dominant node, and try to match against 'override'...
7683
* if it matches 'override', then set mergeSelf == false...the dominant node suppresses the recessive
7784
* one completely.
@@ -99,10 +106,13 @@ public void writeToSerializer( String namespace, XmlSerializer serializer, Xpp3D
99106
*
100107
* D. Iterate through the recessive children, and:
101108
*
102-
* i. if mergeChildren == true and there is a corresponding dominant child (matched by element name),
109+
* i. if 'combine.id' is set and there is a corresponding dominant child (matched by value of 'combine.id'),
110+
* merge the two.
111+
*
112+
* ii. if mergeChildren == true and there is a corresponding dominant child (matched by element name),
103113
* merge the two.
104114
*
105-
* ii. otherwise, add the recessive child as a new child on the dominant root node.
115+
* iii. otherwise, add the recessive child as a new child on the dominant root node.
106116
*/
107117
private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride )
108118
{
@@ -115,7 +125,7 @@ private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boole
115125
boolean mergeSelf = true;
116126

117127
String selfMergeMode = dominant.getAttribute( SELF_COMBINATION_MODE_ATTRIBUTE );
118-
128+
119129
if ( isNotEmpty( selfMergeMode ) && SELF_COMBINATION_OVERRIDE.equals( selfMergeMode ) )
120130
{
121131
mergeSelf = false;
@@ -154,16 +164,35 @@ private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boole
154164
}
155165

156166
Xpp3Dom[] children = recessive.getChildren();
157-
for ( Xpp3Dom child : children )
167+
for ( Xpp3Dom recessiveChild : children )
158168
{
159-
Xpp3Dom childDom = dominant.getChild( child.getName() );
169+
String idValue = recessiveChild.getAttribute( ID_COMBINATION_MODE_ATTRIBUTE );
170+
171+
Xpp3Dom childDom = null;
172+
if ( isNotEmpty( idValue ) )
173+
{
174+
for ( Xpp3Dom dominantChild : dominant.getChildren() )
175+
{
176+
if ( idValue.equals( dominantChild.getAttribute( ID_COMBINATION_MODE_ATTRIBUTE ) ) )
177+
{
178+
childDom = dominantChild;
179+
// we have a match, so don't append but merge
180+
mergeChildren = true;
181+
}
182+
}
183+
}
184+
else
185+
{
186+
childDom = dominant.getChild( recessiveChild.getName() );
187+
}
188+
160189
if ( mergeChildren && childDom != null )
161190
{
162-
mergeIntoXpp3Dom( childDom, child, childMergeOverride );
191+
mergeIntoXpp3Dom( childDom, recessiveChild, childMergeOverride );
163192
}
164193
else
165194
{
166-
dominant.addChild( new Xpp3Dom( child ) );
195+
dominant.addChild( new Xpp3Dom( recessiveChild ) );
167196
}
168197
}
169198
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package org.codehaus.plexus.util.xml;
2+
3+
/*
4+
* Copyright The Codehaus Foundation.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* 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, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
import java.io.StringReader;
20+
21+
import junit.framework.TestCase;
22+
23+
public class Xpp3DomUtilsTest extends TestCase {
24+
25+
public void testCombineId() throws Exception
26+
{
27+
String lhs = "<props>" +
28+
"<property combine.id='LHS-ONLY'><name>LHS-ONLY</name><value>LHS</value></property>" +
29+
"<property combine.id='TOOVERWRITE'><name>TOOVERWRITE</name><value>LHS</value></property>" +
30+
"</props>";
31+
32+
String rhs = "<props>" +
33+
"<property combine.id='RHS-ONLY'><name>RHS-ONLY</name><value>RHS</value></property>" +
34+
"<property combine.id='TOOVERWRITE'><name>TOOVERWRITE</name><value>RHS</value></property>" +
35+
"</props>";
36+
37+
Xpp3Dom leftDom = Xpp3DomBuilder.build( new StringReader( lhs ) );
38+
Xpp3Dom rightDom = Xpp3DomBuilder.build( new StringReader( rhs ) );
39+
40+
Xpp3Dom mergeResult = Xpp3DomUtils.mergeXpp3Dom( leftDom, rightDom, true );
41+
assertEquals( 3, mergeResult.getChildren( "property" ).length );
42+
43+
assertEquals( "LHS-ONLY", mergeResult.getChildren( "property" )[0].getChild( "name" ).getValue() );
44+
assertEquals( "LHS", mergeResult.getChildren( "property" )[0].getChild( "value" ).getValue() );
45+
assertEquals( "TOOVERWRITE", mergeResult.getChildren( "property" )[1].getChild( "name" ).getValue() );
46+
assertEquals( "LHS", mergeResult.getChildren( "property" )[1].getChild( "value" ).getValue() );
47+
assertEquals( "RHS-ONLY", mergeResult.getChildren( "property" )[2].getChild( "name" ).getValue() );
48+
assertEquals( "RHS", mergeResult.getChildren( "property" )[2].getChild( "value" ).getValue() );
49+
}
50+
}

0 commit comments

Comments
 (0)