Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit dd8d35a

Browse filesBrowse files
committed
#61 keep input location while merging
1 parent 26cc2bf commit dd8d35a
Copy full SHA for dd8d35a

File tree

Expand file treeCollapse file tree

4 files changed

+175
-45
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+175
-45
lines changed

‎src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java

Copy file name to clipboardExpand all lines: src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java
+47-18Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ public Xpp3Dom( String name )
9191
childMap = new HashMap<String, Xpp3Dom>();
9292
}
9393

94+
/**
95+
* @since 3.2.0
96+
*/
97+
public Xpp3Dom( String name, Object inputLocation )
98+
{
99+
this( name );
100+
this.inputLocation = inputLocation;
101+
}
102+
94103
/**
95104
* Copy constructor.
96105
*/
@@ -105,6 +114,7 @@ public Xpp3Dom( Xpp3Dom src )
105114
public Xpp3Dom( Xpp3Dom src, String name )
106115
{
107116
this.name = name;
117+
this.inputLocation = src.inputLocation;
108118

109119
int childCount = src.getChildCount();
110120

@@ -321,23 +331,41 @@ public void writeToSerializer( String namespace, XmlSerializer serializer )
321331
}
322332

323333
/**
324-
* Merges one DOM into another, given a specific algorithm and possible override points for that algorithm. The
325-
* algorithm is as follows: 1. if the recessive DOM is null, there is nothing to do...return. 2. Determine whether
326-
* the dominant node will suppress the recessive one (flag=mergeSelf). A. retrieve the 'combine.self' attribute on
327-
* the dominant node, and try to match against 'override'... if it matches 'override', then set mergeSelf ==
328-
* false...the dominant node suppresses the recessive one completely. B. otherwise, use the default value for
329-
* mergeSelf, which is true...this is the same as specifying 'combine.self' == 'merge' as an attribute of the
330-
* dominant root node. 3. If mergeSelf == true A. if the dominant root node's value is empty, set it to the
331-
* recessive root node's value B. For each attribute in the recessive root node which is not set in the dominant
332-
* root node, set it. C. Determine whether children from the recessive DOM will be merged or appended to the
333-
* dominant DOM as siblings (flag=mergeChildren). i. if childMergeOverride is set (non-null), use that value
334-
* (true/false) ii. retrieve the 'combine.children' attribute on the dominant node, and try to match against
335-
* 'append'...if it matches 'append', then set mergeChildren == false...the recessive children will be appended as
336-
* siblings of the dominant children. iii. otherwise, use the default value for mergeChildren, which is true...this
337-
* is the same as specifying 'combine.children' == 'merge' as an attribute on the dominant root node. D. Iterate
338-
* through the recessive children, and: i. if mergeChildren == true and there is a corresponding dominant child
339-
* (matched by element name), merge the two. ii. otherwise, add the recessive child as a new child on the dominant
340-
* root node.
334+
* Merges one DOM into another, given a specific algorithm and possible override points for that algorithm.<p>
335+
* The algorithm is as follows:
336+
* <ol>
337+
* <li> if the recessive DOM is null, there is nothing to do... return.</li>
338+
* <li> Determine whether the dominant node will suppress the recessive one (flag=mergeSelf).
339+
* <ol type="A">
340+
* <li> retrieve the 'combine.self' attribute on the dominant node, and try to match against 'override'...
341+
* if it matches 'override', then set mergeSelf == false...the dominant node suppresses the recessive one
342+
* completely.</li>
343+
* <li> otherwise, use the default value for mergeSelf, which is true...this is the same as specifying
344+
* 'combine.self' == 'merge' as an attribute of the dominant root node.</li>
345+
* </ol></li>
346+
* <li> If mergeSelf == true
347+
* <ol type="A">
348+
* <li> if the dominant root node's value is empty, set it to the recessive root node's value</li>
349+
* <li> For each attribute in the recessive root node which is not set in the dominant root node, set it.</li>
350+
* <li> Determine whether children from the recessive DOM will be merged or appended to the dominant DOM as
351+
* siblings (flag=mergeChildren).
352+
* <ol type="i">
353+
* <li> if childMergeOverride is set (non-null), use that value (true/false)</li>
354+
* <li> retrieve the 'combine.children' attribute on the dominant node, and try to match against
355+
* 'append'...</li>
356+
* <li> if it matches 'append', then set mergeChildren == false...the recessive children will be appended as
357+
* siblings of the dominant children.</li>
358+
* <li> otherwise, use the default value for mergeChildren, which is true...this is the same as specifying
359+
* 'combine.children' == 'merge' as an attribute on the dominant root node.</li>
360+
* </ol></li>
361+
* <li> Iterate through the recessive children, and:
362+
* <ol type="i">
363+
* <li> if mergeChildren == true and there is a corresponding dominant child (matched by element name),
364+
* merge the two.</li>
365+
* <li> otherwise, add the recessive child as a new child on the dominant root node.</li>
366+
* </ol></li>
367+
* </ol></li>
368+
* </ol>
341369
*/
342370
private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride )
343371
{
@@ -358,9 +386,10 @@ private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boole
358386

359387
if ( mergeSelf )
360388
{
361-
if ( isEmpty( dominant.getValue() ) )
389+
if ( isEmpty( dominant.getValue() ) && !isEmpty( recessive.getValue() ) )
362390
{
363391
dominant.setValue( recessive.getValue() );
392+
dominant.setInputLocation( recessive.getInputLocation() );
364393
}
365394

366395
String[] recessiveAttrs = recessive.getAttributeNames();

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

Copy file name to clipboardExpand all lines: src/main/java/org/codehaus/plexus/util/xml/Xpp3DomUtils.java
+43-19Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
import org.codehaus.plexus.util.xml.pull.XmlSerializer;
2020

2121
import java.io.IOException;
22+
import java.util.Arrays;
23+
import java.util.HashMap;
24+
import java.util.Iterator;
25+
import java.util.Map;
2226

2327
/** @author Jason van Zyl */
2428
public class Xpp3DomUtils
@@ -71,24 +75,43 @@ public void writeToSerializer( String namespace, XmlSerializer serializer, Xpp3D
7175
}
7276

7377
/**
74-
* Merges one DOM into another, given a specific algorithm and possible override points for that algorithm. The
75-
* algorithm is as follows: 1. if the recessive DOM is null, there is nothing to do...return. 2. Determine whether
76-
* the dominant node will suppress the recessive one (flag=mergeSelf). A. retrieve the 'combine.self' attribute on
77-
* the dominant node, and try to match against 'override'... if it matches 'override', then set mergeSelf ==
78-
* false...the dominant node suppresses the recessive one completely. B. otherwise, use the default value for
79-
* mergeSelf, which is true...this is the same as specifying 'combine.self' == 'merge' as an attribute of the
80-
* dominant root node. 3. If mergeSelf == true A. if the dominant root node's value is empty, set it to the
81-
* recessive root node's value B. For each attribute in the recessive root node which is not set in the dominant
82-
* root node, set it. C. Determine whether children from the recessive DOM will be merged or appended to the
83-
* dominant DOM as siblings (flag=mergeChildren). i. if childMergeOverride is set (non-null), use that value
84-
* (true/false) ii. retrieve the 'combine.children' attribute on the dominant node, and try to match against
85-
* 'append'...if it matches 'append', then set mergeChildren == false...the recessive children will be appended as
86-
* siblings of the dominant children. iii. otherwise, use the default value for mergeChildren, which is true...this
87-
* is the same as specifying 'combine.children' == 'merge' as an attribute on the dominant root node. D. Iterate
88-
* through the recessive children, and: i. if 'combine.id' is set and there is a corresponding dominant child
89-
* (matched by value of 'combine.id'), merge the two. ii. if mergeChildren == true and there is a corresponding
90-
* dominant child (matched by element name), merge the two. iii. otherwise, add the recessive child as a new child
91-
* on the dominant root node.
78+
* Merges one DOM into another, given a specific algorithm and possible override points for that algorithm.<p>
79+
* The algorithm is as follows:
80+
* <ol>
81+
* <li> if the recessive DOM is null, there is nothing to do... return.</li>
82+
* <li> Determine whether the dominant node will suppress the recessive one (flag=mergeSelf).
83+
* <ol type="A">
84+
* <li> retrieve the 'combine.self' attribute on the dominant node, and try to match against 'override'...
85+
* if it matches 'override', then set mergeSelf == false...the dominant node suppresses the recessive one
86+
* completely.</li>
87+
* <li> otherwise, use the default value for mergeSelf, which is true...this is the same as specifying
88+
* 'combine.self' == 'merge' as an attribute of the dominant root node.</li>
89+
* </ol></li>
90+
* <li> If mergeSelf == true
91+
* <ol type="A">
92+
* <li> if the dominant root node's value is empty, set it to the recessive root node's value</li>
93+
* <li> For each attribute in the recessive root node which is not set in the dominant root node, set it.</li>
94+
* <li> Determine whether children from the recessive DOM will be merged or appended to the dominant DOM as
95+
* siblings (flag=mergeChildren).
96+
* <ol type="i">
97+
* <li> if childMergeOverride is set (non-null), use that value (true/false)</li>
98+
* <li> retrieve the 'combine.children' attribute on the dominant node, and try to match against
99+
* 'append'...</li>
100+
* <li> if it matches 'append', then set mergeChildren == false...the recessive children will be appended as
101+
* siblings of the dominant children.</li>
102+
* <li> otherwise, use the default value for mergeChildren, which is true...this is the same as specifying
103+
* 'combine.children' == 'merge' as an attribute on the dominant root node.</li>
104+
* </ol></li>
105+
* <li> Iterate through the recessive children, and:
106+
* <ol type="i">
107+
* <li> if 'combine.id' is set and there is a corresponding dominant child (matched by value of 'combine.id'),
108+
* merge the two.</li>
109+
* <li> if mergeChildren == true and there is a corresponding dominant child (matched by element name),
110+
* merge the two.</li>
111+
* <li> otherwise, add the recessive child as a new child on the dominant root node.</li>
112+
* </ol></li>
113+
* </ol></li>
114+
* </ol>
92115
*/
93116
private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride )
94117
{
@@ -109,9 +132,10 @@ private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boole
109132

110133
if ( mergeSelf )
111134
{
112-
if ( isEmpty( dominant.getValue() ) )
135+
if ( isEmpty( dominant.getValue() ) && !isEmpty( recessive.getValue() ) )
113136
{
114137
dominant.setValue( recessive.getValue() );
138+
dominant.setInputLocation( recessive.getInputLocation() );
115139
}
116140

117141
String[] recessiveAttrs = recessive.getAttributeNames();

‎src/test/java/org/codehaus/plexus/util/xml/Xpp3DomTest.java

Copy file name to clipboardExpand all lines: src/test/java/org/codehaus/plexus/util/xml/Xpp3DomTest.java
+53-4Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.io.StringReader;
2828
import java.util.HashMap;
2929

30+
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
3031
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
3132
import org.junit.Test;
3233

@@ -38,24 +39,34 @@ public void testShouldPerformAppendAtFirstSubElementLevel()
3839
// create the dominant DOM
3940
Xpp3Dom t1 = new Xpp3Dom( "top" );
4041
t1.setAttribute( Xpp3Dom.CHILDREN_COMBINATION_MODE_ATTRIBUTE, Xpp3Dom.CHILDREN_COMBINATION_APPEND );
42+
t1.setInputLocation( "t1top" );
4143

4244
Xpp3Dom t1s1 = new Xpp3Dom( "topsub1" );
4345
t1s1.setValue( "t1s1Value" );
46+
t1s1.setInputLocation( "t1s1" );
4447

4548
t1.addChild( t1s1 );
4649

4750
// create the recessive DOM
4851
Xpp3Dom t2 = new Xpp3Dom( "top" );
52+
t2.setInputLocation( "t2top" );
4953

5054
Xpp3Dom t2s1 = new Xpp3Dom( "topsub1" );
5155
t2s1.setValue( "t2s1Value" );
56+
t2s1.setInputLocation( "t2s1" );
5257

5358
t2.addChild( t2s1 );
5459

5560
// merge and check results.
5661
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( t1, t2 );
5762

5863
assertEquals( 2, result.getChildren( "topsub1" ).length );
64+
assertEquals( "t2s1Value", result.getChildren( "topsub1" )[0].getValue() );
65+
assertEquals( "t1s1Value", result.getChildren( "topsub1" )[1].getValue() );
66+
67+
assertEquals( "t1top", result.getInputLocation() );
68+
assertEquals( "t2s1", result.getChildren( "topsub1" )[0].getInputLocation() );
69+
assertEquals( "t1s1", result.getChildren( "topsub1" )[1].getInputLocation() );
5970
}
6071

6172
@Test
@@ -64,24 +75,32 @@ public void testShouldOverrideAppendAndDeepMerge()
6475
// create the dominant DOM
6576
Xpp3Dom t1 = new Xpp3Dom( "top" );
6677
t1.setAttribute( Xpp3Dom.CHILDREN_COMBINATION_MODE_ATTRIBUTE, Xpp3Dom.CHILDREN_COMBINATION_APPEND );
78+
t1.setInputLocation( "t1top" );
6779

6880
Xpp3Dom t1s1 = new Xpp3Dom( "topsub1" );
6981
t1s1.setValue( "t1s1Value" );
82+
t1s1.setInputLocation( "t1s1" );
7083

7184
t1.addChild( t1s1 );
7285

7386
// create the recessive DOM
7487
Xpp3Dom t2 = new Xpp3Dom( "top" );
88+
t2.setInputLocation( "t2top" );
7589

7690
Xpp3Dom t2s1 = new Xpp3Dom( "topsub1" );
7791
t2s1.setValue( "t2s1Value" );
92+
t2s1.setInputLocation( "t2s1" );
7893

7994
t2.addChild( t2s1 );
8095

8196
// merge and check results.
8297
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( t1, t2, Boolean.TRUE );
8398

8499
assertEquals( 1, result.getChildren( "topsub1" ).length );
100+
assertEquals( "t1s1Value", result.getChildren( "topsub1" )[0].getValue() );
101+
102+
assertEquals( "t1top", result.getInputLocation() );
103+
assertEquals( "t1s1", result.getChildren( "topsub1" )[0].getInputLocation() );
85104
}
86105

87106
@Test
@@ -90,19 +109,22 @@ public void testShouldPerformSelfOverrideAtTopLevel()
90109
// create the dominant DOM
91110
Xpp3Dom t1 = new Xpp3Dom( "top" );
92111
t1.setAttribute( "attr", "value" );
112+
t1.setInputLocation( "t1top" );
93113

94114
t1.setAttribute( Xpp3Dom.SELF_COMBINATION_MODE_ATTRIBUTE, Xpp3Dom.SELF_COMBINATION_OVERRIDE );
95115

96116
// create the recessive DOM
97117
Xpp3Dom t2 = new Xpp3Dom( "top" );
98118
t2.setAttribute( "attr2", "value2" );
99119
t2.setValue( "t2Value" );
120+
t2.setInputLocation( "t2top" );
100121

101122
// merge and check results.
102123
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( t1, t2 );
103124

104125
assertEquals( 2, result.getAttributeNames().length );
105126
assertNull( result.getValue() );
127+
assertEquals( "t1top", result.getInputLocation() );
106128
}
107129

108130
@Test
@@ -111,11 +133,13 @@ public void testShouldMergeValuesAtTopLevelByDefault()
111133
// create the dominant DOM
112134
Xpp3Dom t1 = new Xpp3Dom( "top" );
113135
t1.setAttribute( "attr", "value" );
136+
t1.setInputLocation( "t1top" );
114137

115138
// create the recessive DOM
116139
Xpp3Dom t2 = new Xpp3Dom( "top" );
117140
t2.setAttribute( "attr2", "value2" );
118141
t2.setValue( "t2Value" );
142+
t2.setInputLocation( "t2top" );
119143

120144
// merge and check results.
121145
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( t1, t2 );
@@ -124,6 +148,7 @@ public void testShouldMergeValuesAtTopLevelByDefault()
124148
assertEquals( 2, result.getAttributeNames().length );
125149

126150
assertEquals( result.getValue(), t2.getValue() );
151+
assertEquals( "t2top", result.getInputLocation() );
127152
}
128153

129154
@Test
@@ -213,10 +238,12 @@ public void testShouldOverwritePluginConfigurationSubItemsByDefault()
213238
throws XmlPullParserException, IOException
214239
{
215240
String parentConfigStr = "<configuration><items><item>one</item><item>two</item></items></configuration>";
216-
Xpp3Dom parentConfig = Xpp3DomBuilder.build( new StringReader( parentConfigStr ) );
241+
Xpp3Dom parentConfig =
242+
Xpp3DomBuilder.build( new StringReader( parentConfigStr ), new FixedInputLocationBuilder( "parent" ) );
217243

218244
String childConfigStr = "<configuration><items><item>three</item></items></configuration>";
219-
Xpp3Dom childConfig = Xpp3DomBuilder.build( new StringReader( childConfigStr ) );
245+
Xpp3Dom childConfig =
246+
Xpp3DomBuilder.build( new StringReader( childConfigStr ), new FixedInputLocationBuilder( "child" ) );
220247

221248
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( childConfig, parentConfig );
222249
Xpp3Dom items = result.getChild( "items" );
@@ -225,18 +252,21 @@ public void testShouldOverwritePluginConfigurationSubItemsByDefault()
225252

226253
Xpp3Dom item = items.getChild( 0 );
227254
assertEquals( "three", item.getValue() );
255+
assertEquals( "child", item.getInputLocation() );
228256
}
229257

230258
@Test
231259
public void testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet()
232260
throws XmlPullParserException, IOException
233261
{
234262
String parentConfigStr = "<configuration><items><item>one</item><item>two</item></items></configuration>";
235-
Xpp3Dom parentConfig = Xpp3DomBuilder.build( new StringReader( parentConfigStr ) );
263+
Xpp3Dom parentConfig =
264+
Xpp3DomBuilder.build( new StringReader( parentConfigStr ), new FixedInputLocationBuilder( "parent" ) );
236265

237266
String childConfigStr =
238267
"<configuration><items combine.children=\"append\"><item>three</item></items></configuration>";
239-
Xpp3Dom childConfig = Xpp3DomBuilder.build( new StringReader( childConfigStr ) );
268+
Xpp3Dom childConfig =
269+
Xpp3DomBuilder.build( new StringReader( childConfigStr ), new FixedInputLocationBuilder( "child" ) );
240270

241271
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( childConfig, parentConfig );
242272
Xpp3Dom items = result.getChild( "items" );
@@ -246,8 +276,11 @@ public void testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet()
246276
Xpp3Dom[] item = items.getChildren();
247277

248278
assertEquals( "one", item[0].getValue() );
279+
assertEquals( "parent", item[0].getInputLocation() );
249280
assertEquals( "two", item[1].getValue() );
281+
assertEquals( "parent", item[1].getInputLocation() );
250282
assertEquals( "three", item[2].getValue() );
283+
assertEquals( "child", item[2].getInputLocation() );
251284
}
252285

253286
@Test
@@ -295,4 +328,20 @@ public void testDupeChildren()
295328
assertNotNull( dom );
296329
assertEquals( "y", dom.getChild( "foo" ).getValue() );
297330
}
331+
332+
private static class FixedInputLocationBuilder
333+
implements Xpp3DomBuilder.InputLocationBuilder
334+
{
335+
private final Object location;
336+
337+
public FixedInputLocationBuilder( Object location )
338+
{
339+
this.location = location;
340+
}
341+
342+
public Object toInputLocation( XmlPullParser parser )
343+
{
344+
return location;
345+
}
346+
}
298347
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.