Skip to content

Commit e77078b

Browse files
committed
Sync with underscore-java.
1 parent 7a84c8e commit e77078b

File tree

5 files changed

+215
-35
lines changed

5 files changed

+215
-35
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ jdk:
77
matrix:
88
include:
99
- jdk: openjdk12
10+
before_install:
11+
- rm "${JAVA_HOME}/lib/security/cacerts"
12+
- ln -s /etc/ssl/certs/java/cacerts "${JAVA_HOME}/lib/security/cacerts"
1013

1114
script:
1215
- mvn -B clean test jacoco:report

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

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,11 @@ private static <T> T baseGet(final Map<String, Object> object, final String path
13571357
Object localObject = object;
13581358
while (localObject != null && index < length) {
13591359
if (localObject instanceof Map) {
1360+
Map.Entry mapEntry = getMapEntry((Map) localObject);
1361+
if (mapEntry != null && "#item".equals(mapEntry.getKey())) {
1362+
localObject = mapEntry.getValue();
1363+
continue;
1364+
}
13601365
localObject = ((Map) localObject).get(paths.get(index));
13611366
} else if (localObject instanceof List) {
13621367
localObject = ((List) localObject).get(Integer.parseInt(paths.get(index)));
@@ -1371,6 +1376,10 @@ private static <T> T baseGet(final Map<String, Object> object, final String path
13711376
return null;
13721377
}
13731378

1379+
private static Map.Entry getMapEntry(Map map) {
1380+
return map.isEmpty() ? null : (Map.Entry) map.entrySet().iterator().next();
1381+
}
1382+
13741383
public static <T> T get(final Map<String, Object> object, final String path) {
13751384
return baseGet(object, path);
13761385
}
@@ -1743,6 +1752,100 @@ public static <T> List<List<T>> createPermutationWithRepetition(final List<T> li
17431752
return result;
17441753
}
17451754

1755+
public static class Status {
1756+
private final int key;
1757+
private final int x;
1758+
private final int y;
1759+
public Status(int key, int x, int y) {
1760+
this.key = key;
1761+
this.x = x;
1762+
this.y = y;
1763+
}
1764+
public int getKey() {
1765+
return key;
1766+
}
1767+
public int getX() {
1768+
return x;
1769+
}
1770+
public int getY() {
1771+
return y;
1772+
}
1773+
}
1774+
1775+
public static List<Status> shortestPathAllKeys(String[] grid) {
1776+
int success = 0;
1777+
int startI = 0;
1778+
int startJ = 0;
1779+
int rows = grid.length;
1780+
int cols = grid[0].length();
1781+
List<Status> result = newArrayList();
1782+
for (int i = 0; i < rows; i++) {
1783+
for (int j = 0; j < cols; j++) {
1784+
char c = grid[i].charAt(j);
1785+
if (c >= 'A' && c <= 'F') {
1786+
success |= 1 << (c - 'A');
1787+
}
1788+
if (c == '@') {
1789+
startI = i;
1790+
startJ = j;
1791+
}
1792+
}
1793+
}
1794+
int[][][] dist = new int[1 << 6][rows][cols];
1795+
for (int i = 0; i < dist.length; i++) {
1796+
for (int j = 0; j < dist[0].length; j++) {
1797+
for (int k = 0; k < dist[0][0].length; k++) {
1798+
dist[i][j][k] = Integer.MAX_VALUE;
1799+
}
1800+
}
1801+
}
1802+
Queue<Status> queue = new LinkedList<Status>();
1803+
queue.offer(new Status(0, startI, startJ));
1804+
dist[0][startI][startJ] = 0;
1805+
return scanDirs(queue, success, result, rows, cols, grid, dist);
1806+
}
1807+
1808+
private static List<Status> scanDirs(Queue<Status> queue, int success, List<Status> result,
1809+
int rows, int cols, String[] grid, int[][][] dist) {
1810+
int path = 0;
1811+
int[][] dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
1812+
while (!queue.isEmpty()) {
1813+
int size = queue.size();
1814+
while (size-- > 0) {
1815+
Status status = queue.poll();
1816+
int key = status.getKey();
1817+
int x = status.getX();
1818+
int y = status.getY();
1819+
if (key == success) {
1820+
return result;
1821+
}
1822+
for (int[] dir : dirs) {
1823+
int xx = x + dir[0];
1824+
int yy = y + dir[1];
1825+
if (xx >= 0 && xx < rows && yy >= 0 && yy < cols && grid[xx].charAt(yy) != '#') {
1826+
int nextKey = key;
1827+
char c = grid[xx].charAt(yy);
1828+
if (c >= 'a' && c <= 'f') {
1829+
nextKey = key | (1 << (c - 'a'));
1830+
}
1831+
if (c >= 'A' && c <= 'F' && (nextKey & (1 << (c - 'A'))) == 0) {
1832+
continue;
1833+
}
1834+
if (path + 1 < dist[nextKey][xx][yy]) {
1835+
dist[nextKey][xx][yy] = path + 1;
1836+
queue.offer(new Status(nextKey, xx, yy));
1837+
}
1838+
}
1839+
}
1840+
}
1841+
path++;
1842+
if (!queue.isEmpty()) {
1843+
result.add(queue.element());
1844+
}
1845+
}
1846+
return result;
1847+
}
1848+
17461849
@SuppressWarnings("unchecked")
17471850
public List<List<T>> createPermutationWithRepetition(final int permutationLength) {
17481851
return createPermutationWithRepetition((List<T>) value(), permutationLength);
@@ -1795,6 +1898,10 @@ public static Object fromXml(final String xml) {
17951898
return Xml.fromXml(xml);
17961899
}
17971900

1901+
public static Object fromXml(final String xml, final Xml.FromType fromType) {
1902+
return Xml.fromXml(xml, fromType);
1903+
}
1904+
17981905
public static Object fromXmlMakeArrays(final String xml) {
17991906
return Xml.fromXmlMakeArrays(xml);
18001907
}

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

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -408,14 +408,14 @@ public static void writeXml(final Map map, final String name, final XmlStringBui
408408
final Map.Entry entry = entries.get(index);
409409
final boolean addNewLine = index < entries.size() - 1
410410
&& !String.valueOf(entries.get(index + 1).getKey()).startsWith(TEXT);
411-
if (String.valueOf(entry.getKey()).startsWith("-") && (entry.getValue() instanceof String)) {
411+
if (String.valueOf(entry.getKey()).startsWith("-") && entry.getValue() instanceof String) {
412412
attrs.add(" " + XmlValue.escapeName(String.valueOf(entry.getKey()).substring(1), namespaces)
413413
+ "=\"" + XmlValue.escape(String.valueOf(entry.getValue())).replace("\"", QUOT) + "\"");
414414
} else if (String.valueOf(entry.getKey()).startsWith(TEXT)) {
415415
addText(entry, elems, identStep, ident, attrKeys, attrs);
416416
} else {
417-
boolean localParentTextFound = (!elems.isEmpty()
418-
&& elems.get(elems.size() - 1) instanceof XmlStringBuilderText) || parentTextFound;
417+
boolean localParentTextFound = !elems.isEmpty()
418+
&& elems.get(elems.size() - 1) instanceof XmlStringBuilderText || parentTextFound;
419419
processElements(entry, identStep, ident, addNewLine, elems, namespaces, localParentTextFound);
420420
}
421421
}
@@ -963,11 +963,12 @@ public static String toXml(Map map) {
963963
}
964964

965965
@SuppressWarnings("unchecked")
966-
private static Object getValue(final Object value) {
966+
private static Object getValue(final Object value, final FromType fromType) {
967967
final Object localValue;
968968
if (value instanceof Map && ((Map<String, Object>) value).entrySet().size() == 1) {
969969
final Map.Entry<String, Object> entry = ((Map<String, Object>) value).entrySet().iterator().next();
970-
if (TEXT.equals(entry.getKey()) || entry.getKey().equals(ELEMENT_TEXT)) {
970+
if (TEXT.equals(entry.getKey())
971+
|| (fromType == FromType.FOR_CONVERT && ELEMENT_TEXT.equals(entry.getKey()))) {
971972
localValue = entry.getValue();
972973
} else {
973974
localValue = value;
@@ -1000,7 +1001,8 @@ private static Object stringToNumber(String number) {
10001001
private static Object createMap(final org.w3c.dom.Node node,
10011002
final BiFunction<Object, Set<String>, String> elementMapper,
10021003
final Function<Object, Object> nodeMapper, final Map<String, Object> attrMap,
1003-
final int[] uniqueIds, final String source, final int[] sourceIndex, final Set<String> namespaces) {
1004+
final int[] uniqueIds, final String source, final int[] sourceIndex, final Set<String> namespaces,
1005+
final FromType fromType) {
10041006
final Map<String, Object> map = U.newLinkedHashMap();
10051007
map.putAll(attrMap);
10061008
final org.w3c.dom.NodeList nodeList = node.getChildNodes();
@@ -1016,7 +1018,7 @@ private static Object createMap(final org.w3c.dom.Node node,
10161018
if (currentNode.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
10171019
sourceIndex[0] = source.indexOf("<" + name, sourceIndex[0]) + name.length() + 1;
10181020
value = addElement(sourceIndex, source, elementMapper, nodeMapper,
1019-
uniqueIds, currentNode, namespaces);
1021+
uniqueIds, currentNode, namespaces, fromType);
10201022
} else {
10211023
if (COMMENT.equals(name)) {
10221024
sourceIndex[0] = source.indexOf("-->", sourceIndex[0]) + 3;
@@ -1030,7 +1032,7 @@ private static Object createMap(final org.w3c.dom.Node node,
10301032
|| currentNode.getNodeType() == org.w3c.dom.Node.DOCUMENT_TYPE_NODE) {
10311033
continue;
10321034
}
1033-
addNodeValue(map, name, value, elementMapper, nodeMapper, uniqueIds, namespaces);
1035+
addNodeValue(map, name, value, elementMapper, nodeMapper, uniqueIds, namespaces, fromType);
10341036
}
10351037
return checkNumberAndBoolean(map, node.getNodeName());
10361038
}
@@ -1064,8 +1066,8 @@ private static Object checkArray(final Map<String, Object> map, final String nam
10641066
final Map<String, Object> localMap4 = (Map) ((LinkedHashMap) localMap).clone();
10651067
localMap4.remove(ARRAY);
10661068
object = name.equals(XmlValue.getMapKey(localMap4))
1067-
? U.newArrayList(Arrays.asList(getValue(XmlValue.getMapValue(localMap4))))
1068-
: U.newArrayList(Arrays.asList(getValue(localMap4)));
1069+
? U.newArrayList(Arrays.asList(getValue(XmlValue.getMapValue(localMap4), FromType.FOR_CONVERT)))
1070+
: U.newArrayList(Arrays.asList(getValue(localMap4, FromType.FOR_CONVERT)));
10691071
} else {
10701072
object = localMap;
10711073
}
@@ -1114,7 +1116,8 @@ private static Map<String, Object> checkNullAndString(final Map<String, Object>
11141116
private static Object addElement(final int[] sourceIndex, final String source,
11151117
final BiFunction<Object, Set<String>, String> elementMapper,
11161118
final Function<Object, Object> nodeMapper, final int[] uniqueIds,
1117-
final org.w3c.dom.Node currentNode, final Set<String> namespaces) {
1119+
final org.w3c.dom.Node currentNode, final Set<String> namespaces,
1120+
final FromType fromType) {
11181121
final Map<String, Object> attrMapLocal = U.newLinkedHashMap();
11191122
if (currentNode.getAttributes().getLength() > 0) {
11201123
final java.util.regex.Matcher matcher = ATTRS.matcher(getAttributes(sourceIndex[0], source));
@@ -1126,7 +1129,7 @@ private static Object addElement(final int[] sourceIndex, final String source,
11261129
matcher.reset();
11271130
while (matcher.find()) {
11281131
addNodeValue(attrMapLocal, '-' + matcher.group(1), matcher.group(2),
1129-
elementMapper, nodeMapper, uniqueIds, namespaces);
1132+
elementMapper, nodeMapper, uniqueIds, namespaces, fromType);
11301133
}
11311134
}
11321135
if (getAttributes(sourceIndex[0], source).endsWith("/")
@@ -1136,7 +1139,7 @@ private static Object addElement(final int[] sourceIndex, final String source,
11361139
attrMapLocal.put(SELF_CLOSING, TRUE);
11371140
}
11381141
return createMap(currentNode, elementMapper, nodeMapper, attrMapLocal, uniqueIds, source,
1139-
sourceIndex, namespaces);
1142+
sourceIndex, namespaces, fromType);
11401143
}
11411144

11421145
static String getAttributes(final int sourceIndex, final String source) {
@@ -1209,39 +1212,39 @@ private static String unescapeName(final String name) {
12091212
@SuppressWarnings("unchecked")
12101213
private static void addNodeValue(final Map<String, Object> map, final String name, final Object value,
12111214
final BiFunction<Object, Set<String>, String> elementMapper, final Function<Object, Object> nodeMapper,
1212-
final int[] uniqueIds, final Set<String> namespaces) {
1215+
final int[] uniqueIds, final Set<String> namespaces, final FromType fromType) {
12131216
final String elementName = unescapeName(elementMapper.apply(name, namespaces));
12141217
if (map.containsKey(elementName)) {
12151218
if (TEXT.equals(elementName)) {
1216-
map.put(elementName + uniqueIds[0], nodeMapper.apply(getValue(value)));
1219+
map.put(elementName + uniqueIds[0], nodeMapper.apply(getValue(value, fromType)));
12171220
uniqueIds[0] += 1;
12181221
} else if (COMMENT.equals(elementName)) {
1219-
map.put(elementName + uniqueIds[1], nodeMapper.apply(getValue(value)));
1222+
map.put(elementName + uniqueIds[1], nodeMapper.apply(getValue(value, fromType)));
12201223
uniqueIds[1] += 1;
12211224
} else if (CDATA.equals(elementName)) {
1222-
map.put(elementName + uniqueIds[2], nodeMapper.apply(getValue(value)));
1225+
map.put(elementName + uniqueIds[2], nodeMapper.apply(getValue(value, fromType)));
12231226
uniqueIds[2] += 1;
12241227
} else {
12251228
final Object object = map.get(elementName);
12261229
if (object instanceof List) {
1227-
addText(map, elementName, (List<Object>) object, value);
1230+
addText(map, elementName, (List<Object>) object, value, fromType);
12281231
} else {
12291232
final List<Object> objects = U.newArrayList();
12301233
objects.add(object);
1231-
addText(map, elementName, objects, value);
1234+
addText(map, elementName, objects, value, fromType);
12321235
map.put(elementName, objects);
12331236
}
12341237
}
12351238
} else {
12361239
if (elementName != null) {
1237-
map.put(elementName, nodeMapper.apply(getValue(value)));
1240+
map.put(elementName, nodeMapper.apply(getValue(value, fromType)));
12381241
}
12391242
}
12401243
}
12411244

12421245
@SuppressWarnings("unchecked")
12431246
private static void addText(final Map<String, Object> map, final String name, final List<Object> objects,
1244-
final Object value) {
1247+
final Object value, final FromType fromType) {
12451248
int lastIndex = map.size() - 1;
12461249
final int index = objects.size();
12471250
while (true) {
@@ -1256,7 +1259,7 @@ private static void addText(final Map<String, Object> map, final String name, fi
12561259
objects.add(index, item);
12571260
lastIndex -= 1;
12581261
}
1259-
final Object newValue = getValue(value);
1262+
final Object newValue = getValue(value, fromType);
12601263
if (newValue instanceof List) {
12611264
objects.add(((List) newValue).get(0));
12621265
} else {
@@ -1266,6 +1269,16 @@ private static void addText(final Map<String, Object> map, final String name, fi
12661269

12671270
@SuppressWarnings("unchecked")
12681271
public static Object fromXml(final String xml) {
1272+
return fromXml(xml, FromType.FOR_CONVERT);
1273+
}
1274+
1275+
public enum FromType {
1276+
FOR_CONVERT,
1277+
FOR_FORMAT
1278+
}
1279+
1280+
@SuppressWarnings("unchecked")
1281+
public static Object fromXml(final String xml, final FromType fromType) {
12691282
if (xml == null) {
12701283
return null;
12711284
}
@@ -1280,8 +1293,8 @@ public Object apply(Object object) {
12801293
return object;
12811294
}
12821295
}, Collections.<String, Object>emptyMap(), new int[] {1, 1, 1}, xml, new int[] {0},
1283-
U.<String>newLinkedHashSet());
1284-
if (checkResult(xml, document, result)) {
1296+
U.<String>newLinkedHashSet(), fromType);
1297+
if (checkResult(xml, document, result, fromType)) {
12851298
return ((Map.Entry) ((Map) result).entrySet().iterator().next()).getValue();
12861299
}
12871300
return result;
@@ -1291,7 +1304,8 @@ public Object apply(Object object) {
12911304
}
12921305

12931306
@SuppressWarnings("unchecked")
1294-
private static boolean checkResult(final String xml, org.w3c.dom.Document document, final Object result) {
1307+
private static boolean checkResult(final String xml, org.w3c.dom.Document document, final Object result,
1308+
final FromType fromType) {
12951309
final Map<String, String> headerAttributes = getHeaderAttributes(xml);
12961310
if (document.getXmlEncoding() != null && !"UTF-8".equalsIgnoreCase(document.getXmlEncoding())) {
12971311
((Map) result).put(ENCODING, document.getXmlEncoding());
@@ -1300,7 +1314,8 @@ private static boolean checkResult(final String xml, org.w3c.dom.Document docume
13001314
}
13011315
} else if (headerAttributes.containsKey(STANDALONE.substring(1))) {
13021316
((Map) result).put(STANDALONE, headerAttributes.get(STANDALONE.substring(1)));
1303-
} else if (((Map.Entry) ((Map) result).entrySet().iterator().next()).getKey().equals("root")
1317+
} else if (fromType == FromType.FOR_CONVERT
1318+
&& ((Map.Entry) ((Map) result).entrySet().iterator().next()).getKey().equals("root")
13041319
&& (((Map.Entry) ((Map) result).entrySet().iterator().next()).getValue() instanceof List
13051320
|| ((Map.Entry) ((Map) result).entrySet().iterator().next()).getValue() instanceof Map)) {
13061321
if (xml.startsWith(XML_HEADER)) {
@@ -1369,8 +1384,8 @@ public Object apply(Object object) {
13691384
return object instanceof List ? object : U.newArrayList(Arrays.asList(object));
13701385
}
13711386
}, Collections.<String, Object>emptyMap(), new int[] {1, 1, 1}, xml, new int[] {0},
1372-
U.<String>newLinkedHashSet());
1373-
if (checkResult(xml, document, result)) {
1387+
U.<String>newLinkedHashSet(), FromType.FOR_CONVERT);
1388+
if (checkResult(xml, document, result, FromType.FOR_CONVERT)) {
13741389
return ((Map.Entry) ((Map) result).entrySet().iterator().next()).getValue();
13751390
}
13761391
return result;
@@ -1388,8 +1403,8 @@ public Object apply(Object object) {
13881403
return object;
13891404
}
13901405
}, Collections.<String, Object>emptyMap(), new int[]{1, 1, 1}, xml, new int[]{0},
1391-
U.<String>newLinkedHashSet());
1392-
if (checkResult(xml, document, result)) {
1406+
U.<String>newLinkedHashSet(), FromType.FOR_CONVERT);
1407+
if (checkResult(xml, document, result, FromType.FOR_CONVERT)) {
13931408
return ((Map.Entry) ((Map) result).entrySet().iterator().next()).getValue();
13941409
}
13951410
return result;
@@ -1445,11 +1460,8 @@ public String apply(Object object, Set<String> namespaces) {
14451460

14461461
@SuppressWarnings("unchecked")
14471462
public static String formatXml(String xml, XmlStringBuilder.Step identStep) {
1448-
Object result = fromXml(xml);
1449-
if (result instanceof Map) {
1450-
return toXml((Map) result, identStep);
1451-
}
1452-
return toXml((List) result, identStep);
1463+
Object result = fromXml(xml, FromType.FOR_FORMAT);
1464+
return toXml((Map) result, identStep);
14531465
}
14541466

14551467
public static String formatXml(String xml) {

0 commit comments

Comments
 (0)