Skip to content

Commit 78b102b

Browse files
committed
Sync with underscore-java
1 parent 199d0d9 commit 78b102b

File tree

7 files changed

+536
-13
lines changed

7 files changed

+536
-13
lines changed

pom-pack17.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
<option>-keep public class com.github.underscore.Xml$XmlStringBuilder { *; }</option>
116116
<option>-keep public class com.github.underscore.Xml$FromType { *; }</option>
117117
<option>-keep public class com.github.underscore.Xml$ArrayTrue { *; }</option>
118+
<option>-keep public class com.github.underscore.XmlBuilder { *; }</option>
118119
<option>-keepclassmembers class * { *** newArrayList(); *** newLinkedHashSet(); *** newHashSet(java.lang.Iterable); *** newLinkedHashMap(); }</option>
119120
<option>-dontnote com.github.underscore.*$ClassForName</option>
120121
<option>-dontnote com.github.underscore.*$OperationType</option>

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

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import java.io.FileInputStream;
2828
import java.io.FileOutputStream;
2929
import java.io.IOException;
30+
import java.net.URI;
31+
import java.net.URISyntaxException;
3032
import java.net.URL;
3133
import java.nio.channels.Channels;
3234
import java.nio.channels.ReadableByteChannel;
@@ -1722,6 +1724,7 @@ public static List<String> stringToPath(final String string) {
17221724
private enum OperationType {
17231725
GET,
17241726
SET,
1727+
UPDATE,
17251728
REMOVE
17261729
}
17271730

@@ -1766,9 +1769,10 @@ private static <T> T baseGetOrSetOrRemove(
17661769
@SuppressWarnings("unchecked")
17671770
private static void checkSetAndRemove(
17681771
Object value, OperationType operationType, Object savedLocalObject, String savedPath) {
1769-
if (operationType == OperationType.SET) {
1772+
if (operationType == OperationType.SET || operationType == OperationType.UPDATE) {
17701773
if (savedLocalObject instanceof Map) {
1771-
((Map) savedLocalObject).put(savedPath, value);
1774+
checkSetOrUpdate(
1775+
value, operationType, (Map<String, Object>) savedLocalObject, savedPath);
17721776
} else {
17731777
((List) savedLocalObject).set(Integer.parseInt(savedPath), value);
17741778
}
@@ -1781,6 +1785,18 @@ private static void checkSetAndRemove(
17811785
}
17821786
}
17831787

1788+
private static void checkSetOrUpdate(
1789+
Object value,
1790+
OperationType operationType,
1791+
Map<String, Object> savedLocalObject,
1792+
String savedPath) {
1793+
if (operationType == OperationType.UPDATE && savedLocalObject.containsKey(savedPath)) {
1794+
savedLocalObject.put(Underscore.uniqueId(savedPath), value);
1795+
} else {
1796+
savedLocalObject.put(savedPath, value);
1797+
}
1798+
}
1799+
17841800
private static Map.Entry getMapEntry(Map map) {
17851801
return map.isEmpty() ? null : (Map.Entry) map.entrySet().iterator().next();
17861802
}
@@ -1836,6 +1852,15 @@ public static <T> T set(
18361852
return baseGetOrSetOrRemove(object, paths, value, OperationType.SET);
18371853
}
18381854

1855+
public static <T> T update(final Map<String, Object> object, final String path, Object value) {
1856+
return update(object, stringToPath(path), value);
1857+
}
1858+
1859+
public static <T> T update(
1860+
final Map<String, Object> object, final List<String> paths, Object value) {
1861+
return baseGetOrSetOrRemove(object, paths, value, OperationType.UPDATE);
1862+
}
1863+
18391864
public static <T> T remove(final Map<String, Object> object, final String path) {
18401865
return remove(object, stringToPath(path));
18411866
}
@@ -2025,8 +2050,9 @@ public Map<String, Object> xmlMap() {
20252050
}
20262051
}
20272052

2028-
public static long downloadUrl(final String url, final String fileName) throws IOException {
2029-
final URL website = new URL(url);
2053+
public static long downloadUrl(final String url, final String fileName)
2054+
throws IOException, URISyntaxException {
2055+
final URL website = new URI(url).toURL();
20302056
try (ReadableByteChannel rbc = Channels.newChannel(website.openStream());
20312057
final FileOutputStream fos = new FileOutputStream(fileName)) {
20322058
return fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
@@ -2192,7 +2218,7 @@ public static FetchResponse fetch(
21922218
final Integer connectTimeout,
21932219
final Integer readTimeout) {
21942220
try {
2195-
final java.net.URL localUrl = new java.net.URL(url);
2221+
final java.net.URL localUrl = new java.net.URI(url).toURL();
21962222
final java.net.HttpURLConnection connection =
21972223
(java.net.HttpURLConnection) localUrl.openConnection();
21982224
setupConnection(connection, method, headerFields, connectTimeout, readTimeout);
@@ -2222,7 +2248,7 @@ public static FetchResponse fetch(
22222248
responseCode,
22232249
connection.getHeaderFields(),
22242250
result);
2225-
} catch (java.io.IOException ex) {
2251+
} catch (java.io.IOException | java.net.URISyntaxException ex) {
22262252
throw new UnsupportedOperationException(ex);
22272253
}
22282254
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,7 +1193,7 @@ private static void checkLocalMap(
11931193
|| localMap2.size() != 1
11941194
|| XmlValue.getMapKey(localMap2).startsWith("-")
11951195
|| XmlValue.getMapValue(localMap2) instanceof List) {
1196-
if ("root".equals(XmlValue.getMapKey(localMap2))) {
1196+
if (ROOT.equals(XmlValue.getMapKey(localMap2))) {
11971197
writeArray((List) XmlValue.getMapValue(localMap2), builder, arrayTrue);
11981198
} else {
11991199
XmlObject.writeXml(
@@ -1935,6 +1935,6 @@ public static String changeXmlEncoding(
19351935
}
19361936

19371937
public static String changeXmlEncoding(String xml, String encoding) {
1938-
return changeXmlEncoding(xml, XmlStringBuilder.Step.THREE_SPACES, encoding);
1938+
return changeXmlEncoding(xml, XmlStringBuilder.Step.TWO_SPACES, encoding);
19391939
}
19401940
}
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright 2015-2023 Valentyn Kolesnikov
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
package com.github.underscore;
25+
26+
import java.util.ArrayList;
27+
import java.util.LinkedHashMap;
28+
import java.util.List;
29+
import java.util.Map;
30+
31+
public class XmlBuilder {
32+
private static final String SELF_CLOSING = "-self-closing";
33+
private static final String TRUE = "true";
34+
private final Map<String, Object> data;
35+
private String path;
36+
private String savedPath;
37+
38+
XmlBuilder(String rootName) {
39+
data = new LinkedHashMap<>();
40+
Map<String, Object> value = new LinkedHashMap<>();
41+
value.put(SELF_CLOSING, TRUE);
42+
data.put(rootName, value);
43+
path = rootName;
44+
}
45+
46+
public static XmlBuilder create(String rootName) {
47+
return new XmlBuilder(rootName);
48+
}
49+
50+
public static XmlBuilder parse(String xml) {
51+
Map<String, Object> xmlData = U.fromXmlMap(xml);
52+
XmlBuilder xmlBuilder = new XmlBuilder(Xml.XmlValue.getMapKey(xmlData));
53+
xmlBuilder.setData(xmlData);
54+
return xmlBuilder;
55+
}
56+
57+
@SuppressWarnings("unchecked")
58+
public XmlBuilder e(String elementName) {
59+
U.remove(data, path + "." + SELF_CLOSING);
60+
Map<String, Object> value = new LinkedHashMap<>();
61+
value.put(SELF_CLOSING, TRUE);
62+
Object object = U.get(data, path + "." + elementName);
63+
if (object instanceof Map) {
64+
List<Object> list = new ArrayList<>();
65+
list.add(object);
66+
list.add(value);
67+
U.set(data, path + "." + elementName, list);
68+
path += "." + elementName + ".1";
69+
savedPath = path;
70+
} else if (object instanceof List) {
71+
path += "." + elementName + "." + ((List<Object>) object).size();
72+
savedPath = path;
73+
((List<Object>) object).add(value);
74+
} else {
75+
U.set(data, path + "." + elementName, value);
76+
path += "." + elementName;
77+
}
78+
return this;
79+
}
80+
81+
public XmlBuilder a(String attributeName, String value) {
82+
U.remove(data, path + "." + SELF_CLOSING);
83+
U.set(data, path + ".-" + attributeName, value);
84+
return this;
85+
}
86+
87+
public XmlBuilder c(String comment) {
88+
U.remove(data, path + "." + SELF_CLOSING);
89+
U.update(data, path + ".#comment", comment);
90+
return this;
91+
}
92+
93+
public XmlBuilder i(String target, String value) {
94+
U.remove(data, path + "." + SELF_CLOSING);
95+
U.set(data, "?" + target, value);
96+
return this;
97+
}
98+
99+
public XmlBuilder d(String cdata) {
100+
U.remove(data, path + "." + SELF_CLOSING);
101+
U.update(data, path + ".#cdata-section", cdata);
102+
return this;
103+
}
104+
105+
public XmlBuilder t(String text) {
106+
U.remove(data, path + "." + SELF_CLOSING);
107+
U.update(data, path + ".#text", text);
108+
return this;
109+
}
110+
111+
public XmlBuilder importXmlBuilder(XmlBuilder xmlBuilder) {
112+
data.putAll(xmlBuilder.data);
113+
return this;
114+
}
115+
116+
public XmlBuilder up() {
117+
if (path.equals(savedPath)) {
118+
path = path.substring(0, path.lastIndexOf("."));
119+
}
120+
path = path.substring(0, path.lastIndexOf("."));
121+
return this;
122+
}
123+
124+
public XmlBuilder root() {
125+
int index = path.indexOf(".");
126+
XmlBuilder xmlBuilder = new XmlBuilder(index == -1 ? path : path.substring(0, index));
127+
xmlBuilder.setData(data);
128+
return xmlBuilder;
129+
}
130+
131+
public org.w3c.dom.Document getDocument() {
132+
try {
133+
return Xml.Document.createDocument(asString());
134+
} catch (Exception ex) {
135+
throw new IllegalArgumentException(ex);
136+
}
137+
}
138+
139+
public XmlBuilder set(final String path, final Object value) {
140+
U.set(data, path, value);
141+
return this;
142+
}
143+
144+
public XmlBuilder remove(final String key) {
145+
U.remove(data, key);
146+
return this;
147+
}
148+
149+
public Map<String, Object> build() {
150+
return U.deepCopyMap(data);
151+
}
152+
153+
public XmlBuilder clear() {
154+
data.clear();
155+
return this;
156+
}
157+
158+
public boolean isEmpty() {
159+
return data.isEmpty();
160+
}
161+
162+
public int size() {
163+
return data.size();
164+
}
165+
166+
public String asString() {
167+
return U.toXml(data);
168+
}
169+
170+
public String toXml(Xml.XmlStringBuilder.Step identStep) {
171+
return Xml.toXml(data, identStep);
172+
}
173+
174+
public String toXml() {
175+
return U.toXml(data);
176+
}
177+
178+
public String toJson(Json.JsonStringBuilder.Step identStep) {
179+
return Json.toJson(data, identStep);
180+
}
181+
182+
public String toJson() {
183+
return U.toJson(data);
184+
}
185+
186+
private void setData(Map<String, Object> newData) {
187+
data.clear();
188+
data.putAll(newData);
189+
}
190+
}

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

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@
2929
import static org.junit.jupiter.api.Assertions.assertEquals;
3030
import static org.junit.jupiter.api.Assertions.assertNull;
3131
import static org.junit.jupiter.api.Assertions.assertThrows;
32+
import static org.junit.jupiter.api.Assertions.assertTrue;
3233

3334
import java.io.IOException;
35+
import java.net.URISyntaxException;
3436
import java.nio.file.Files;
3537
import java.nio.file.Paths;
3638
import java.util.ArrayList;
@@ -633,7 +635,7 @@ void fetchGet() {
633635
}
634636

635637
@Test
636-
void downloadUrl() throws IOException {
638+
void downloadUrl() throws IOException, URISyntaxException {
637639
try {
638640
long result =
639641
U.downloadUrl(
@@ -763,13 +765,24 @@ void fetchPut() {
763765

764766
@Test
765767
void fetchWrongUrl() {
766-
assertThrows(UnsupportedOperationException.class, () -> U.fetch("ttt"));
768+
assertThrows(IllegalArgumentException.class, () -> U.fetch("ttt"));
767769
}
768770

769771
@Test
770772
void fetchWrongUrlWithRetry() {
773+
assertThrows(IllegalArgumentException.class, () -> U.fetch("ttt", 30000, 30000, 1, 100));
774+
}
775+
776+
@Test
777+
void fetchWrongUrl2() {
778+
assertThrows(UnsupportedOperationException.class, () -> U.fetch("test://ttt"));
779+
}
780+
781+
@Test
782+
void fetchWrongUrlWithRetry2() {
771783
assertThrows(
772-
UnsupportedOperationException.class, () -> U.fetch("ttt", 30000, 30000, 1, 100));
784+
UnsupportedOperationException.class,
785+
() -> U.fetch("test://ttt", 30000, 30000, 1, 100));
773786
}
774787

775788
@Test
@@ -1004,6 +1017,20 @@ void removeMapKey() {
10041017
U.remove(map2, "list.0");
10051018
}
10061019

1020+
@Test
1021+
void updateMapValue() {
1022+
Map<String, Object> map = U.newLinkedHashMap();
1023+
map.put("-self-closing1", "true");
1024+
map.put("-self-closing2", "false");
1025+
U.update(map, "-self-closing1", "false");
1026+
U.update(map, "-self-closing3", "true");
1027+
U.update(map, asList("-self-closing1"), "false");
1028+
U.update(map, asList("-self-closing3"), "true");
1029+
assertTrue(U.toJson(map).startsWith("{\n"
1030+
+ " \"-self-closing1\": \"true\",\n"
1031+
+ " \"-self-closing2\": \"false\",\n"));
1032+
}
1033+
10071034
@Test
10081035
void renameMapKey() {
10091036
Map<String, Object> map = U.newLinkedHashMap();

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ void now() {
157157
*/
158158
@Test
159159
void uniqueId() {
160-
assertEquals("contact_1", Underscore.uniqueId("contact_"));
161-
assertEquals("2", Underscore.uniqueId(null));
160+
assertTrue(Underscore.uniqueId("contact_").matches("contact_\\d+"));
161+
assertTrue(Underscore.uniqueId(null).matches("\\d+"));
162162
}
163163

164164
@Test

0 commit comments

Comments
 (0)