Skip to content

Commit

Permalink
#95 comment()
Browse files Browse the repository at this point in the history
  • Loading branch information
yegor256 committed Dec 7, 2019
1 parent ce20fbf commit 6766b15
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 41 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -108,6 +108,7 @@ Full list of supported directives in the current version:
* `PUSH`: saves cursor in stack
* `POP`: retrieves cursor from stack
* `NS`: sets namespace of all current nodes
* `COMMENT`: adds XML comment

"Cursor" or "current nodes" is where we're currently located
in the XML document. When Xembly script starts, the cursor is
Expand Down
9 changes: 9 additions & 0 deletions src/main/antlr3/org/xembly/Xembly.g
Expand Up @@ -163,6 +163,15 @@ directive returns [Directive ret]
throw new ParsingException(ex);
}
}
|
'COMMENT' argument
{
try {
$ret = new CommentDirective($argument.ret.toString());
} catch (final XmlContentException ex) {
throw new ParsingException(ex);
}
}
;

argument returns [Object ret]
Expand Down
84 changes: 84 additions & 0 deletions src/main/java/org/xembly/CommentDirective.java
@@ -0,0 +1,84 @@
/**
* Copyright (c) 2013-2019, xembly.org
* 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 xembly.org 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.
*/
package org.xembly;

import lombok.EqualsAndHashCode;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

/**
* COMMENT directive.
*
* <p>The class is immutable and thread-safe.
*
* @author Yegor Bugayenko (yegor256@gmail.com)
* @version $Id$
* @since 0.23
*/
@EqualsAndHashCode(of = "value")
final class CommentDirective implements Directive {

/**
* Text value to set.
*/
private final transient Arg value;

/**
* Public ctor.
* @param val Text value to set
* @throws XmlContentException If invalid input
*/
CommentDirective(final String val) throws XmlContentException {
this.value = new Arg(val);
}

@Override
public String toString() {
return String.format("CDATA %s", this.value);
}

@Override
public Directive.Cursor exec(final Node dom,
final Directive.Cursor cursor, final Directive.Stack stack) {
final Document doc;
if (dom.getOwnerDocument() == null) {
doc = Document.class.cast(dom);
} else {
doc = dom.getOwnerDocument();
}
final String val = this.value.raw();
for (final Node node : cursor) {
final Node cdata = doc.createComment(val);
node.appendChild(cdata);
}
return cursor;
}

}
28 changes: 27 additions & 1 deletion src/main/java/org/xembly/Directives.java
Expand Up @@ -528,7 +528,33 @@ public Directives cdata(final Object text) {
} catch (final XmlContentException ex) {
throw new IllegalArgumentException(
String.format(
"failed to understand XML content, CDATA(%s)",
"Failed to understand XML content, CDATA(%s)",
text
),
ex
);
}
return this;
}

/**
* Add an XML comment.
*
* <p>If a value provided contains illegal XML characters, a runtime
* exception will be thrown. To avoid this, it is recommended to use
* {@link Xembler#escape(String)}.
*
* @param text Text to set
* @return This object
* @since 0.23
*/
public Directives comment(final Object text) {
try {
this.all.add(new CommentDirective(text.toString()));
} catch (final XmlContentException ex) {
throw new IllegalArgumentException(
String.format(
"Failed to understand XML content, comment(%s)",
text
),
ex
Expand Down
63 changes: 63 additions & 0 deletions src/test/java/org/xembly/CommentDirectiveTest.java
@@ -0,0 +1,63 @@
/**
* Copyright (c) 2013-2019, xembly.org
* 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 xembly.org 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.
*/
package org.xembly;

import com.jcabi.matchers.XhtmlMatchers;
import javax.xml.parsers.DocumentBuilderFactory;
import org.hamcrest.MatcherAssert;
import org.junit.Test;
import org.w3c.dom.Document;

/**
* Test case for {@link CommentDirective}.
* @author Yegor Bugayenko (yegor256@gmail.com)
* @version $Id$
*/
public final class CommentDirectiveTest {

/**
* CommentDirective can add a comment.
* @throws Exception If some problem inside
*/
@Test
public void addsComment() throws Exception {
final Iterable<Directive> dirs = new Directives(
"ADD 'root'; ADD 'foo'; COMMENT 'How are you?';"
);
final Document dom = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().newDocument();
new Xembler(dirs).apply(dom);
MatcherAssert.assertThat(
XhtmlMatchers.xhtml(dom),
XhtmlMatchers.hasXPath("//comment()")
);
}

}
16 changes: 16 additions & 0 deletions src/test/java/org/xembly/DirectivesTest.java
Expand Up @@ -319,4 +319,20 @@ public Void call() throws Exception {
);
}

/**
* Directives can add comments.
* @throws Exception If some problem inside
*/
@Test
public void addsComments() throws Exception {
MatcherAssert.assertThat(
new Xembler(
new Directives()
.add("victory")
.comment(Xembler.escape("Yes, we <win>!"))
).xml(),
XhtmlMatchers.hasXPath("//comment()")
);
}

}
40 changes: 0 additions & 40 deletions src/test/java/org/xembly/XemblerTest.java
Expand Up @@ -55,46 +55,6 @@
@SuppressWarnings("PMD.TooManyMethods")
public final class XemblerTest {


@Test
public void test() throws Exception {


// '<books><book>Object Thinking</book><books>'

// create "books"
// add "book"
// change the content of "book" to "Object Thinking"

final Node node = new XMLDocument(
"<books><book>War and Peace</book></books>"
).node();
Directives dirs = new Directives()
.xpath("/books/book")
.strict(1)
.remove()
.add("book")
.set("Elegant Objects:\n\r$40.96")
.attr("id", 123);
new Xembler(dirs).apply(node);
System.out.println(new XMLDocument(node).toString());
}
















/**
* Xembler can change DOM document.
* @throws Exception If some problem inside
Expand Down

0 comments on commit 6766b15

Please sign in to comment.