diff --git a/pom.xml b/pom.xml index aa88513..9a8d0ea 100644 --- a/pom.xml +++ b/pom.xml @@ -161,6 +161,26 @@ OF THE POSSIBILITY OF SUCH DAMAGE. 8 + + maven-invoker-plugin + + + groovy/pom.xml + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + diff --git a/src/it/groovy/README.md b/src/it/groovy/README.md new file mode 100644 index 0000000..eff85a9 --- /dev/null +++ b/src/it/groovy/README.md @@ -0,0 +1,12 @@ +# Groovy Integration Test + +This module contains integration tests for `jcabi-xml` usage in Groovy scripts. + +To run the tests, execute the following command: + +```shell +mvn clean integration-test invoker:run -Dinvoker.test=groovy -DskipTests +``` + +The testing Groovy code you can find in the [verify.groovy](verify.groovy) +script. \ No newline at end of file diff --git a/src/it/groovy/first.xmir b/src/it/groovy/first.xmir new file mode 100644 index 0000000..f692288 --- /dev/null +++ b/src/it/groovy/first.xmir @@ -0,0 +1,4 @@ + + + + diff --git a/src/it/groovy/invoker.properties b/src/it/groovy/invoker.properties new file mode 100644 index 0000000..2329e6c --- /dev/null +++ b/src/it/groovy/invoker.properties @@ -0,0 +1 @@ +invoker.goals = clean \ No newline at end of file diff --git a/src/it/groovy/pom.xml b/src/it/groovy/pom.xml new file mode 100644 index 0000000..774df8a --- /dev/null +++ b/src/it/groovy/pom.xml @@ -0,0 +1,48 @@ + + + + 4.0.0 + + com.jcabi + jcabi + 1.39.0 + + com.jcabi.xml + groovy + 1.0-SNAPSHOT + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + diff --git a/src/it/groovy/same.xmir b/src/it/groovy/same.xmir new file mode 100644 index 0000000..950c93f --- /dev/null +++ b/src/it/groovy/same.xmir @@ -0,0 +1,4 @@ + + + + diff --git a/src/it/groovy/verify.groovy b/src/it/groovy/verify.groovy new file mode 100644 index 0000000..8eb2ed6 --- /dev/null +++ b/src/it/groovy/verify.groovy @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012-2022, jcabi.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: 1) Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. 2) Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. 3) Neither the name of the jcabi.com nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +import com.jcabi.xml.XMLDocument + +def log = new File(basedir, 'build.log') +def fist = new XMLDocument(new File(basedir, 'first.xmir')) +def same = new XMLDocument(new File(basedir, 'same.xmir')) + +assert fist.equals(same) + +assert log.text.contains("BUILD SUCCESS") \ No newline at end of file diff --git a/src/main/java/com/jcabi/xml/XMLDocument.java b/src/main/java/com/jcabi/xml/XMLDocument.java index e5b14d1..fa16c27 100644 --- a/src/main/java/com/jcabi/xml/XMLDocument.java +++ b/src/main/java/com/jcabi/xml/XMLDocument.java @@ -115,6 +115,11 @@ public final class XMLDocument implements XML { */ private final transient Node cache; + /** + * Transformer factory to use for {@link #toString()}. + */ + private final transient TransformerFactory tfactory; + static { if (XMLDocument.DFACTORY.getClass().getName().contains("xerces")) { try { @@ -155,6 +160,34 @@ public XMLDocument(final String text) { ); } + /** + * Public ctor, from XML as a text. + * + *

The object is created with a default implementation of + * {@link NamespaceContext}, which already defines a + * number of namespaces, for convenience, including: + * + *

 xhtml: http://www.w3.org/1999/xhtml
+     * xs: http://www.w3.org/2001/XMLSchema
+     * xsi: http://www.w3.org/2001/XMLSchema-instance
+     * xsl: http://www.w3.org/1999/XSL/Transform
+     * svg: http://www.w3.org/2000/svg
+ * + *

In future versions we will add more namespaces (submit a ticket if + * you need more of them defined here). + * + * @param text XML document body + * @param factory Transformer factory + */ + public XMLDocument(final String text, final TransformerFactory factory) { + this( + new DomParser(XMLDocument.DFACTORY, text).document(), + new XPathContext(), + false, + factory + ); + } + /** * Public ctor, from XML as a text. * @@ -307,16 +340,37 @@ public XMLDocument(final InputStream stream) throws IOException { * @param ctx Namespace context * @param lfe Is it a leaf node? */ - private XMLDocument(final Node node, final XPathContext ctx, - final boolean lfe) { - this.context = ctx; - this.leaf = lfe; - this.cache = node; + private XMLDocument( + final Node node, + final XPathContext ctx, + final boolean lfe + ) { + this(node, ctx, lfe, XMLDocument.TFACTORY); + } + + /** + * Private ctor. + * @param cache The source + * @param context Namespace context + * @param leaf Is it a leaf node? + * @param tfactory Transformer factory + * @checkstyle ParameterNumberCheck (5 lines) + */ + public XMLDocument( + final Node cache, + final XPathContext context, + final boolean leaf, + final TransformerFactory tfactory + ) { + this.context = context; + this.leaf = leaf; + this.cache = cache; + this.tfactory = tfactory; } @Override public String toString() { - return XMLDocument.asString(this.cache); + return this.asString(this.cache); } @Override @@ -505,18 +559,18 @@ private T fetch(final String query, final Class type) * @param node The DOM node. * @return String representation */ - private static String asString(final Node node) { + private String asString(final Node node) { final StringWriter writer = new StringWriter(); final Transformer trans; try { synchronized (XMLDocument.class) { - trans = XMLDocument.TFACTORY.newTransformer(); + trans = this.tfactory.newTransformer(); } } catch (final TransformerConfigurationException ex) { throw new IllegalArgumentException( String.format( "Failed to create transformer by %s", - XMLDocument.TFACTORY.getClass().getName() + this.tfactory.getClass().getName() ), ex ); diff --git a/src/test/java/com/jcabi/xml/XMLDocumentTest.java b/src/test/java/com/jcabi/xml/XMLDocumentTest.java index 2d7c3b7..c40e1c5 100644 --- a/src/test/java/com/jcabi/xml/XMLDocumentTest.java +++ b/src/test/java/com/jcabi/xml/XMLDocumentTest.java @@ -40,6 +40,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import javax.xml.transform.TransformerFactory; import org.apache.commons.lang3.StringUtils; import org.cactoos.io.ResourceOf; import org.cactoos.io.TeeInput; @@ -48,6 +49,7 @@ import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.hamcrest.core.IsEqual; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -381,6 +383,27 @@ void comparesToAnotherDocument() { ); } + @Test + @Disabled + void comparesDocumentsWithDifferentIndentations() { + // @checkstyle MethodBodyCommentsCheck (4 lines) + // @todo #1:90min Implement comparison of XML documents with different indentations. + // The current implementation of XMLDocument does not ignore different indentations + // when comparing two XML documents. We need to implement a comparison that ignores + // different indentations. Don't forget to remove the @Disabled annotation from this test. + final TransformerFactory factory = TransformerFactory.newInstance( + "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl", + Thread.currentThread().getContextClassLoader() + ); + MatcherAssert.assertThat( + "Different indentations should be ignored", + new XMLDocument("\n \n", factory), + Matchers.equalTo( + new XMLDocument("\n \n\n", factory) + ) + ); + } + @Test void preservesXmlNamespaces() { final String xml = "";