Skip to content

Commit

Permalink
bug(objectionary#3927): combine all
Browse files Browse the repository at this point in the history
  • Loading branch information
maxonfjvipon committed Feb 18, 2025
1 parent 242087f commit 176fe81
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 86 deletions.
129 changes: 93 additions & 36 deletions eo-parser/src/main/java/org/eolang/parser/StUnhex.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,60 +24,117 @@
package org.eolang.parser;

import com.yegor256.xsline.Shift;
import com.yegor256.xsline.StClasspath;
import com.yegor256.xsline.StEnvelope;
import com.yegor256.xsline.StSequence;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import org.apache.commons.text.StringEscapeUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xembly.Directive;
import org.xembly.Directives;

/**
* This {@link Shift} turns hex data inside XMIR
* This {@link Shift} turns hex data inside XMIR.
* into EO-printable data.
*
* @since 0.29.0
*/
final class StUnhex extends StEnvelope {
/**
* Ctor.
* Unexing via {@link com.github.lombrozo.xnav.Xnav}.
*/
StUnhex() {
super(
new StSequence(
StUnhex.class.getSimpleName(),
new StXnav(
StUnhex.xpath("number"),
xnav -> {
final double number = StUnhex.buffer(
StUnhex.undash(xnav.element("o").text().orElse(""))
).getDouble();
final Node node = xnav.node();
if (Double.isNaN(number) || Double.isInfinite(number)) {
((Element) node).setAttribute("skip", "");
} else {
node.setTextContent(StUnhex.number(number));
}
}
),
new StXnav(
StUnhex.xpath("string"),
xnav -> xnav.node().setTextContent(
String.format(
"\"%s\"",
StringEscapeUtils.escapeJava(
new String(
StUnhex.buffer(
StUnhex.undash(xnav.element("o").text().orElse(""))
).array(),
StandardCharsets.UTF_8
)
)
static final Shift XNAV = new StSequence(
StUnhex.class.getSimpleName(),
new StXnav(
StUnhex.elements("number"),
xnav -> {
final double number = StUnhex.buffer(
StUnhex.undash(xnav.element("o").text().orElse(""))
).getDouble();
final Node node = xnav.node();
if (Double.isNaN(number) || Double.isInfinite(number)) {
((Element) node).setAttribute("skip", "");
} else {
node.setTextContent(StUnhex.number(number));
}
}
),
new StXnav(
StUnhex.elements("string"),
xnav -> xnav.node().setTextContent(
String.format(
"\"%s\"",
StringEscapeUtils.escapeJava(
new String(
StUnhex.buffer(
StUnhex.undash(xnav.element("o").text().orElse(""))
).array(),
StandardCharsets.UTF_8
)
)
)
)
);
)
);

/**
* Unhexing via {@link com.jcabi.xml.XMLDocument#xpath(String)}.
*/
static final Shift XPATH = new StSequence(
StUnhex.class.getSimpleName(),
new StXPath(
StUnhex.elements("number"),
xml -> {
final double number = StUnhex.buffer(
StUnhex.undash(xml.xpath("./o/text()").get(0))
).getDouble();
final Iterable<Directive> dirs;
if (Double.isNaN(number) || Double.isInfinite(number)) {
dirs = new Directives().attr("skip", "");
} else {
dirs = new Directives().set(StUnhex.number(number));
}
return dirs;
}
),
new StXPath(
StUnhex.elements("string"),
xml -> new Directives().set(
String.format(
"\"%s\"",
StringEscapeUtils.escapeJava(
new String(
StUnhex.buffer(
StUnhex.undash(xml.xpath("./o/text()").get(0))
).array(),
StandardCharsets.UTF_8
)
)
)
)
)
);

/**
* Unhexing via XSL.
*/
static final Shift XSL = new StClasspath("/org/eolang/parser/print/unhex-data.xsl");

/**
* Ctor.
*/
StUnhex() {
this(StUnhex.XNAV);
}

/**
* Base ctor.
* @param origin Original shift
*/
StUnhex(final Shift origin) {
super(origin);
}

/**
Expand Down Expand Up @@ -137,11 +194,11 @@ private static String undash(final String txt) {
}

/**
* Make XPath.
* Find elements by XPath for given type.
* @param type The type to match
* @return XPath
*/
private static String xpath(final String type) {
private static String elements(final String type) {
return String.format(
"//o[@base='Q.org.eolang.%1$s' and(not(@skip)) and o[1][@base='Q.org.eolang.bytes' and not(o) and string-length(normalize-space(text()))>0]]",
type
Expand Down
31 changes: 17 additions & 14 deletions eo-parser/src/main/java/org/eolang/parser/StXPath.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
* @since 0.29.0
*/
public final class StXPath implements Shift {
/**
* Xpath for finding first element.
*/
private static final String INDEXED = "(%s)[1]";

/**
* XPath to search for.
Expand Down Expand Up @@ -68,22 +72,21 @@ public String uid() {
@Override
public XML apply(final int position, final XML xml) {
final List<XML> nodes = xml.nodes(this.xpath);
if (nodes.size() > 1) {
throw new IllegalArgumentException(
String.format(
"XPath '%s' returned too many elements (%d)",
this.xpath, nodes.size()
)
final XML doc;
if (nodes.isEmpty()) {
doc = xml;
} else {
final Directives dirs = new Directives();
for (final XML node : nodes) {
dirs.xpath(String.format(StXPath.INDEXED, this.xpath))
.strict(1)
.append(this.fun.apply(node));
}
doc = new XMLDocument(
new Xembler(dirs).applyQuietly(xml.inner())
);
}
final Directives dirs = new Directives();
if (!nodes.isEmpty()) {
dirs.xpath(this.xpath);
dirs.append(this.fun.apply(nodes.get(0)));
}
return new XMLDocument(
new Xembler(dirs).applyQuietly(xml.deepCopy())
);
return doc;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ SOFTWARE.
<xsl:template match="o[@base='Q.org.eolang.number' and o[1][eo:has-data(.)]]">
<xsl:variable name="bytes" select="o[1]/text()"/>
<xsl:choose>
<xsl:when test="$bytes='7F-F8-00-00-00-00-00-00' or $bytes='7F-F0-00-00-00-00-00-00' or $bytes='FF-F0-00-00-00-00-00-00'">
<xsl:when test="$bytes='7F-F8-00-00-00-00-00-00' or $bytes='7F-F0-00-00-00-00-00-00' or $bytes='FF-F0-00-00-00-00-00-00' or $bytes='FF-FF-FF-FF-FF-FF-FF-FF'">
<xsl:copy-of select="."/>
</xsl:when>
<xsl:when test="$bytes='00-00-00-00-00-00-00-00'">
Expand Down
89 changes: 55 additions & 34 deletions eo-parser/src/test/java/org/eolang/parser/StUnhexTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,14 @@

import com.jcabi.matchers.XhtmlMatchers;
import com.jcabi.xml.XMLDocument;
import com.yegor256.xsline.Shift;
import com.yegor256.xsline.Xsline;
import java.util.stream.Stream;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.Test;
import org.hamcrest.Matchers;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

/**
* Test case for {@link StUnhex}.
Expand All @@ -36,39 +41,45 @@
*/
final class StUnhexTest {

@Test
void convertsIntFromHexToEo() {
@ParameterizedTest
@MethodSource("shifts")
void convertsIntFromHexToEo(final Shift shift) {
MatcherAssert.assertThat(
EoIndentLexerTest.TO_ADD_MESSAGE,
new Xsline(new StUnhex()).pass(
new Xsline(new StUnhex(shift)).pass(
new XMLDocument(
"<p><o base='Q.org.eolang.number'><o base='Q.org.eolang.bytes'>43-70-2E-4F-30-46-73-2E</o></o></p>"
)
),
XhtmlMatchers.hasXPaths("//o[text()='72872276393407200']")
Matchers.anyOf(
XhtmlMatchers.hasXPath("//o[text()='72872276393407200']"),
XhtmlMatchers.hasXPath("//o[text()='7.28722763934072e16']")
)
);
}

@Test
void convertsMaxIntFromHexToEo() {
@ParameterizedTest
@MethodSource("shifts")
void convertsMaxIntFromHexToEo(final Shift shift) {
MatcherAssert.assertThat(
EoIndentLexerTest.TO_ADD_MESSAGE,
new Xsline(new StUnhex()).pass(
new Xsline(new StUnhex(shift)).pass(
new XMLDocument(
"<p><o base='Q.org.eolang.number'><o base='Q.org.eolang.bytes'>FF-FF-FF-FF-FF-FF-FF-FF</o></o></p>"
)
),
XhtmlMatchers.hasXPaths(
"//o[@base='Q.org.eolang.number' and @skip and o[@base='Q.org.eolang.bytes' and text()!='']]"
XhtmlMatchers.hasXPath(
"//o[@base='Q.org.eolang.number' and o[@base='Q.org.eolang.bytes' and text()!='']]"
)
);
}

@Test
void convertsStringFromHexToEo() {
@ParameterizedTest
@MethodSource("shifts")
void convertsStringFromHexToEo(final Shift shift) {
MatcherAssert.assertThat(
"String bytes must be converted to human readable string, but they didn't",
new Xsline(new StUnhex()).pass(
new Xsline(new StUnhex(shift)).pass(
new XMLDocument(
String.join(
"",
Expand All @@ -84,61 +95,71 @@ void convertsStringFromHexToEo() {
);
}

@Test
void convertsEmptyStringFromHexToEo() {
@ParameterizedTest
@MethodSource("shifts")
void convertsEmptyStringFromHexToEo(final Shift shift) {
MatcherAssert.assertThat(
EoIndentLexerTest.TO_ADD_MESSAGE,
new Xsline(new StUnhex()).pass(
new Xsline(new StUnhex(shift)).pass(
new XMLDocument(
"<p><o base='Q.org.eolang.string'><o base='Q.org.eolang.bytes'/></o></p>"
)
),
XhtmlMatchers.hasXPaths(
"//o[empty(text())]"
)
XhtmlMatchers.hasXPath("//o[empty(text())]")
);
}

@Test
void convertsStringWithDoubleSpacesFromHexToEo() {
@ParameterizedTest
@MethodSource("shifts")
void convertsStringWithDoubleSpacesFromHexToEo(final Shift shift) {
MatcherAssert.assertThat(
EoIndentLexerTest.TO_ADD_MESSAGE,
new Xsline(new StUnhex()).pass(
new Xsline(new StUnhex(shift)).pass(
new XMLDocument(
"<o base=\"Q.org.eolang.string\"><o base=\"Q.org.eolang.bytes\">7A-0A-20-20-79-0A-20-78</o></o>"
)
),
XhtmlMatchers.hasXPaths(
"//o[text()='\"z\\n y\\n x\"']"
)
XhtmlMatchers.hasXPath("//o[text()='\"z\\n y\\n x\"']")
);
}

@Test
void convertsNegativeZeroFromHexToEo() {
@ParameterizedTest
@MethodSource("shifts")
void convertsNegativeZeroFromHexToEo(final Shift shift) {
MatcherAssert.assertThat(
EoIndentLexerTest.TO_ADD_MESSAGE,
new Xsline(new StUnhex()).pass(
new Xsline(new StUnhex(shift)).pass(
new XMLDocument(
"<o base='Q.org.eolang.number'><o base='Q.org.eolang.bytes'>80-00-00-00-00-00-00-00</o></o>"
)
),
XhtmlMatchers.hasXPaths("//o[text()='-0']")
XhtmlMatchers.hasXPath("//o[text()='-0']")
);
}

@Test
void convertsFloatFromHexToEo() {
@ParameterizedTest
@MethodSource("shifts")
void convertsFloatFromHexToEo(final Shift shift) {
MatcherAssert.assertThat(
EoIndentLexerTest.TO_ADD_MESSAGE,
new Xsline(new StUnhex()).pass(
new Xsline(new StUnhex(shift)).pass(
new XMLDocument(
"<p><o base='Q.org.eolang.number'><o base='Q.org.eolang.bytes'>41-42-43-67-AE-CD-3E-FD</o></o></p>"
)
),
XhtmlMatchers.hasXPaths(
"//o[text()='2393807.3656386123']"
Matchers.anyOf(
XhtmlMatchers.hasXPath("//o[text()='2393807.3656386123']"),
XhtmlMatchers.hasXPath("//o[text()='2.3938073656386123e6']")
)
);
}

@SuppressWarnings("PMD.UnusedPrivateMethod")
private static Stream<Arguments> shifts() {
return Stream.of(
Arguments.of(StUnhex.XNAV),
Arguments.of(StUnhex.XPATH),
Arguments.of(StUnhex.XSL)
);
}
}
2 changes: 1 addition & 1 deletion eo-parser/src/test/java/org/eolang/parser/StXPathTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void modifiesSimpleNode() {
new Xsline(
new StEndless(
new StXPath(
"(//x[@a and not(@b)])[1]",
"//x[@a and not(@b)]",
xml -> new Directives().attr(
"b", xml.xpath("text()").get(0)
)
Expand Down

0 comments on commit 176fe81

Please sign in to comment.