();
}
+ /**
+ * @since 3.2.0
+ */
+ public Xpp3Dom( String name, Object inputLocation )
+ {
+ this( name );
+ this.inputLocation = inputLocation;
+ }
+
/**
* Copy constructor.
*/
@@ -100,6 +114,7 @@ public Xpp3Dom( Xpp3Dom src )
public Xpp3Dom( Xpp3Dom src, String name )
{
this.name = name;
+ this.inputLocation = src.inputLocation;
int childCount = src.getChildCount();
@@ -278,6 +293,26 @@ public void setParent( Xpp3Dom parent )
this.parent = parent;
}
+ // ----------------------------------------------------------------------
+ // Input location handling
+ // ----------------------------------------------------------------------
+
+ /**
+ * @since 3.2.0
+ */
+ public Object getInputLocation()
+ {
+ return inputLocation;
+ }
+
+ /**
+ * @since 3.2.0
+ */
+ public void setInputLocation( Object inputLocation )
+ {
+ this.inputLocation = inputLocation;
+ }
+
// ----------------------------------------------------------------------
// Helpers
// ----------------------------------------------------------------------
@@ -296,23 +331,41 @@ public void writeToSerializer( String namespace, XmlSerializer serializer )
}
/**
- * Merges one DOM into another, given a specific algorithm and possible override points for that algorithm. The
- * algorithm is as follows: 1. if the recessive DOM is null, there is nothing to do...return. 2. Determine whether
- * the dominant node will suppress the recessive one (flag=mergeSelf). A. retrieve the 'combine.self' attribute on
- * the dominant node, and try to match against 'override'... if it matches 'override', then set mergeSelf ==
- * false...the dominant node suppresses the recessive one completely. B. otherwise, use the default value for
- * mergeSelf, which is true...this is the same as specifying 'combine.self' == 'merge' as an attribute of the
- * dominant root node. 3. If mergeSelf == true A. if the dominant root node's value is empty, set it to the
- * recessive root node's value B. For each attribute in the recessive root node which is not set in the dominant
- * root node, set it. C. Determine whether children from the recessive DOM will be merged or appended to the
- * dominant DOM as siblings (flag=mergeChildren). i. if childMergeOverride is set (non-null), use that value
- * (true/false) ii. retrieve the 'combine.children' attribute on the dominant node, and try to match against
- * 'append'...if it matches 'append', then set mergeChildren == false...the recessive children will be appended as
- * siblings of the dominant children. iii. otherwise, use the default value for mergeChildren, which is true...this
- * is the same as specifying 'combine.children' == 'merge' as an attribute on the dominant root node. D. Iterate
- * through the recessive children, and: i. if mergeChildren == true and there is a corresponding dominant child
- * (matched by element name), merge the two. ii. otherwise, add the recessive child as a new child on the dominant
- * root node.
+ * Merges one DOM into another, given a specific algorithm and possible override points for that algorithm.
+ * The algorithm is as follows:
+ *
+ * - if the recessive DOM is null, there is nothing to do... return.
+ * - Determine whether the dominant node will suppress the recessive one (flag=mergeSelf).
+ *
+ * - retrieve the 'combine.self' attribute on the dominant node, and try to match against 'override'...
+ * if it matches 'override', then set mergeSelf == false...the dominant node suppresses the recessive one
+ * completely.
+ * - otherwise, use the default value for mergeSelf, which is true...this is the same as specifying
+ * 'combine.self' == 'merge' as an attribute of the dominant root node.
+ *
+ * - If mergeSelf == true
+ *
+ * - if the dominant root node's value is empty, set it to the recessive root node's value
+ * - For each attribute in the recessive root node which is not set in the dominant root node, set it.
+ * - Determine whether children from the recessive DOM will be merged or appended to the dominant DOM as
+ * siblings (flag=mergeChildren).
+ *
+ * - if childMergeOverride is set (non-null), use that value (true/false)
+ * - retrieve the 'combine.children' attribute on the dominant node, and try to match against
+ * 'append'...
+ * - if it matches 'append', then set mergeChildren == false...the recessive children will be appended as
+ * siblings of the dominant children.
+ * - otherwise, use the default value for mergeChildren, which is true...this is the same as specifying
+ * 'combine.children' == 'merge' as an attribute on the dominant root node.
+ *
+ * - Iterate through the recessive children, and:
+ *
+ * - if mergeChildren == true and there is a corresponding dominant child (matched by element name),
+ * merge the two.
+ * - otherwise, add the recessive child as a new child on the dominant root node.
+ *
+ *
+ *
*/
private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride )
{
@@ -333,9 +386,10 @@ private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boole
if ( mergeSelf )
{
- if ( isEmpty( dominant.getValue() ) )
+ if ( isEmpty( dominant.getValue() ) && !isEmpty( recessive.getValue() ) )
{
dominant.setValue( recessive.getValue() );
+ dominant.setInputLocation( recessive.getInputLocation() );
}
String[] recessiveAttrs = recessive.getAttributeNames();
diff --git a/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomBuilder.java b/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomBuilder.java
index 3f8ce989..ffe108d5 100644
--- a/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomBuilder.java
+++ b/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomBuilder.java
@@ -37,7 +37,16 @@ public class Xpp3DomBuilder
public static Xpp3Dom build( Reader reader )
throws XmlPullParserException, IOException
{
- return build( reader, DEFAULT_TRIM );
+ return build( reader, null );
+ }
+
+ /**
+ * @since 3.2.0
+ */
+ public static Xpp3Dom build( Reader reader, InputLocationBuilder locationBuilder )
+ throws XmlPullParserException, IOException
+ {
+ return build( reader, DEFAULT_TRIM, locationBuilder );
}
public static Xpp3Dom build( InputStream is, String encoding )
@@ -68,13 +77,22 @@ public static Xpp3Dom build( InputStream is, String encoding, boolean trim )
public static Xpp3Dom build( Reader reader, boolean trim )
throws XmlPullParserException, IOException
+ {
+ return build( reader, trim, null );
+ }
+
+ /**
+ * @since 3.2.0
+ */
+ public static Xpp3Dom build( Reader reader, boolean trim, InputLocationBuilder locationBuilder )
+ throws XmlPullParserException, IOException
{
try
{
final XmlPullParser parser = new MXParser();
parser.setInput( reader );
- final Xpp3Dom xpp3Dom = build( parser, trim );
+ final Xpp3Dom xpp3Dom = build( parser, trim, locationBuilder );
reader.close();
reader = null;
@@ -94,6 +112,15 @@ public static Xpp3Dom build( XmlPullParser parser )
public static Xpp3Dom build( XmlPullParser parser, boolean trim )
throws XmlPullParserException, IOException
+ {
+ return build( parser, trim, null );
+ }
+
+ /**
+ * @since 3.2.0
+ */
+ public static Xpp3Dom build( XmlPullParser parser, boolean trim, InputLocationBuilder locationBuilder )
+ throws XmlPullParserException, IOException
{
List elements = new ArrayList();
@@ -113,6 +140,11 @@ public static Xpp3Dom build( XmlPullParser parser, boolean trim )
Xpp3Dom childConfiguration = new Xpp3Dom( rawName );
+ if ( locationBuilder != null )
+ {
+ childConfiguration.setInputLocation( locationBuilder.toInputLocation( parser ) );
+ }
+
int depth = elements.size();
if ( depth > 0 )
@@ -194,4 +226,14 @@ else if ( eventType == XmlPullParser.END_TAG )
throw new IllegalStateException( "End of document found before returning to 0 depth" );
}
+
+ /**
+ * Input location builder interface, to be implemented to choose how to store data.
+ *
+ * @since 3.2.0
+ */
+ public static interface InputLocationBuilder
+ {
+ Object toInputLocation( XmlPullParser parser );
+ }
}
diff --git a/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomUtils.java b/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomUtils.java
index f3d5d488..70d00143 100644
--- a/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomUtils.java
+++ b/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomUtils.java
@@ -19,6 +19,10 @@
import org.codehaus.plexus.util.xml.pull.XmlSerializer;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
/** @author Jason van Zyl */
public class Xpp3DomUtils
@@ -71,24 +75,43 @@ public void writeToSerializer( String namespace, XmlSerializer serializer, Xpp3D
}
/**
- * Merges one DOM into another, given a specific algorithm and possible override points for that algorithm. The
- * algorithm is as follows: 1. if the recessive DOM is null, there is nothing to do...return. 2. Determine whether
- * the dominant node will suppress the recessive one (flag=mergeSelf). A. retrieve the 'combine.self' attribute on
- * the dominant node, and try to match against 'override'... if it matches 'override', then set mergeSelf ==
- * false...the dominant node suppresses the recessive one completely. B. otherwise, use the default value for
- * mergeSelf, which is true...this is the same as specifying 'combine.self' == 'merge' as an attribute of the
- * dominant root node. 3. If mergeSelf == true A. if the dominant root node's value is empty, set it to the
- * recessive root node's value B. For each attribute in the recessive root node which is not set in the dominant
- * root node, set it. C. Determine whether children from the recessive DOM will be merged or appended to the
- * dominant DOM as siblings (flag=mergeChildren). i. if childMergeOverride is set (non-null), use that value
- * (true/false) ii. retrieve the 'combine.children' attribute on the dominant node, and try to match against
- * 'append'...if it matches 'append', then set mergeChildren == false...the recessive children will be appended as
- * siblings of the dominant children. iii. otherwise, use the default value for mergeChildren, which is true...this
- * is the same as specifying 'combine.children' == 'merge' as an attribute on the dominant root node. D. Iterate
- * through the recessive children, and: i. if 'combine.id' is set and there is a corresponding dominant child
- * (matched by value of 'combine.id'), merge the two. ii. if mergeChildren == true and there is a corresponding
- * dominant child (matched by element name), merge the two. iii. otherwise, add the recessive child as a new child
- * on the dominant root node.
+ * Merges one DOM into another, given a specific algorithm and possible override points for that algorithm.
+ * The algorithm is as follows:
+ *
+ * - if the recessive DOM is null, there is nothing to do... return.
+ * - Determine whether the dominant node will suppress the recessive one (flag=mergeSelf).
+ *
+ * - retrieve the 'combine.self' attribute on the dominant node, and try to match against 'override'...
+ * if it matches 'override', then set mergeSelf == false...the dominant node suppresses the recessive one
+ * completely.
+ * - otherwise, use the default value for mergeSelf, which is true...this is the same as specifying
+ * 'combine.self' == 'merge' as an attribute of the dominant root node.
+ *
+ * - If mergeSelf == true
+ *
+ * - if the dominant root node's value is empty, set it to the recessive root node's value
+ * - For each attribute in the recessive root node which is not set in the dominant root node, set it.
+ * - Determine whether children from the recessive DOM will be merged or appended to the dominant DOM as
+ * siblings (flag=mergeChildren).
+ *
+ * - if childMergeOverride is set (non-null), use that value (true/false)
+ * - retrieve the 'combine.children' attribute on the dominant node, and try to match against
+ * 'append'...
+ * - if it matches 'append', then set mergeChildren == false...the recessive children will be appended as
+ * siblings of the dominant children.
+ * - otherwise, use the default value for mergeChildren, which is true...this is the same as specifying
+ * 'combine.children' == 'merge' as an attribute on the dominant root node.
+ *
+ * - Iterate through the recessive children, and:
+ *
+ * - if 'combine.id' is set and there is a corresponding dominant child (matched by value of 'combine.id'),
+ * merge the two.
+ * - if mergeChildren == true and there is a corresponding dominant child (matched by element name),
+ * merge the two.
+ * - otherwise, add the recessive child as a new child on the dominant root node.
+ *
+ *
+ *
*/
private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride )
{
@@ -109,9 +132,10 @@ private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boole
if ( mergeSelf )
{
- if ( isEmpty( dominant.getValue() ) )
+ if ( isEmpty( dominant.getValue() ) && !isEmpty( recessive.getValue() ) )
{
dominant.setValue( recessive.getValue() );
+ dominant.setInputLocation( recessive.getInputLocation() );
}
String[] recessiveAttrs = recessive.getAttributeNames();
diff --git a/src/test/java/org/codehaus/plexus/util/xml/Xpp3DomBuilderTest.java b/src/test/java/org/codehaus/plexus/util/xml/Xpp3DomBuilderTest.java
index 302443c2..0c8e5a17 100644
--- a/src/test/java/org/codehaus/plexus/util/xml/Xpp3DomBuilderTest.java
+++ b/src/test/java/org/codehaus/plexus/util/xml/Xpp3DomBuilderTest.java
@@ -175,6 +175,35 @@ public void testEscapingInAttributes()
assertEquals( "Compare stringified DOMs", newString, s );
}
+ @Test
+ public void testInputLocationTracking()
+ throws IOException, XmlPullParserException
+ {
+ Xpp3DomBuilder.InputLocationBuilder ilb = new Xpp3DomBuilder.InputLocationBuilder() {
+ public Object toInputLocation( XmlPullParser parser )
+ {
+ return parser.getLineNumber(); // store only line number as a simple Integer
+ }
+
+ };
+ Xpp3Dom dom = Xpp3DomBuilder.build( new StringReader( createDomString() ), true, ilb );
+ Xpp3Dom expectedDom = createExpectedDom();
+ assertEquals( "root input location", expectedDom.getInputLocation(), dom.getInputLocation() );
+ for( int i = 0; i < dom.getChildCount(); i++ )
+ {
+ Xpp3Dom elt = dom.getChild( i );
+ Xpp3Dom expectedElt = expectedDom.getChild( i );
+ assertEquals( elt.getName() + " input location", expectedElt.getInputLocation(), elt.getInputLocation() );
+
+ if ( "el2".equals( elt.getName() ) )
+ {
+ Xpp3Dom el3 = elt.getChild( 0 );
+ Xpp3Dom expectedEl3 = expectedElt.getChild( 0 );
+ assertEquals( el3.getName() + " input location", expectedEl3.getInputLocation(), el3.getInputLocation() );
+ }
+ }
+ }
+
private static String getAttributeEncodedString()
{
StringBuilder domString = new StringBuilder();
@@ -237,23 +266,33 @@ private static String createDomString()
private static Xpp3Dom createExpectedDom()
{
+ int line = 1;
Xpp3Dom expectedDom = new Xpp3Dom( "root" );
+ expectedDom.setInputLocation( line );
Xpp3Dom el1 = new Xpp3Dom( "el1" );
+ el1.setInputLocation( ++line );
el1.setValue( "element1" );
expectedDom.addChild( el1 );
+ ++line; // newline trimmed in Xpp3Dom but not in source
Xpp3Dom el2 = new Xpp3Dom( "el2" );
+ el2.setInputLocation( ++line );
el2.setAttribute( "att2", "attribute2\nnextline" );
expectedDom.addChild( el2 );
Xpp3Dom el3 = new Xpp3Dom( "el3" );
+ el3.setInputLocation( ++line );
el3.setAttribute( "att3", "attribute3" );
el3.setValue( "element3" );
el2.addChild( el3 );
+ ++line;
Xpp3Dom el4 = new Xpp3Dom( "el4" );
+ el4.setInputLocation( ++line );
el4.setValue( "" );
expectedDom.addChild( el4 );
Xpp3Dom el5 = new Xpp3Dom( "el5" );
+ el5.setInputLocation( ++line );
expectedDom.addChild( el5 );
Xpp3Dom el6 = new Xpp3Dom( "el6" );
+ el6.setInputLocation( ++line );
el6.setAttribute( "xml:space", "preserve" );
el6.setValue( " do not trim " );
expectedDom.addChild( el6 );
diff --git a/src/test/java/org/codehaus/plexus/util/xml/Xpp3DomTest.java b/src/test/java/org/codehaus/plexus/util/xml/Xpp3DomTest.java
index dd06f7b1..04444f31 100644
--- a/src/test/java/org/codehaus/plexus/util/xml/Xpp3DomTest.java
+++ b/src/test/java/org/codehaus/plexus/util/xml/Xpp3DomTest.java
@@ -27,6 +27,7 @@
import java.io.StringReader;
import java.util.HashMap;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.junit.Test;
@@ -38,17 +39,21 @@ public void testShouldPerformAppendAtFirstSubElementLevel()
// create the dominant DOM
Xpp3Dom t1 = new Xpp3Dom( "top" );
t1.setAttribute( Xpp3Dom.CHILDREN_COMBINATION_MODE_ATTRIBUTE, Xpp3Dom.CHILDREN_COMBINATION_APPEND );
+ t1.setInputLocation( "t1top" );
Xpp3Dom t1s1 = new Xpp3Dom( "topsub1" );
t1s1.setValue( "t1s1Value" );
+ t1s1.setInputLocation( "t1s1" );
t1.addChild( t1s1 );
// create the recessive DOM
Xpp3Dom t2 = new Xpp3Dom( "top" );
+ t2.setInputLocation( "t2top" );
Xpp3Dom t2s1 = new Xpp3Dom( "topsub1" );
t2s1.setValue( "t2s1Value" );
+ t2s1.setInputLocation( "t2s1" );
t2.addChild( t2s1 );
@@ -56,6 +61,12 @@ public void testShouldPerformAppendAtFirstSubElementLevel()
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( t1, t2 );
assertEquals( 2, result.getChildren( "topsub1" ).length );
+ assertEquals( "t2s1Value", result.getChildren( "topsub1" )[0].getValue() );
+ assertEquals( "t1s1Value", result.getChildren( "topsub1" )[1].getValue() );
+
+ assertEquals( "t1top", result.getInputLocation() );
+ assertEquals( "t2s1", result.getChildren( "topsub1" )[0].getInputLocation() );
+ assertEquals( "t1s1", result.getChildren( "topsub1" )[1].getInputLocation() );
}
@Test
@@ -64,17 +75,21 @@ public void testShouldOverrideAppendAndDeepMerge()
// create the dominant DOM
Xpp3Dom t1 = new Xpp3Dom( "top" );
t1.setAttribute( Xpp3Dom.CHILDREN_COMBINATION_MODE_ATTRIBUTE, Xpp3Dom.CHILDREN_COMBINATION_APPEND );
+ t1.setInputLocation( "t1top" );
Xpp3Dom t1s1 = new Xpp3Dom( "topsub1" );
t1s1.setValue( "t1s1Value" );
+ t1s1.setInputLocation( "t1s1" );
t1.addChild( t1s1 );
// create the recessive DOM
Xpp3Dom t2 = new Xpp3Dom( "top" );
+ t2.setInputLocation( "t2top" );
Xpp3Dom t2s1 = new Xpp3Dom( "topsub1" );
t2s1.setValue( "t2s1Value" );
+ t2s1.setInputLocation( "t2s1" );
t2.addChild( t2s1 );
@@ -82,6 +97,10 @@ public void testShouldOverrideAppendAndDeepMerge()
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( t1, t2, Boolean.TRUE );
assertEquals( 1, result.getChildren( "topsub1" ).length );
+ assertEquals( "t1s1Value", result.getChildren( "topsub1" )[0].getValue() );
+
+ assertEquals( "t1top", result.getInputLocation() );
+ assertEquals( "t1s1", result.getChildren( "topsub1" )[0].getInputLocation() );
}
@Test
@@ -90,6 +109,7 @@ public void testShouldPerformSelfOverrideAtTopLevel()
// create the dominant DOM
Xpp3Dom t1 = new Xpp3Dom( "top" );
t1.setAttribute( "attr", "value" );
+ t1.setInputLocation( "t1top" );
t1.setAttribute( Xpp3Dom.SELF_COMBINATION_MODE_ATTRIBUTE, Xpp3Dom.SELF_COMBINATION_OVERRIDE );
@@ -97,12 +117,14 @@ public void testShouldPerformSelfOverrideAtTopLevel()
Xpp3Dom t2 = new Xpp3Dom( "top" );
t2.setAttribute( "attr2", "value2" );
t2.setValue( "t2Value" );
+ t2.setInputLocation( "t2top" );
// merge and check results.
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( t1, t2 );
assertEquals( 2, result.getAttributeNames().length );
assertNull( result.getValue() );
+ assertEquals( "t1top", result.getInputLocation() );
}
@Test
@@ -111,11 +133,13 @@ public void testShouldMergeValuesAtTopLevelByDefault()
// create the dominant DOM
Xpp3Dom t1 = new Xpp3Dom( "top" );
t1.setAttribute( "attr", "value" );
+ t1.setInputLocation( "t1top" );
// create the recessive DOM
Xpp3Dom t2 = new Xpp3Dom( "top" );
t2.setAttribute( "attr2", "value2" );
t2.setValue( "t2Value" );
+ t2.setInputLocation( "t2top" );
// merge and check results.
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( t1, t2 );
@@ -124,6 +148,7 @@ public void testShouldMergeValuesAtTopLevelByDefault()
assertEquals( 2, result.getAttributeNames().length );
assertEquals( result.getValue(), t2.getValue() );
+ assertEquals( "t2top", result.getInputLocation() );
}
@Test
@@ -213,10 +238,12 @@ public void testShouldOverwritePluginConfigurationSubItemsByDefault()
throws XmlPullParserException, IOException
{
String parentConfigStr = "- one
- two
";
- Xpp3Dom parentConfig = Xpp3DomBuilder.build( new StringReader( parentConfigStr ) );
+ Xpp3Dom parentConfig =
+ Xpp3DomBuilder.build( new StringReader( parentConfigStr ), new FixedInputLocationBuilder( "parent" ) );
String childConfigStr = "- three
";
- Xpp3Dom childConfig = Xpp3DomBuilder.build( new StringReader( childConfigStr ) );
+ Xpp3Dom childConfig =
+ Xpp3DomBuilder.build( new StringReader( childConfigStr ), new FixedInputLocationBuilder( "child" ) );
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( childConfig, parentConfig );
Xpp3Dom items = result.getChild( "items" );
@@ -225,6 +252,7 @@ public void testShouldOverwritePluginConfigurationSubItemsByDefault()
Xpp3Dom item = items.getChild( 0 );
assertEquals( "three", item.getValue() );
+ assertEquals( "child", item.getInputLocation() );
}
@Test
@@ -232,11 +260,13 @@ public void testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet()
throws XmlPullParserException, IOException
{
String parentConfigStr = "- one
- two
";
- Xpp3Dom parentConfig = Xpp3DomBuilder.build( new StringReader( parentConfigStr ) );
+ Xpp3Dom parentConfig =
+ Xpp3DomBuilder.build( new StringReader( parentConfigStr ), new FixedInputLocationBuilder( "parent" ) );
String childConfigStr =
"- three
";
- Xpp3Dom childConfig = Xpp3DomBuilder.build( new StringReader( childConfigStr ) );
+ Xpp3Dom childConfig =
+ Xpp3DomBuilder.build( new StringReader( childConfigStr ), new FixedInputLocationBuilder( "child" ) );
Xpp3Dom result = Xpp3Dom.mergeXpp3Dom( childConfig, parentConfig );
Xpp3Dom items = result.getChild( "items" );
@@ -246,8 +276,11 @@ public void testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet()
Xpp3Dom[] item = items.getChildren();
assertEquals( "one", item[0].getValue() );
+ assertEquals( "parent", item[0].getInputLocation() );
assertEquals( "two", item[1].getValue() );
+ assertEquals( "parent", item[1].getInputLocation() );
assertEquals( "three", item[2].getValue() );
+ assertEquals( "child", item[2].getInputLocation() );
}
@Test
@@ -295,4 +328,20 @@ public void testDupeChildren()
assertNotNull( dom );
assertEquals( "y", dom.getChild( "foo" ).getValue() );
}
+
+ private static class FixedInputLocationBuilder
+ implements Xpp3DomBuilder.InputLocationBuilder
+ {
+ private final Object location;
+
+ public FixedInputLocationBuilder( Object location )
+ {
+ this.location = location;
+ }
+
+ public Object toInputLocation( XmlPullParser parser )
+ {
+ return location;
+ }
+ }
}
diff --git a/src/test/java/org/codehaus/plexus/util/xml/Xpp3DomUtilsTest.java b/src/test/java/org/codehaus/plexus/util/xml/Xpp3DomUtilsTest.java
index f41f2641..f4d0eb04 100644
--- a/src/test/java/org/codehaus/plexus/util/xml/Xpp3DomUtilsTest.java
+++ b/src/test/java/org/codehaus/plexus/util/xml/Xpp3DomUtilsTest.java
@@ -20,6 +20,7 @@
import java.io.StringReader;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.junit.Test;
public class Xpp3DomUtilsTest
@@ -34,17 +35,44 @@ public void testCombineId()
String rhs = "" + "RHS-ONLYRHS"
+ "TOOVERWRITERHS" + "";
- Xpp3Dom leftDom = Xpp3DomBuilder.build( new StringReader( lhs ) );
- Xpp3Dom rightDom = Xpp3DomBuilder.build( new StringReader( rhs ) );
+ Xpp3Dom leftDom = Xpp3DomBuilder.build( new StringReader( lhs ), new FixedInputLocationBuilder( "left" ) );
+ Xpp3Dom rightDom = Xpp3DomBuilder.build( new StringReader( rhs ), new FixedInputLocationBuilder( "right" ) );
Xpp3Dom mergeResult = Xpp3DomUtils.mergeXpp3Dom( leftDom, rightDom, true );
assertEquals( 3, mergeResult.getChildren( "property" ).length );
- assertEquals( "LHS-ONLY", mergeResult.getChildren( "property" )[0].getChild( "name" ).getValue() );
- assertEquals( "LHS", mergeResult.getChildren( "property" )[0].getChild( "value" ).getValue() );
+ Xpp3Dom p0 = mergeResult.getChildren( "property" )[0];
+ assertEquals( "LHS-ONLY", p0.getChild( "name" ).getValue() );
+ assertEquals( "left", p0.getChild( "name" ).getInputLocation() );
+ assertEquals( "LHS", p0.getChild( "value" ).getValue() );
+ assertEquals( "left", p0.getChild( "value" ).getInputLocation() );
+
+ Xpp3Dom p1 = mergeResult.getChildren( "property" )[1];
assertEquals( "TOOVERWRITE", mergeResult.getChildren( "property" )[1].getChild( "name" ).getValue() );
+ assertEquals( "left", p1.getChild( "name" ).getInputLocation() );
assertEquals( "LHS", mergeResult.getChildren( "property" )[1].getChild( "value" ).getValue() );
+ assertEquals( "left", p1.getChild( "value" ).getInputLocation() );
+
+ Xpp3Dom p2 = mergeResult.getChildren( "property" )[2];
assertEquals( "RHS-ONLY", mergeResult.getChildren( "property" )[2].getChild( "name" ).getValue() );
+ assertEquals( "right", p2.getChild( "name" ).getInputLocation() );
assertEquals( "RHS", mergeResult.getChildren( "property" )[2].getChild( "value" ).getValue() );
+ assertEquals( "right", p2.getChild( "value" ).getInputLocation() );
+ }
+
+ private static class FixedInputLocationBuilder
+ implements Xpp3DomBuilder.InputLocationBuilder
+ {
+ private final Object location;
+
+ public FixedInputLocationBuilder( Object location )
+ {
+ this.location = location;
+ }
+
+ public Object toInputLocation( XmlPullParser parser )
+ {
+ return location;
+ }
}
}