From 2d07bf74ce138eeb651c302483e52fcd50531f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Boutemy?= Date: Thu, 21 Feb 2019 13:10:23 +0100 Subject: [PATCH] #61 add input location support when building XPP3 DOM --- pom.xml | 2 +- .../org/codehaus/plexus/util/xml/Xpp3Dom.java | 25 ++++++++++ .../plexus/util/xml/Xpp3DomBuilder.java | 46 ++++++++++++++++++- .../plexus/util/xml/Xpp3DomBuilderTest.java | 39 ++++++++++++++++ 4 files changed, 109 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 62050f6b..b4be05fb 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ limitations under the License. plexus-utils - 3.1.2-SNAPSHOT + 3.2.0-SNAPSHOT Plexus Common Utilities A collection of various utility classes to ease working with strings, files, command lines, XML and diff --git a/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java b/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java index 3467ab4c..321b7855 100644 --- a/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java +++ b/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java @@ -48,6 +48,11 @@ public class Xpp3Dom protected Xpp3Dom parent; + /** + * @since 3.2.0 + */ + protected Object inputLocation; + private static final String[] EMPTY_STRING_ARRAY = new String[0]; private static final Xpp3Dom[] EMPTY_DOM_ARRAY = new Xpp3Dom[0]; @@ -278,6 +283,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 // ---------------------------------------------------------------------- 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/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 );