Skip to content

Commit 167416a

Browse files
committed
Sync with underscore-java.
1 parent fc4d182 commit 167416a

File tree

3 files changed

+176
-2
lines changed

3 files changed

+176
-2
lines changed

src/main/java/com/github/underscore/U.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@
5353
import java.util.function.Function;
5454
import java.util.function.Predicate;
5555
import java.util.zip.GZIPInputStream;
56+
import javax.xml.xpath.XPath;
57+
import javax.xml.xpath.XPathConstants;
58+
import javax.xml.xpath.XPathFactory;
59+
import org.w3c.dom.NodeList;
5660

5761
@SuppressWarnings({
5862
"java:S135",
@@ -1785,6 +1789,40 @@ public static <T> T get(final Map<String, Object> object, final List<String> pat
17851789
return baseGetOrSetOrRemove(object, paths, null, OperationType.GET);
17861790
}
17871791

1792+
public static String selectToken(final Map<String, Object> object, final String expression) {
1793+
final String xml = toXml(object);
1794+
try {
1795+
final XPath xPath = XPathFactory.newInstance().newXPath();
1796+
final org.w3c.dom.Document document = Xml.Document.createDocument(xml);
1797+
final NodeList nodes =
1798+
(NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
1799+
if (nodes.getLength() == 0) {
1800+
return null;
1801+
}
1802+
return nodes.item(0).getNodeValue();
1803+
} catch (Exception ex) {
1804+
throw new IllegalArgumentException(ex);
1805+
}
1806+
}
1807+
1808+
public static List<String> selectTokens(
1809+
final Map<String, Object> object, final String expression) {
1810+
final String xml = toXml(object);
1811+
try {
1812+
final XPath xPath = XPathFactory.newInstance().newXPath();
1813+
final org.w3c.dom.Document document = Xml.Document.createDocument(xml);
1814+
final NodeList nodes =
1815+
(NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
1816+
final List<String> result = new ArrayList<>();
1817+
for (int i = 0; i < nodes.getLength(); i++) {
1818+
result.add(nodes.item(i).getNodeValue());
1819+
}
1820+
return result;
1821+
} catch (Exception ex) {
1822+
throw new IllegalArgumentException(ex);
1823+
}
1824+
}
1825+
17881826
public static <T> T set(final Map<String, Object> object, final String path, Object value) {
17891827
return set(object, stringToPath(path), value);
17901828
}

src/main/java/com/github/underscore/Xml.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,8 +1776,10 @@ public org.xml.sax.InputSource resolveEntity(String publicId, String systemId) {
17761776
}
17771777
}
17781778

1779-
private static class Document {
1780-
private static org.w3c.dom.Document createDocument(final String xml)
1779+
protected static class Document {
1780+
private Document() {}
1781+
1782+
public static org.w3c.dom.Document createDocument(final String xml)
17811783
throws java.io.IOException, javax.xml.parsers.ParserConfigurationException,
17821784
org.xml.sax.SAXException {
17831785
final javax.xml.parsers.DocumentBuilderFactory factory =

src/test/java/com/github/underscore/LodashTest.java

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,140 @@ void getNotFound() {
471471
"a[0].d.c"));
472472
}
473473

474+
@Test
475+
void selectTokenGetBookTitleWrittenAfter2001() {
476+
String inventory =
477+
"{\n"
478+
+ " \"inventory\": {\n"
479+
+ " \"#comment\": \"Test is test comment\",\n"
480+
+ " \"book\": [\n"
481+
+ " {\n"
482+
+ " \"-year\": \"2000\",\n"
483+
+ " \"title\": \"Snow Crash\",\n"
484+
+ " \"author\": \"Neal Stephenson\",\n"
485+
+ " \"publisher\": \"Spectra\",\n"
486+
+ " \"isbn\": \"0553380958\",\n"
487+
+ " \"price\": \"14.95\"\n"
488+
+ " },\n"
489+
+ " {\n"
490+
+ " \"-year\": \"2005\",\n"
491+
+ " \"title\": \"Burning Tower\",\n"
492+
+ " \"author\": [\n"
493+
+ " \"Larry Niven\",\n"
494+
+ " \"Jerry Pournelle\"\n"
495+
+ " ],\n"
496+
+ " \"publisher\": \"Pocket\",\n"
497+
+ " \"isbn\": \"0743416910\",\n"
498+
+ " \"price\": \"5.99\"\n"
499+
+ " },\n"
500+
+ " {\n"
501+
+ " \"-year\": \"1995\",\n"
502+
+ " \"title\": \"Zodiac\",\n"
503+
+ " \"author\": \"Neal Stephenson\",\n"
504+
+ " \"publisher\": \"Spectra\",\n"
505+
+ " \"isbn\": \"0553573862\",\n"
506+
+ " \"price\": \"7.50\"\n"
507+
+ " }\n"
508+
+ " ]\n"
509+
+ " }\n"
510+
+ "}";
511+
Map<String, Object> objectMap = U.fromJsonMap(inventory);
512+
assertEquals("Burning Tower", U.selectToken(objectMap, "//book[@year>2001]/title/text()"));
513+
assertNull(U.selectToken(objectMap, "//book[@year>2001]/title1/text()"));
514+
assertThrows(IllegalArgumentException.class, () -> U.selectToken(objectMap, "\\"));
515+
}
516+
517+
@Test
518+
void selectTokenManufacturerWithName() {
519+
String json =
520+
"{\n"
521+
+ " \"Stores\": [\n"
522+
+ " \"Lambton Quay\",\n"
523+
+ " \"Willis Street\"\n"
524+
+ " ],\n"
525+
+ " \"Manufacturers\": [\n"
526+
+ " {\n"
527+
+ " \"Name\": \"Acme Co\",\n"
528+
+ " \"Products\": [\n"
529+
+ " {\n"
530+
+ " \"Name\": \"Anvil\",\n"
531+
+ " \"Price\": 50\n"
532+
+ " }\n"
533+
+ " ]\n"
534+
+ " },\n"
535+
+ " {\n"
536+
+ " \"Name\": \"Contoso\",\n"
537+
+ " \"Products\": [\n"
538+
+ " {\n"
539+
+ " \"Name\": \"Elbow Grease\",\n"
540+
+ " \"Price\": 99.95\n"
541+
+ " },\n"
542+
+ " {\n"
543+
+ " \"Name\": \"Headlight Fluid\",\n"
544+
+ " \"Price\": 4\n"
545+
+ " }\n"
546+
+ " ]\n"
547+
+ " }\n"
548+
+ " ]\n"
549+
+ "}";
550+
Map<String, Object> objectMap = U.fromJsonMap(json);
551+
assertEquals(
552+
"Anvil",
553+
U.selectToken(objectMap, "//Manufacturers[Name='Acme Co']/Products/Name/text()"));
554+
assertEquals(
555+
"50",
556+
U.selectToken(objectMap, "//Manufacturers[Name='Acme Co']/Products/Price/text()"));
557+
assertEquals("Anvil", U.selectToken(objectMap, "//Products[Price>=50]/Name/text()"));
558+
assertEquals(
559+
Arrays.asList("Anvil", "Elbow Grease"),
560+
U.selectTokens(objectMap, "//Products[Price>=50]/Name/text()"));
561+
}
562+
563+
@Test
564+
void selectTokensGetAllWriters() {
565+
String inventory =
566+
"{\n"
567+
+ " \"inventory\": {\n"
568+
+ " \"#comment\": \"Test is test comment\",\n"
569+
+ " \"book\": [\n"
570+
+ " {\n"
571+
+ " \"-year\": \"2000\",\n"
572+
+ " \"title\": \"Snow Crash\",\n"
573+
+ " \"author\": \"Neal Stephenson\",\n"
574+
+ " \"publisher\": \"Spectra\",\n"
575+
+ " \"isbn\": \"0553380958\",\n"
576+
+ " \"price\": \"14.95\"\n"
577+
+ " },\n"
578+
+ " {\n"
579+
+ " \"-year\": \"2005\",\n"
580+
+ " \"title\": \"Burning Tower\",\n"
581+
+ " \"author\": [\n"
582+
+ " \"Larry Niven\",\n"
583+
+ " \"Jerry Pournelle\"\n"
584+
+ " ],\n"
585+
+ " \"publisher\": \"Pocket\",\n"
586+
+ " \"isbn\": \"0743416910\",\n"
587+
+ " \"price\": \"5.99\"\n"
588+
+ " },\n"
589+
+ " {\n"
590+
+ " \"-year\": \"1995\",\n"
591+
+ " \"title\": \"Zodiac\",\n"
592+
+ " \"author\": \"Neal Stephenson\",\n"
593+
+ " \"publisher\": \"Spectra\",\n"
594+
+ " \"isbn\": \"0553573862\",\n"
595+
+ " \"price\": \"7.50\"\n"
596+
+ " }\n"
597+
+ " ]\n"
598+
+ " }\n"
599+
+ "}";
600+
Map<String, Object> objectMap = U.fromJsonMap(inventory);
601+
assertEquals(
602+
"[Neal Stephenson, Larry Niven, Jerry Pournelle, Neal Stephenson]",
603+
U.selectTokens(objectMap, "//book/author/text()").toString());
604+
assertEquals("[]", U.selectTokens(objectMap, "//book/author1/text()").toString());
605+
assertThrows(IllegalArgumentException.class, () -> U.selectTokens(objectMap, "\\"));
606+
}
607+
474608
@SuppressWarnings("unchecked")
475609
@Test
476610
void fetchGet() {

0 commit comments

Comments
 (0)