This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 5439a6ef3c org.apache.juneau.common.reflect API improvements
5439a6ef3c is described below
commit 5439a6ef3c860740ddba5fd98685e884124ead07
Author: James Bognar <[email protected]>
AuthorDate: Tue Nov 25 11:10:02 2025 -0500
org.apache.juneau.common.reflect API improvements
---
TODO-StringUtils.md | 26 +-
.../apache/juneau/common/utils/StringUtils.java | 237 ++++
.../apache/juneau/common/utils/IOUtils_Test.java | 88 ++
.../juneau/common/utils/ListBuilder_Test.java | 55 -
.../juneau/common/utils/MapBuilder_Test.java | 69 -
.../juneau/common/utils/SetBuilder_Test.java | 55 -
.../juneau/common/utils/StringUtils_Test.java | 99 ++
.../java/org/apache/juneau/utils/IOUtils_Test.java | 109 --
.../org/apache/juneau/utils/StringUtils_Test.java | 1325 --------------------
9 files changed, 437 insertions(+), 1626 deletions(-)
diff --git a/TODO-StringUtils.md b/TODO-StringUtils.md
index 120e9737f8..8def9bcaee 100644
--- a/TODO-StringUtils.md
+++ b/TODO-StringUtils.md
@@ -3,7 +3,7 @@
This document outlines recommended methods to add to the `StringUtils` class
to make it a comprehensive string utility library suitable for external use.
## Current Status
-The `StringUtils` class currently has 187+ public static methods covering:
+The `StringUtils` class currently has 198+ public static methods covering:
- Base64 encoding/decoding
- Hex encoding/decoding
- URL encoding/decoding
@@ -82,23 +82,23 @@ The `StringUtils` class currently has 187+ public static
methods covering:
### 6. String Formatting and Templates
- ✅ `format(String template, Object... args)` - Implemented (could be enhanced)
-- [ ] `formatWithNamedArgs(String template, Map<String, Object> args)` -
Format with named placeholders
-- [ ] `interpolate(String template, Map<String, Object> variables)` - Variable
interpolation
-- [ ] `pluralize(String word, int count)` - Simple pluralization
-- [ ] `ordinal(int number)` - Convert number to ordinal (1st, 2nd, 3rd, etc.)
+- ✅ `formatWithNamedArgs(String template, Map<String, Object> args)` - Format
with named placeholders - Implemented
+- ✅ `interpolate(String template, Map<String, Object> variables)` - Variable
interpolation - Implemented
+- ✅ `pluralize(String word, int count)` - Simple pluralization - Implemented
+- ✅ `ordinal(int number)` - Convert number to ordinal (1st, 2nd, 3rd, etc.) -
Implemented
### 7. String Cleaning and Sanitization
- ✅ `clean(String str)` - Implemented
- ✅ `normalizeWhitespace(String str)` - Implemented
- ✅ `removeControlChars(String str)` - Implemented
- ✅ `removeNonPrintable(String str)` - Implemented
-- [ ] `sanitize(String str)` - Basic HTML/XML sanitization
-- [ ] `escapeHtml(String str)` - Escape HTML entities
-- [ ] `unescapeHtml(String str)` - Unescape HTML entities
-- [ ] `escapeXml(String str)` - Escape XML entities
-- [ ] `unescapeXml(String str)` - Unescape XML entities
-- [ ] `escapeSql(String str)` - Escape SQL strings (basic)
-- [ ] `escapeRegex(String str)` - Escape regex special characters
+- ✅ `sanitize(String str)` - Basic HTML/XML sanitization - Implemented
+- ✅ `escapeHtml(String str)` - Escape HTML entities - Implemented
+- ✅ `unescapeHtml(String str)` - Unescape HTML entities - Implemented
+- ✅ `escapeXml(String str)` - Escape XML entities - Implemented
+- ✅ `unescapeXml(String str)` - Unescape XML entities - Implemented
+- ✅ `escapeSql(String str)` - Escape SQL strings (basic) - Implemented
+- ✅ `escapeRegex(String str)` - Escape regex special characters - Implemented
### 8. String Comparison and Sorting
- [ ] `equalsIgnoreCase(String str1, String str2)` - Case-insensitive equals
@@ -197,7 +197,7 @@ The `StringUtils` class currently has 187+ public static
methods covering:
### Medium Priority (Useful Utilities)
1. ✅ String searching and matching methods - Completed
-2. String formatting and templates
+2. ✅ String formatting and templates - Completed
3. String comparison and sorting methods
4. String generation and random methods
5. String parsing and extraction methods
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/utils/StringUtils.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/utils/StringUtils.java
index 2c64c05442..14b149a41f 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/utils/StringUtils.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/utils/StringUtils.java
@@ -2285,6 +2285,243 @@ public class StringUtils {
.replace("|", "\\|");
}
+ /**
+ * Compares two strings for equality, ignoring case.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bjava'>
+ * equalsIgnoreCase(<js>"Hello"</js>, <js>"hello"</js>);
<jc>// true</jc>
+ * equalsIgnoreCase(<js>"Hello"</js>, <js>"WORLD"</js>);
<jc>// false</jc>
+ * equalsIgnoreCase(<jk>null</jk>, <jk>null</jk>);
<jc>// true</jc>
+ * </p>
+ *
+ * @param str1 The first string.
+ * @param str2 The second string.
+ * @return <jk>true</jk> if the strings are equal ignoring case,
<jk>false</jk> otherwise.
+ */
+ public static boolean equalsIgnoreCase(String str1, String str2) {
+ if (str1 == str2)
+ return true;
+ if (str1 == null || str2 == null)
+ return false;
+ return str1.equalsIgnoreCase(str2);
+ }
+
+ /**
+ * Compares two strings lexicographically, ignoring case.
+ *
+ * <p>
+ * Returns a negative integer, zero, or a positive integer as the first
string is less than, equal to, or greater than the second string, ignoring case.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bjava'>
+ * compareIgnoreCase(<js>"apple"</js>, <js>"BANANA"</js>);
<jc>// negative (apple < banana)</jc>
+ * compareIgnoreCase(<js>"Hello"</js>, <js>"hello"</js>);
<jc>// 0 (equal)</jc>
+ * compareIgnoreCase(<js>"Zebra"</js>, <js>"apple"</js>);
<jc>// positive (zebra > apple)</jc>
+ * </p>
+ *
+ * @param str1 The first string.
+ * @param str2 The second string.
+ * @return A negative integer, zero, or a positive integer as the first
string is less than, equal to, or greater than the second.
+ */
+ public static int compareIgnoreCase(String str1, String str2) {
+ if (str1 == str2)
+ return 0;
+ if (str1 == null)
+ return -1;
+ if (str2 == null)
+ return 1;
+ return str1.compareToIgnoreCase(str2);
+ }
+
+ /**
+ * Performs natural string comparison that handles numbers correctly.
+ *
+ * <p>
+ * Compares strings in a way that numbers are compared numerically
rather than lexicographically.
+ * For example, "file2.txt" comes before "file10.txt" in natural order.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bjava'>
+ * naturalCompare(<js>"file2.txt"</js>, <js>"file10.txt"</js>);
<jc>// negative (2 < 10)</jc>
+ * naturalCompare(<js>"file10.txt"</js>, <js>"file2.txt"</js>);
<jc>// positive (10 > 2)</jc>
+ * naturalCompare(<js>"file1.txt"</js>, <js>"file1.txt"</js>);
<jc>// 0 (equal)</jc>
+ * </p>
+ *
+ * @param str1 The first string.
+ * @param str2 The second string.
+ * @return A negative integer, zero, or a positive integer as the first
string is less than, equal to, or greater than the second.
+ */
+ public static int naturalCompare(String str1, String str2) {
+ if (str1 == str2)
+ return 0;
+ if (str1 == null)
+ return -1;
+ if (str2 == null)
+ return 1;
+
+ var len1 = str1.length();
+ var len2 = str2.length();
+ var i1 = 0;
+ var i2 = 0;
+
+ while (i1 < len1 && i2 < len2) {
+ var c1 = str1.charAt(i1);
+ var c2 = str2.charAt(i2);
+
+ // If both are digits, compare numerically
+ if (Character.isDigit(c1) && Character.isDigit(c2)) {
+ // Skip leading zeros
+ while (i1 < len1 && str1.charAt(i1) == '0')
+ i1++;
+ while (i2 < len2 && str2.charAt(i2) == '0')
+ i2++;
+
+ // Find end of number sequences
+ var end1 = i1;
+ var end2 = i2;
+ while (end1 < len1 &&
Character.isDigit(str1.charAt(end1)))
+ end1++;
+ while (end2 < len2 &&
Character.isDigit(str2.charAt(end2)))
+ end2++;
+
+ // Compare lengths first (longer number is
larger)
+ var lenNum1 = end1 - i1;
+ var lenNum2 = end2 - i2;
+ if (lenNum1 != lenNum2)
+ return lenNum1 - lenNum2;
+
+ // Same length, compare digit by digit
+ for (var j = 0; j < lenNum1; j++) {
+ var d1 = str1.charAt(i1 + j);
+ var d2 = str2.charAt(i2 + j);
+ if (d1 != d2)
+ return d1 - d2;
+ }
+
+ i1 = end1;
+ i2 = end2;
+ } else {
+ // Compare characters (case-insensitive)
+ var cmp = Character.toLowerCase(c1) -
Character.toLowerCase(c2);
+ if (cmp != 0)
+ return cmp;
+ i1++;
+ i2++;
+ }
+ }
+
+ return len1 - len2;
+ }
+
+ /**
+ * Calculates the Levenshtein distance (edit distance) between two
strings.
+ *
+ * <p>
+ * The Levenshtein distance is the minimum number of single-character
edits (insertions, deletions, or substitutions) required to change one string
into another.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bjava'>
+ * levenshteinDistance(<js>"kitten"</js>, <js>"sitting"</js>);
<jc>// 3</jc>
+ * levenshteinDistance(<js>"hello"</js>, <js>"hello"</js>);
<jc>// 0</jc>
+ * levenshteinDistance(<js>"abc"</js>, <js>""</js>);
<jc>// 3</jc>
+ * </p>
+ *
+ * @param str1 The first string.
+ * @param str2 The second string.
+ * @return The Levenshtein distance between the two strings.
+ */
+ public static int levenshteinDistance(String str1, String str2) {
+ if (str1 == null)
+ str1 = "";
+ if (str2 == null)
+ str2 = "";
+
+ var len1 = str1.length();
+ var len2 = str2.length();
+
+ // Use dynamic programming with optimized space (only need
previous row)
+ var prev = new int[len2 + 1];
+ var curr = new int[len2 + 1];
+
+ // Initialize first row
+ for (var j = 0; j <= len2; j++)
+ prev[j] = j;
+
+ for (var i = 1; i <= len1; i++) {
+ curr[0] = i;
+ for (var j = 1; j <= len2; j++) {
+ if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
+ curr[j] = prev[j - 1];
+ } else {
+ curr[j] = 1 +
Math.min(Math.min(prev[j], curr[j - 1]), prev[j - 1]);
+ }
+ }
+ // Swap arrays
+ var temp = prev;
+ prev = curr;
+ curr = temp;
+ }
+
+ return prev[len2];
+ }
+
+ /**
+ * Calculates the similarity percentage between two strings using
Levenshtein distance.
+ *
+ * <p>
+ * Returns a value between 0.0 (completely different) and 1.0
(identical).
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bjava'>
+ * similarity(<js>"hello"</js>, <js>"hello"</js>);
<jc>// 1.0 (100%)</jc>
+ * similarity(<js>"kitten"</js>, <js>"sitting"</js>);
<jc>// ~0.57 (57%)</jc>
+ * similarity(<js>"abc"</js>, <js>"xyz"</js>);
<jc>// 0.0 (0%)</jc>
+ * </p>
+ *
+ * @param str1 The first string.
+ * @param str2 The second string.
+ * @return A similarity value between 0.0 and 1.0, where 1.0 means
identical.
+ */
+ public static double similarity(String str1, String str2) {
+ if (str1 == null)
+ str1 = "";
+ if (str2 == null)
+ str2 = "";
+
+ if (str1.equals(str2))
+ return 1.0;
+
+ var maxLen = Math.max(str1.length(), str2.length());
+ if (maxLen == 0)
+ return 1.0;
+
+ var distance = levenshteinDistance(str1, str2);
+ return 1.0 - ((double)distance / maxLen);
+ }
+
+ /**
+ * Checks if two strings are similar based on a similarity threshold.
+ *
+ * <p>
+ * Uses the {@link #similarity(String, String)} method to calculate
similarity and compares it to the threshold.
+ *
+ * <h5 class='section'>Example:</h5>
+ * <p class='bjava'>
+ * isSimilar(<js>"hello"</js>, <js>"hello"</js>, <js>0.8</js>);
<jc>// true</jc>
+ * isSimilar(<js>"kitten"</js>, <js>"sitting"</js>, <js>0.8</js>);
<jc>// false</jc>
+ * isSimilar(<js>"kitten"</js>, <js>"sitting"</js>, <js>0.5</js>);
<jc>// true</jc>
+ * </p>
+ *
+ * @param str1 The first string.
+ * @param str2 The second string.
+ * @param threshold The similarity threshold (0.0 to 1.0).
+ * @return <jk>true</jk> if the similarity is greater than or equal to
the threshold, <jk>false</jk> otherwise.
+ */
+ public static boolean isSimilar(String str1, String str2, double
threshold) {
+ return similarity(str1, str2) >= threshold;
+ }
+
/**
* Join the specified tokens into a delimited string.
*
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/utils/IOUtils_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/utils/IOUtils_Test.java
index 8d56b80c41..62d8937ef4 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/common/utils/IOUtils_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/utils/IOUtils_Test.java
@@ -18,6 +18,7 @@
package org.apache.juneau.common.utils;
import static org.apache.juneau.common.utils.IOUtils.*;
+import static org.apache.juneau.common.utils.IOUtils.UTF8;
import static org.junit.jupiter.api.Assertions.*;
import java.io.*;
@@ -32,9 +33,96 @@ import org.junit.jupiter.api.*;
*/
class IOUtils_Test extends TestBase {
+
//====================================================================================================
+ // read(Path)
+
//====================================================================================================
@Test void a01_readPath() throws IOException {
var p = new Properties();
p.load(new
StringReader(read(Paths.get("src/test/resources/files/Test3.properties"))));
assertEquals("files/Test3.properties", p.get("file"));
}
+
+
//====================================================================================================
+ // pipe(Reader, Writer)
+
//====================================================================================================
+ @Test void b01_pipe() throws Exception {
+ var out = new TestWriter();
+ var in = new TestReader("foobar");
+
+ pipe(in, out);
+ assertTrue(in.closed);
+ assertFalse(out.closed);
+ assertEquals("foobar", out.toString());
+ }
+
+
//====================================================================================================
+ // loadSystemResourceAsString(String, String...)
+
//====================================================================================================
+ @Test void c01_loadSystemResourceAsString() throws Exception {
+ assertNotNull(loadSystemResourceAsString("test1.txt", "."));
+ assertNull(loadSystemResourceAsString("test2.txt", "."));
+ assertNull(loadSystemResourceAsString("test3.txt", "sub"));
+ assertNull(loadSystemResourceAsString("test3.txt", "sub2"));
+ assertNotNull(loadSystemResourceAsString("test3.txt", "."));
+ assertNotNull(loadSystemResourceAsString("test4.txt", ".",
"sub"));
+ assertNotNull(loadSystemResourceAsString("test4.txt", "sub"));
+ }
+
+
//====================================================================================================
+ // Test helper classes
+
//====================================================================================================
+ public static class TestReader extends StringReader {
+ boolean closed;
+
+ public TestReader(String s) {
+ super(s);
+ }
+
+ @Override /* Reader */
+ public void close() {
+ closed = true;
+ }
+ }
+
+ public static class TestWriter extends StringWriter {
+ boolean closed;
+
+ public TestWriter() { /* no-op */ }
+
+ @Override /* Writer */
+ public void close() {
+ closed = true;
+ }
+ }
+
+ public static class TestInputStream extends ByteArrayInputStream {
+ boolean closed;
+
+ public TestInputStream(String s) {
+ super(s.getBytes());
+ }
+
+ @Override /* InputStream */
+ public void close() throws IOException {
+ super.close();
+ closed = true;
+ }
+ }
+
+ public static class TestOutputStream extends ByteArrayOutputStream {
+ boolean closed;
+
+ public TestOutputStream() { /* no-op */ }
+
+ @Override /* OutputStream */
+ public void close() throws IOException {
+ super.close();
+ closed = true;
+ }
+
+ @Override /* Overridden from Object */
+ public synchronized String toString() {
+ return new String(this.toByteArray(), UTF8);
+ }
+ }
}
\ No newline at end of file
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/utils/ListBuilder_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/utils/ListBuilder_Test.java
deleted file mode 100644
index 604ab8bf42..0000000000
---
a/juneau-utest/src/test/java/org/apache/juneau/common/utils/ListBuilder_Test.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.common.utils;
-
-import static org.apache.juneau.common.utils.CollectionUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.util.*;
-
-import org.junit.jupiter.api.*;
-
-public class ListBuilder_Test {
-
- @Test
- void build_basic_add_and_addAll() {
- List<String> l = listb(String.class)
- .add("a")
- .add("b", "c")
- .addAll(l("d", "e"))
- .build();
- assertEquals(l("a","b","c","d","e"), l);
- }
-
- @Test
- void build_sparse_and_unmodifiable() {
- assertNull(listb(String.class).sparse().build());
- List<String> l = listb(String.class).add("a").unmodifiable().build();
- assertThrows(UnsupportedOperationException.class, () -> l.add("b"));
- }
-
- @Test
- void sorted_natural_and_custom() {
- List<Integer> l1 = listb(Integer.class).add(3,1,2).sorted().build();
- assertEquals(l(1,2,3), l1);
-
- List<Integer> l2 =
listb(Integer.class).add(3,1,2).sorted(Comparator.reverseOrder()).build();
- assertEquals(l(3,2,1), l2);
- }
-}
-
-
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/utils/MapBuilder_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/utils/MapBuilder_Test.java
deleted file mode 100644
index 569f718fe3..0000000000
---
a/juneau-utest/src/test/java/org/apache/juneau/common/utils/MapBuilder_Test.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.common.utils;
-
-import static org.apache.juneau.common.utils.CollectionUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.util.*;
-
-import org.junit.jupiter.api.*;
-
-public class MapBuilder_Test {
-
- @Test
- void build_basic_add_and_addAll() {
- Map<String,Integer> m = mapb(String.class, Integer.class)
- .add("a",1)
- .add("b",2)
- .addAll(map("c",3))
- .build();
- LinkedHashMap<String,Integer> expected = map();
- expected.put("a",1);
- expected.put("b",2);
- expected.put("c",3);
- assertEquals(expected, m);
- }
-
- @Test
- void build_sparse_and_unmodifiable() {
- assertNull(mapb(String.class, Integer.class).sparse().build());
- Map<String,Integer> m = mapb(String.class,
Integer.class).add("a",1).unmodifiable().build();
- assertThrows(UnsupportedOperationException.class, () -> m.put("b",2));
- }
-
- @Test
- void sorted_natural_and_custom() {
- Map<String,Integer> m1 = mapb(String.class, Integer.class)
- .add("b",2).add("c",3).add("a",1)
- .sorted()
- .build();
- assertEquals(new TreeMap<>(map("a",1,"b",2,"c",3)), m1);
-
- Map<String,Integer> m2 = mapb(String.class, Integer.class)
- .add("b",2).add("c",3).add("a",1)
- .sorted(Comparator.reverseOrder())
- .build();
- TreeMap<String,Integer> expected = new
TreeMap<>(Comparator.reverseOrder());
- expected.put("c",3);
- expected.put("b",2);
- expected.put("a",1);
- assertEquals(expected, m2);
- }
-}
-
-
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/utils/SetBuilder_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/utils/SetBuilder_Test.java
deleted file mode 100644
index c83e79dd9c..0000000000
---
a/juneau-utest/src/test/java/org/apache/juneau/common/utils/SetBuilder_Test.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.common.utils;
-
-import static org.apache.juneau.common.utils.CollectionUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.util.*;
-
-import org.junit.jupiter.api.*;
-
-public class SetBuilder_Test {
-
- @Test
- void build_basic_add_and_addAll() {
- Set<String> s = setb(String.class)
- .add("a")
- .add("b", "c")
- .addAll(new LinkedHashSet<>(l("d", "e")))
- .build();
- assertEquals(new LinkedHashSet<>(l("a","b","c","d","e")), s);
- }
-
- @Test
- void build_sparse_and_unmodifiable() {
- assertNull(setb(String.class).sparse().build());
- Set<String> s = setb(String.class).add("a").unmodifiable().build();
- assertThrows(UnsupportedOperationException.class, () -> s.add("b"));
- }
-
- @Test
- void sorted_natural_and_custom() {
- Set<Integer> s1 = setb(Integer.class).add(3,1,2).sorted().build();
- assertEquals(new TreeSet<>(l(1,2,3)), s1);
-
- Set<Integer> s2 =
setb(Integer.class).add(3,1,2).sorted(Comparator.reverseOrder()).build();
- assertEquals(new TreeSet<>(l(3,2,1)), s2);
- }
-}
-
-
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/utils/StringUtils_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/utils/StringUtils_Test.java
index cf822513b2..0338cca701 100755
---
a/juneau-utest/src/test/java/org/apache/juneau/common/utils/StringUtils_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/utils/StringUtils_Test.java
@@ -1522,6 +1522,105 @@ class StringUtils_Test extends TestBase {
assertFalse(pattern.matcher("filextxt").matches());
}
+ @Test void a73_equalsIgnoreCase() {
+ assertTrue(equalsIgnoreCase("Hello", "hello"));
+ assertTrue(equalsIgnoreCase("HELLO", "hello"));
+ assertTrue(equalsIgnoreCase("Hello", "HELLO"));
+ assertTrue(equalsIgnoreCase("Hello", "Hello"));
+ assertFalse(equalsIgnoreCase("Hello", "World"));
+ assertTrue(equalsIgnoreCase(null, null));
+ assertFalse(equalsIgnoreCase(null, "test"));
+ assertFalse(equalsIgnoreCase("test", null));
+ assertTrue(equalsIgnoreCase("", ""));
+ }
+
+ @Test void a74_compareIgnoreCase() {
+ assertTrue(compareIgnoreCase("apple", "BANANA") < 0);
+ assertTrue(compareIgnoreCase("BANANA", "apple") > 0);
+ assertEquals(0, compareIgnoreCase("Hello", "hello"));
+ assertEquals(0, compareIgnoreCase("HELLO", "hello"));
+ assertTrue(compareIgnoreCase("Zebra", "apple") > 0);
+ assertTrue(compareIgnoreCase("apple", "Zebra") < 0);
+ assertEquals(0, compareIgnoreCase(null, null));
+ assertTrue(compareIgnoreCase(null, "test") < 0);
+ assertTrue(compareIgnoreCase("test", null) > 0);
+ }
+
+ @Test void a75_naturalCompare() {
+ // Numbers should be compared numerically
+ assertTrue(naturalCompare("file2.txt", "file10.txt") < 0);
+ assertTrue(naturalCompare("file10.txt", "file2.txt") > 0);
+ assertEquals(0, naturalCompare("file1.txt", "file1.txt"));
+ assertTrue(naturalCompare("file1.txt", "file2.txt") < 0);
+ assertTrue(naturalCompare("file2.txt", "file1.txt") > 0);
+
+ // Leading zeros
+ assertTrue(naturalCompare("file02.txt", "file10.txt") < 0);
+ assertTrue(naturalCompare("file002.txt", "file10.txt") < 0);
+
+ // Mixed alphanumeric
+ assertTrue(naturalCompare("a2b", "a10b") < 0);
+ assertTrue(naturalCompare("a10b", "a2b") > 0);
+
+ // Same numbers, different text
+ assertTrue(naturalCompare("file1a.txt", "file1b.txt") < 0);
+
+ // Null handling
+ assertEquals(0, naturalCompare(null, null));
+ assertTrue(naturalCompare(null, "test") < 0);
+ assertTrue(naturalCompare("test", null) > 0);
+
+ // Case-insensitive comparison
+ assertTrue(naturalCompare("Apple", "banana") < 0);
+ assertTrue(naturalCompare("banana", "Apple") > 0);
+ }
+
+ @Test void a76_levenshteinDistance() {
+ assertEquals(0, levenshteinDistance("hello", "hello"));
+ assertEquals(3, levenshteinDistance("kitten", "sitting")); //
kitten -> sitten (s), sitten -> sittin (i), sittin -> sitting (g)
+ assertEquals(3, levenshteinDistance("abc", ""));
+ assertEquals(3, levenshteinDistance("", "abc"));
+ assertEquals(1, levenshteinDistance("hello", "hallo")); // e ->
a (1 substitution)
+ assertEquals(1, levenshteinDistance("hello", "helo")); //
Remove one 'l' (1 deletion)
+ assertEquals(1, levenshteinDistance("hello", "hell")); //
Remove 'o' (1 deletion)
+ assertEquals(1, levenshteinDistance("hello", "hellox")); // Add
'x' (1 insertion)
+ // Null handling
+ assertEquals(0, levenshteinDistance(null, null));
+ assertEquals(5, levenshteinDistance("hello", null));
+ assertEquals(5, levenshteinDistance(null, "hello"));
+ }
+
+ @Test void a77_similarity() {
+ assertEquals(1.0, similarity("hello", "hello"), 0.0001);
+ assertEquals(0.0, similarity("abc", "xyz"), 0.0001);
+ // kitten -> sitting: distance = 3, maxLen = 7, similarity = 1
- 3/7 = 4/7 ≈ 0.571
+ assertEquals(4.0/7.0, similarity("kitten", "sitting"), 0.01);
+ assertEquals(1.0, similarity("", ""), 0.0001);
+ assertEquals(0.0, similarity("abc", ""), 0.0001);
+ assertEquals(0.0, similarity("", "abc"), 0.0001);
+ // Null handling
+ assertEquals(1.0, similarity(null, null), 0.0001);
+ assertEquals(0.0, similarity("hello", null), 0.0001);
+ assertEquals(0.0, similarity(null, "hello"), 0.0001);
+ // Similar strings
+ // "hello" vs "hallo": distance = 1, maxLen = 5, similarity = 1
- 1/5 = 0.8
+ assertEquals(0.8, similarity("hello", "hallo"), 0.0001);
+ }
+
+ @Test void a78_isSimilar() {
+ assertTrue(isSimilar("hello", "hello", 0.8));
+ assertTrue(isSimilar("hello", "hello", 1.0));
+ assertFalse(isSimilar("kitten", "sitting", 0.8));
+ assertTrue(isSimilar("kitten", "sitting", 0.5));
+ assertFalse(isSimilar("abc", "xyz", 0.5));
+ assertTrue(isSimilar("hello", "hallo", 0.8));
+ assertFalse(isSimilar("hello", "world", 0.8));
+ // Null handling
+ assertTrue(isSimilar(null, null, 0.8));
+ assertFalse(isSimilar("hello", null, 0.8));
+ assertFalse(isSimilar(null, "hello", 0.8));
+ }
+
//====================================================================================================
// String manipulation methods
//====================================================================================================
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/utils/IOUtils_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/utils/IOUtils_Test.java
deleted file mode 100755
index 222ec11003..0000000000
--- a/juneau-utest/src/test/java/org/apache/juneau/utils/IOUtils_Test.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.utils;
-
-import static org.apache.juneau.common.utils.IOUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.io.*;
-
-import org.apache.juneau.*;
-import org.junit.jupiter.api.*;
-
-class IOUtils_Test extends TestBase {
-
-
//====================================================================================================
- // read(File)
- // read(InputStream, Charset)
- // read(InputStream)
- // read(Reader, int, int)
-
//====================================================================================================
- @Test void a01_read() throws Exception {
- var out = new TestWriter();
- var in = new TestReader("foobar");
-
- pipe(in, out);
- assertTrue(in.closed);
- assertFalse(out.closed);
- assertEquals("foobar", out.toString());
- }
-
- @Test void a02_loadSystemResourceAsString() throws Exception {
- assertNotNull(loadSystemResourceAsString("test1.txt", "."));
- assertNull(loadSystemResourceAsString("test2.txt", "."));
- assertNull(loadSystemResourceAsString("test3.txt", "sub"));
- assertNull(loadSystemResourceAsString("test3.txt", "sub2"));
- assertNotNull(loadSystemResourceAsString("test3.txt", "."));
- assertNotNull(loadSystemResourceAsString("test4.txt", ".",
"sub"));
- assertNotNull(loadSystemResourceAsString("test4.txt", "sub"));
- }
-
- public static class TestReader extends StringReader {
- boolean closed;
-
- public TestReader(String s) {
- super(s);
- }
-
- @Override /* Reader */
- public void close() {
- closed = true;
- }
- }
-
- public static class TestWriter extends StringWriter {
- boolean closed;
-
- public TestWriter() { /* no-op */ }
-
- @Override /* Writer */
- public void close() {
- closed = true;
- }
- }
-
- public static class TestInputStream extends ByteArrayInputStream {
- boolean closed;
-
- public TestInputStream(String s) {
- super(s.getBytes());
- }
-
- @Override /* InputStream */
- public void close() throws IOException {
- super.close();
- closed = true;
- }
- }
-
- public static class TestOutputStream extends ByteArrayOutputStream {
- boolean closed;
-
- public TestOutputStream() { /* no-op */ }
-
- @Override /* OutputStream */
- public void close() throws IOException {
- super.close();
- closed = true;
- }
-
- @Override /* Overridden from Object */
- public synchronized String toString() {
- return new String(this.toByteArray(), UTF8);
- }
- }
-}
\ No newline at end of file
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/utils/StringUtils_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/utils/StringUtils_Test.java
deleted file mode 100755
index a0af01483a..0000000000
--- a/juneau-utest/src/test/java/org/apache/juneau/utils/StringUtils_Test.java
+++ /dev/null
@@ -1,1325 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.utils;
-
-import static org.apache.juneau.TestUtils.*;
-import static org.apache.juneau.common.utils.CollectionUtils.*;
-import static org.apache.juneau.common.utils.StringUtils.*;
-import static org.apache.juneau.common.utils.StringUtils.reverse;
-import static org.apache.juneau.junit.bct.BctAssertions.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.collections.*;
-import org.apache.juneau.common.utils.*;
-import org.junit.jupiter.api.*;
-
-class StringUtils_Test extends TestBase {
-
-
//====================================================================================================
- // isNumeric(String,Class)
- // parseNumber(String,Class)
-
//====================================================================================================
- @Test void a01_testParser() {
-
- // Integers
- assertTrue(isNumeric("123"));
- assertEquals(123, parseNumber("123", null));
- assertEquals(123, parseNumber("123", Integer.class));
- assertEquals((short)123, parseNumber("123", Short.class));
- assertEquals((long)123, parseNumber("123", Long.class));
-
- assertTrue(isNumeric("0123"));
- assertEquals(0123, parseNumber("0123", null));
-
- assertTrue(isNumeric("-0123"));
- assertEquals(-0123, parseNumber("-0123", null));
-
- // Hexadecimal
- assertTrue(isNumeric("0x123"));
- assertEquals(0x123, parseNumber("0x123", null));
-
- assertTrue(isNumeric("-0x123"));
- assertEquals(-0x123, parseNumber("-0x123", null));
-
- assertTrue(isNumeric("0X123"));
- assertEquals(0X123, parseNumber("0X123", null));
-
- assertTrue(isNumeric("-0X123"));
- assertEquals(-0X123, parseNumber("-0X123", null));
-
- assertTrue(isNumeric("#123"));
- assertEquals(0x123, parseNumber("#123", null));
-
- assertTrue(isNumeric("-#123"));
- assertEquals(-0x123, parseNumber("-#123", null));
-
- assertFalse(isNumeric("x123"));
- assertFalse(isNumeric("0x123x"));
-
- // Decimal
- assertTrue(isNumeric("0.123"));
- assertEquals(0.123f, parseNumber("0.123", null));
-
- assertTrue(isNumeric("-0.123"));
- assertEquals(-0.123f, parseNumber("-0.123", null));
-
- assertTrue(isNumeric(".123"));
- assertEquals(.123f, parseNumber(".123", null));
-
- assertTrue(isNumeric("-.123"));
- assertEquals(-.123f, parseNumber("-.123", null));
-
- assertFalse(isNumeric("0.123.4"));
-
- assertTrue(isNumeric("0.84370821629078d"));
- assertEquals(0.84370821629078d,
parseNumber("0.84370821629078d", null));
-
- assertTrue(isNumeric("84370821629078.8437d"));
- assertEquals(84370821629078.8437d,
parseNumber("84370821629078.8437d", null));
-
- assertTrue(isNumeric("0.16666666666666666d"));
- assertEquals(0.16666666666666666d,
parseNumber("0.16666666666666666d", null));
-
- assertTrue(isNumeric("0.16666666f"));
- assertEquals(0.16666666f, parseNumber("0.16666666f", null));
-
- assertTrue(isNumeric("0.16666666d"));
- assertEquals(0.16666666f, parseNumber("0.16666666d", null));
-
-
assertTrue(isNumeric("3.140000000000000124344978758017532527446746826171875d"));
- assertEquals(3.14f,
parseNumber("3.140000000000000124344978758017532527446746826171875d", null));
-
- assertTrue(isNumeric("12345.678f"));
- assertEquals(1.2345678e4f, parseNumber("12345.678f", null));
-
- // Scientific notation
- assertTrue(isNumeric("1e1"));
- assertEquals(1e1f, parseNumber("1e1", null));
-
- assertTrue(isNumeric("1e+1"));
- assertEquals(1e+1f, parseNumber("1e+1", null));
-
- assertTrue(isNumeric("1e-1"));
- assertEquals(1e-1f, parseNumber("1e-1", null));
-
- assertTrue(isNumeric("1.1e1"));
- assertEquals(1.1e1f, parseNumber("1.1e1", null));
-
- assertTrue(isNumeric("1.1e+1"));
- assertEquals(1.1e+1f, parseNumber("1.1e+1", null));
-
- assertTrue(isNumeric("1.1e-1"));
- assertEquals(1.1e-1f, parseNumber("1.1e-1", null));
-
- assertTrue(isNumeric(".1e1"));
- assertEquals(.1e1f, parseNumber(".1e1", null));
-
- assertTrue(isNumeric(".1e+1"));
- assertEquals(.1e+1f, parseNumber(".1e+1", null));
-
- assertTrue(isNumeric(".1e-1"));
- assertEquals(.1e-1f, parseNumber(".1e-1", null));
-
- // Hexadecimal + scientific
- assertTrue(isNumeric("0x123e1"));
- assertEquals(0x123e1, parseNumber("0x123e1", null));
-
- assertThrows(NumberFormatException.class, ()->parseNumber("x",
Number.class));
- assertThrows(NumberFormatException.class, ()->parseNumber("x",
null));
- assertThrowsWithMessage(NumberFormatException.class,
"Unsupported Number type", ()->parseNumber("x", BadNumber.class));
- }
-
- @SuppressWarnings("serial")
- private abstract static class BadNumber extends Number {}
-
-
//====================================================================================================
- // test - Basic tests
-
//====================================================================================================
- @Test void a02_numberRanges() {
- // An integer range is -2,147,483,648 to 2,147,483,647
-
- assertFalse(isNumeric(null));
- assertFalse(isNumeric(""));
- assertFalse(isNumeric("x"));
-
- var s = "-2147483648";
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Integer);
- assertEquals(-2147483648, parseNumber(s, null));
-
- s = "2147483647";
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Integer);
- assertEquals(2147483647, parseNumber(s, null));
-
- s = "-2147483649";
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Long);
- assertEquals(-2147483649L, parseNumber(s, null));
-
- s = "2147483648";
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Long);
- assertEquals(2147483648L, parseNumber(s, null));
-
- // An long range is -9,223,372,036,854,775,808 to
+9,223,372,036,854,775,807
-
- s = "-9223372036854775808";
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Long);
- assertEquals(-9223372036854775808L, parseNumber(s, null));
-
- s = "9223372036854775807";
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Long);
- assertEquals(9223372036854775807L, parseNumber(s, null));
-
- // Anything that falls outside this range should be a double.
-
- s = "-9223372036854775809";
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Double);
- assertEquals(-9223372036854775808L, parseNumber(s,
null).longValue());
- assertEquals(-9.223372036854776E18, parseNumber(s, null));
-
- s = "9223372036854775808";
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Double);
- assertEquals(9223372036854775807L, parseNumber(s,
null).longValue());
- assertEquals(9.223372036854776E18, parseNumber(s, null));
-
- // Check case where string is longer than 20 characters since
it's a different code path.
-
- s = "-123456789012345678901";
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Double);
- assertEquals(-9223372036854775808L, parseNumber(s,
null).longValue());
- assertEquals(-1.2345678901234568E20, parseNumber(s, null));
-
- s = "123456789012345678901";
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Double);
- assertEquals(9223372036854775807L, parseNumber(s,
null).longValue());
- assertEquals(1.2345678901234568E20, parseNumber(s, null));
-
- // Autodetected floating point numbers smaller than
Float.MAX_VALUE
- s = String.valueOf(Float.MAX_VALUE / 2);
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Float);
- assertEquals(1.7014117E38f, parseNumber(s, null));
-
- s = String.valueOf((-Float.MAX_VALUE) / 2);
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Float);
- assertEquals(-1.7014117E38f, parseNumber(s, null));
-
- // Autodetected floating point numbers larger than
Float.MAX_VALUE
- s = String.valueOf((double)Float.MAX_VALUE * 2);
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Double);
- assertEquals("6.805646932770577E38", parseNumber(s,
null).toString());
-
- s = String.valueOf((double)Float.MAX_VALUE * -2);
- assertTrue(isNumeric(s));
- assertTrue(parseNumber(s, null) instanceof Double);
- assertEquals("-6.805646932770577E38", parseNumber(s,
null).toString());
-
- s = String.valueOf("214748364x");
- assertFalse(isNumeric(s));
- assertThrows(NumberFormatException.class,
()->parseNumber("214748364x", Number.class));
-
- s = String.valueOf("2147483640x");
- assertFalse(isNumeric(s));
- assertThrows(NumberFormatException.class,
()->parseNumber("2147483640x", Long.class));
- }
-
-
//====================================================================================================
- // testReplaceVars
-
//====================================================================================================
- @Test void a03_replaceVars() throws Exception {
- var m =
JsonMap.ofJson("{a:'A',b:1,c:true,d:'{e}',e:'E{f}E',f:'F',g:'{a}',h:'a',i:null}");
-
- assertEquals("xxx", replaceVars("xxx", m));
- assertEquals("A", replaceVars("{a}", m));
- assertEquals("AA", replaceVars("{a}{a}", m));
- assertEquals("xAx", replaceVars("x{a}x", m));
- assertEquals("xAxAx", replaceVars("x{a}x{a}x", m));
- assertEquals("1", replaceVars("{b}", m));
- assertEquals("11", replaceVars("{b}{b}", m));
- assertEquals("x1x", replaceVars("x{b}x", m));
- assertEquals("x1x1x", replaceVars("x{b}x{b}x", m));
- assertEquals("true", replaceVars("{c}", m));
- assertEquals("truetrue", replaceVars("{c}{c}", m));
- assertEquals("xtruextruex", replaceVars("x{c}x{c}x", m));
- assertEquals("EFE", replaceVars("{d}", m));
- assertEquals("EFEEFE", replaceVars("{d}{d}", m));
- assertEquals("xEFEx", replaceVars("x{d}x", m));
- assertEquals("xEFExEFEx", replaceVars("x{d}x{d}x", m));
- assertEquals("A", replaceVars("{g}", m));
- assertEquals("AA", replaceVars("{g}{g}", m));
- assertEquals("xAx", replaceVars("x{g}x", m));
- assertEquals("xAxAx", replaceVars("x{g}x{g}x", m));
- assertEquals("{x}", replaceVars("{x}", m));
- assertEquals("{x}{x}", replaceVars("{x}{x}", m));
- assertEquals("x{x}x{x}x", replaceVars("x{x}x{x}x", m));
- assertEquals("{A}", replaceVars("{{g}}", m));
- assertEquals("A", replaceVars("{{h}}", m));
- assertEquals("{}", replaceVars("{{i}}", m));
- assertEquals("{}", replaceVars("{}", m));
- }
-
-
//====================================================================================================
- // isFloat(String)
-
//====================================================================================================
- @Test void a04_isFloat() {
- var valid = a(
- "+1.0",
- "-1.0",
- ".0",
- "NaN",
- "Infinity",
- "1e1",
- "-1e-1",
- "+1e+1",
- "-1.1e-1",
- "+1.1e+1",
- "1.1f",
- "1.1F",
- "1.1d",
- "1.1D",
- "0x1.fffffffffffffp1023",
- "0x1.FFFFFFFFFFFFFP1023"
- );
- for (var s : valid)
- assertTrue(isFloat(s));
-
- var invalid = a(
- null,
- "",
- "a",
- "+",
- "-",
- ".",
- "a",
- "+a",
- "11a"
- );
- for (var s : invalid)
- assertFalse(isFloat(s));
- }
-
-
//====================================================================================================
- // isDecimal(String)
-
//====================================================================================================
- @Test void a05_isDecimal() {
- var valid = a(
- "+1",
- "-1",
- "0x123",
- "0X123",
- "0xdef",
- "0XDEF",
- "#def",
- "#DEF",
- "0123"
- );
- for (var s : valid)
- assertTrue(isDecimal(s));
-
- var invalid = a(
- null,
- "",
- "a",
- "+",
- "-",
- ".",
- "0xdeg",
- "0XDEG",
- "#deg",
- "#DEG",
- "0128",
- "012A"
- );
- for (var s : invalid)
- assertFalse(isDecimal(s));
- }
-
-
//====================================================================================================
- // join(Object[],String)
- // join(int[],String)
- // join(Collection,String)
- // join(Object[],char)
- // join(int[],char)
- // join(Collection,char)
-
//====================================================================================================
- @Test void a01_join() {
- assertNull(StringUtils.join((Object[])null, ","));
- assertEquals("1", StringUtils.join(a(1), ","));
- assertEquals("1,2", StringUtils.join(a(1,2), ","));
-
- assertNull(StringUtils.join((Collection<?>)null, ","));
- assertEquals("1", StringUtils.join(l(a(1)), ","));
- assertEquals("1,2", StringUtils.join(l(a(1,2)), ","));
-
- assertNull(StringUtils.join((Object[])null, ','));
- assertEquals("x,y,z", StringUtils.join(a("x,y","z"), ','));
-
- assertNull(StringUtils.join((int[])null, ','));
- assertEquals("1", StringUtils.join(ints(1), ','));
- assertEquals("1,2", StringUtils.join(ints(1,2), ','));
-
- assertNull(StringUtils.join((Collection<?>)null, ','));
- assertEquals("1", StringUtils.join(l(a(1)), ','));
- assertEquals("1,2", StringUtils.join(l(a(1,2)), ','));
-
- assertNull(StringUtils.joine((List<?>)null, ','));
- assertEquals("x\\,y,z", StringUtils.joine(l(a("x,y","z")),
','));
- }
-
-
//====================================================================================================
- // split(String,char)
-
//====================================================================================================
- @Test void a07_split() {
- assertNull(StringUtils.splita((String)null));
- assertEmpty(StringUtils.splita(""));
- assertList(StringUtils.splita("1"), "1");
- assertList(StringUtils.splita("1,2"), "1", "2");
- assertList(StringUtils.splita("1\\,2"), "1,2");
- assertList(StringUtils.splita("1\\\\,2"), "1\\", "2");
- assertList(StringUtils.splita("1\\\\\\,2"), "1\\,2");
- assertList(StringUtils.splita("1,2\\"), "1", "2\\");
- assertList(StringUtils.splita("1,2\\\\"), "1", "2\\");
- assertList(StringUtils.splita("1,2\\,"), "1", "2,");
- assertList(StringUtils.splita("1,2\\\\,"), "1", "2\\", "");
- }
-
- @Test void a08_split2() {
- assertEmpty(split2test(null));
- assertString("[]", split2test(""));
- assertString("[1]", split2test("1"));
- assertString("[1,2]", split2test("1,2"));
- assertList(split2test("1\\,2"), "1,2");
- assertList(split2test("1\\\\,2"), "1\\", "2");
- assertList(split2test("1\\\\\\,2"), "1\\,2");
- assertList(split2test("1,2\\"), "1", "2\\");
- assertList(split2test("1,2\\\\"), "1", "2\\");
- assertList(split2test("1,2\\,"), "1", "2,");
- assertList(split2test("1,2\\\\,"), "1", "2\\", "");
- }
-
- private static List<String> split2test(String s) {
- var l = new ArrayList<String>();
- StringUtils.split(s, l::add);
- return l;
- }
-
-
//====================================================================================================
- // split(String,char,int)
-
//====================================================================================================
- @Test void a09_splitWithLimit() {
- assertString("[boo,and,foo]", StringUtils.splita("boo:and:foo",
':', 10));
- assertString("[boo,and:foo]", StringUtils.splita("boo:and:foo",
':', 2));
- assertString("[boo:and:foo]", StringUtils.splita("boo:and:foo",
':', 1));
- assertString("[boo:and:foo]", StringUtils.splita("boo:and:foo",
':', 0));
- assertString("[boo:and:foo]", StringUtils.splita("boo:and:foo",
':', -1));
- assertString("[boo,and,foo]", StringUtils.splita("boo : and :
foo", ':', 10));
- assertString("[boo,and : foo]", StringUtils.splita("boo : and :
foo", ':', 2));
- }
-
-
//====================================================================================================
- // nullIfEmpty(String)
-
//====================================================================================================
- @Test void a10_nullIfEmpty() {
- assertNull(StringUtils.nullIfEmpty(null));
- assertNull(StringUtils.nullIfEmpty(""));
- assertNotNull(StringUtils.nullIfEmpty("x"));
- }
-
-
//====================================================================================================
- // unescapeChars(String,char[],char)
-
//====================================================================================================
- @Test void a11_unescapeChars() {
- var escape = AsciiSet.of("\\,|");
-
- assertNull(unEscapeChars(null, escape));
- assertEquals("xxx", unEscapeChars("xxx", escape));
-
- assertEquals("xxx", unEscapeChars("xxx", escape));
- assertEquals("x,xx", unEscapeChars("x\\,xx", escape));
- assertEquals("x\\xx", unEscapeChars("x\\xx", escape));
- assertEquals("x\\,xx", unEscapeChars("x\\\\,xx", escape));
- assertEquals("x\\,xx", unEscapeChars("x\\\\\\,xx", escape));
- assertEquals("\\", unEscapeChars("\\", escape));
- assertEquals(",", unEscapeChars("\\,", escape));
- assertEquals("|", unEscapeChars("\\|", escape));
-
- escape = AsciiSet.of(",|");
- assertEquals("x\\\\xx", unEscapeChars("x\\\\xx", escape));
- }
-
-
//====================================================================================================
- // decodeHex(String)
-
//====================================================================================================
- @Test void a12_decodeHex() {
- assertNull(decodeHex(null));
- assertEquals("19azAZ", decodeHex("19azAZ"));
- assertEquals("[0][1][ffff]", decodeHex("\u0000\u0001\uFFFF"));
- }
-
-
//====================================================================================================
- // startsWith(String,char)
-
//====================================================================================================
- @Test void a13_startsWith() {
- assertFalse(startsWith(null, 'a'));
- assertFalse(startsWith("", 'a'));
- assertTrue(startsWith("a", 'a'));
- assertTrue(startsWith("ab", 'a'));
- }
-
-
//====================================================================================================
- // endsWith(String,char)
-
//====================================================================================================
- @Test void a14_endsWith() {
- assertFalse(endsWith(null, 'a'));
- assertFalse(endsWith("", 'a'));
- assertTrue(endsWith("a", 'a'));
- assertTrue(endsWith("ba", 'a'));
- }
-
-
//====================================================================================================
- // base64EncodeToString(String)
- // base64DecodeToString(String)
-
//====================================================================================================
- @Test void a15_base64EncodeToString() {
- assertNull(base64DecodeToString(base64EncodeToString(null)));
- assertEquals("",
base64DecodeToString(base64EncodeToString("")));
- assertEquals("foobar",
base64DecodeToString(base64EncodeToString("foobar")));
- assertEquals("\u0000\uffff",
base64DecodeToString(base64EncodeToString("\u0000\uffff")));
- assertThrowsWithMessage(IllegalArgumentException.class,
"Invalid BASE64 string length. Must be multiple of 4.", ()->base64Decode("a"));
- assertThrows(IllegalArgumentException.class,
()->base64Decode("aaa"));
- }
-
-
//====================================================================================================
- // generateUUID(String)
-
//====================================================================================================
- @Test void a16_generateUUID() {
- for (var i = 0; i < 10; i++) {
- var s = random(i);
- assertEquals(i, s.length());
- for (var c : s.toCharArray())
- assertTrue(Character.isLowerCase(c) ||
Character.isDigit(c));
- }
- }
-
-
//====================================================================================================
- // trim(String)
-
//====================================================================================================
- @Test void a17_trim() {
- assertNull(trim(null));
- assertEquals("", trim(""));
- assertEquals("", trim(" "));
- }
-
-
//====================================================================================================
- // parseISO8601Date(String)
-
//====================================================================================================
- @Test void a18_parseISO8601Date() throws Exception {
- assertNull(parseIsoDate(null));
- assertNull(parseIsoDate(""));
-
- setTimeZone("GMT");
- try {
- assertString("2000-01-01T00:00:00Z",
parseIsoDate("2000"));
- assertString("2000-02-01T00:00:00Z",
parseIsoDate("2000-02"));
- assertString("2000-02-03T00:00:00Z",
parseIsoDate("2000-02-03"));
- assertString("2000-02-03T04:00:00Z",
parseIsoDate("2000-02-03T04"));
- assertString("2000-02-03T04:05:00Z",
parseIsoDate("2000-02-03T04:05"));
- assertString("2000-02-03T04:05:06Z",
parseIsoDate("2000-02-03T04:05:06"));
- assertString("2000-02-03T04:00:00Z",
parseIsoDate("2000-02-03 04"));
- assertString("2000-02-03T04:05:00Z",
parseIsoDate("2000-02-03 04:05"));
- assertString("2000-02-03T04:05:06Z",
parseIsoDate("2000-02-03 04:05:06"));
- assertString("2000-02-03T04:05:06Z",
parseIsoDate("2000-02-03 04:05:06,789"));// ISO8601 doesn't support
milliseconds, so it gets trimmed.
- } finally {
- unsetTimeZone();
- }
- }
-
-
//====================================================================================================
- // parseMap(String,char,char,boolean)
-
//====================================================================================================
- @Test void a19_splitMap() {
- assertString("{a=1}", StringUtils.splitMap("a=1", true));
- assertString("{a=1,b=2}", StringUtils.splitMap("a=1,b=2",
true));
- assertString("{a=1,b=2}", StringUtils.splitMap(" a = 1 , b = 2
", true));
- assertString("{ a = 1 , b = 2 }", StringUtils.splitMap(" a = 1
, b = 2 ", false));
- assertString("{a=}", StringUtils.splitMap("a", true));
- assertString("{a=,b=}", StringUtils.splitMap("a,b", true));
- assertString("{a=1,b=}", StringUtils.splitMap("a=1,b", true));
- assertString("{a=,b=1}", StringUtils.splitMap("a,b=1", true));
- assertString("{a==1}", StringUtils.splitMap("a\\==1", true));
- assertString("{a\\=1}", StringUtils.splitMap("a\\\\=1", true));
- }
-
-
//====================================================================================================
- // isAbsoluteUri(String)
-
//====================================================================================================
- @Test void a10_isAbsoluteUri() {
- assertFalse(isAbsoluteUri(null));
- assertFalse(isAbsoluteUri(""));
- assertTrue(isAbsoluteUri("http://foo"));
- assertTrue(isAbsoluteUri("x://x"));
- assertFalse(isAbsoluteUri("xX://x"));
- assertFalse(isAbsoluteUri("x ://x"));
- assertFalse(isAbsoluteUri("x: //x"));
- assertFalse(isAbsoluteUri("x:/ /x"));
- assertFalse(isAbsoluteUri("x:x//x"));
- assertFalse(isAbsoluteUri("x:/x/x"));
- }
-
-
//====================================================================================================
- // getAuthorityUri(String)
-
//====================================================================================================
- @Test void a21_getAuthorityUri() {
- assertEquals("http://foo", getAuthorityUri("http://foo"));
- assertEquals("http://foo:123",
getAuthorityUri("http://foo:123"));
- assertEquals("http://foo:123",
getAuthorityUri("http://foo:123/"));
- assertEquals("http://foo:123",
getAuthorityUri("http://foo:123/bar"));
- }
-
-
//====================================================================================================
- // splitQuoted(String)
-
//====================================================================================================
- @Test void a22_splitQuoted() {
- assertNull(StringUtils.splitQuoted(null));
- assertEmpty(StringUtils.splitQuoted(""));
- assertEmpty(StringUtils.splitQuoted(" \t "));
- assertList(StringUtils.splitQuoted("foo"), "foo");
- assertList(StringUtils.splitQuoted("foo bar baz"), "foo",
"bar", "baz");
- assertList(StringUtils.splitQuoted("'foo'"), "foo");
- assertList(StringUtils.splitQuoted(" ' foo ' "), " foo ");
- assertList(StringUtils.splitQuoted("'foo' 'bar'"), "foo",
"bar");
- assertList(StringUtils.splitQuoted("\"foo\""), "foo");
- assertList(StringUtils.splitQuoted(" \" foo \" "), " foo ");
- assertList(StringUtils.splitQuoted("\"foo\" \"bar\""), "foo",
"bar");
- assertList(StringUtils.splitQuoted("'foo\\'bar'"), "foo'bar");
- assertList(StringUtils.splitQuoted("'foo\\\"bar'"), "foo\"bar");
- assertList(StringUtils.splitQuoted("'\\'foo\\'bar\\''"),
"'foo'bar'");
- assertList(StringUtils.splitQuoted("'\\\"foo\\\"bar\\\"'"),
"\"foo\"bar\"");
- assertList(StringUtils.splitQuoted("'\\'foo\\''"), "'foo'");
- assertList(StringUtils.splitQuoted("\"\\\"foo\\\"\""),
"\"foo\"");
- assertList(StringUtils.splitQuoted("'\"foo\"'"), "\"foo\"");
- assertList(StringUtils.splitQuoted("\"'foo'\""), "'foo'");
- }
-
-
//====================================================================================================
- // firstNonWhitespaceChar(String)
-
//====================================================================================================
- @Test void a23_firstNonWhitespaceChar() {
- assertEquals('f', firstNonWhitespaceChar("foo"));
- assertEquals('f', firstNonWhitespaceChar(" foo"));
- assertEquals('f', firstNonWhitespaceChar("\tfoo"));
- assertEquals(0, firstNonWhitespaceChar(""));
- assertEquals(0, firstNonWhitespaceChar(" "));
- assertEquals(0, firstNonWhitespaceChar("\t"));
- assertEquals(0, firstNonWhitespaceChar(null));
- }
-
-
//====================================================================================================
- // lastNonWhitespaceChar(String)
-
//====================================================================================================
- @Test void a24_lastNonWhitespaceChar() {
- assertEquals('r', lastNonWhitespaceChar("bar"));
- assertEquals('r', lastNonWhitespaceChar(" bar "));
- assertEquals('r', lastNonWhitespaceChar("\tbar\t"));
- assertEquals(0, lastNonWhitespaceChar(""));
- assertEquals(0, lastNonWhitespaceChar(" "));
- assertEquals(0, lastNonWhitespaceChar("\t"));
- assertEquals(0, lastNonWhitespaceChar(null));
- }
-
-
//====================================================================================================
- // testIsJsonObject(Object)
-
//====================================================================================================
- @Test void a25_isJsonObject() {
- assertTrue(isJsonObject("{foo:'bar'}", true));
- assertTrue(isJsonObject(" { foo:'bar' } ", true));
- assertFalse(isJsonObject(" { foo:'bar' ", true));
- assertFalse(isJsonObject(" foo:'bar' } ", true));
- assertTrue(isJsonObject("/*foo*/ { foo:'bar' } /*foo*/", true));
- }
-
-
//====================================================================================================
- // isJsonArray(Object)
-
//====================================================================================================
- @Test void a26_isJsonArray() {
- assertTrue(isJsonArray("[123,'bar']", true));
- assertTrue(isJsonArray(" [ 123,'bar' ] ", true));
- assertFalse(isJsonArray(" [ 123,'bar' ", true));
- assertFalse(isJsonArray(" 123,'bar' ] ", true));
- assertTrue(isJsonArray("/*foo*/ [ 123,'bar' ] /*foo*/", true));
- }
-
-
//====================================================================================================
- // addLineNumbers(String)
-
//====================================================================================================
- @Test void a27_addLineNumbers() {
- assertNull(getNumberedLines(null));
- assertEquals("1: \n", getNumberedLines(""));
- assertEquals("1: foo\n", getNumberedLines("foo"));
- assertEquals("1: foo\n2: bar\n", getNumberedLines("foo\nbar"));
- }
-
-
//====================================================================================================
- // compare(String,String)
-
//====================================================================================================
- @Test void a28_compare() {
- assertTrue(compare("a","b") < 0);
- assertTrue(compare("b","a") > 0);
- assertTrue(compare(null,"b") < 0);
- assertTrue(compare("b",null) > 0);
- assertEquals(0, compare(null,null));
- }
-
-
//====================================================================================================
- // matchPattern(String)
-
//====================================================================================================
- @Test void a29_getMatchPattern() {
-
assertTrue(StringUtils.getMatchPattern("a").matcher("a").matches());
-
assertTrue(StringUtils.getMatchPattern("*a*").matcher("aaa").matches());
-
assertFalse(StringUtils.getMatchPattern("*b*").matcher("aaa").matches());
- }
-
-
//====================================================================================================
- // getDuration(String)
-
//====================================================================================================
- @Test void a30_getDuration() {
- assertEquals(-1, getDuration(null));
- assertEquals(-1, getDuration(""));
- assertEquals(-1, getDuration(" "));
- assertEquals(1, getDuration("1"));
- assertEquals(10, getDuration("10"));
- assertEquals(10, getDuration("10"));
-
- long
- s = 1000,
- m = s * 60,
- h = m * 60,
- d = h * 24,
- w = d * 7;
-
- assertEquals(10*s, getDuration("10s"));
- assertEquals(10*s, getDuration("10 s"));
- assertEquals(10*s, getDuration(" 10 s "));
- assertEquals(10*s, getDuration("10sec"));
- assertEquals(10*s, getDuration("10 sec"));
- assertEquals(10*s, getDuration(" 10 sec "));
- assertEquals(10*s, getDuration("10seconds"));
- assertEquals(10*s, getDuration("10 seconds"));
- assertEquals(10*s, getDuration(" 10 seconds "));
- assertEquals(10*s, getDuration("10S"));
- assertEquals(10*s, getDuration("10 S"));
- assertEquals(10*s, getDuration(" 10 S "));
-
- assertEquals(10*m, getDuration("10m"));
- assertEquals(10*m, getDuration("10 m"));
- assertEquals(10*m, getDuration(" 10 m "));
- assertEquals(10*m, getDuration("10min"));
- assertEquals(10*m, getDuration("10 min"));
- assertEquals(10*m, getDuration(" 10 min "));
- assertEquals(10*m, getDuration("10minutes"));
- assertEquals(10*m, getDuration("10 minutes"));
- assertEquals(10*m, getDuration(" 10 minutes "));
- assertEquals(10*m, getDuration("10M"));
- assertEquals(10*m, getDuration("10 M"));
- assertEquals(10*m, getDuration(" 10 M "));
-
- assertEquals(10*h, getDuration("10h"));
- assertEquals(10*h, getDuration("10 h"));
- assertEquals(10*h, getDuration(" 10 h "));
- assertEquals(10*h, getDuration("10hour"));
- assertEquals(10*h, getDuration("10 hour"));
- assertEquals(10*h, getDuration(" 10 hour "));
- assertEquals(10*h, getDuration("10hours"));
- assertEquals(10*h, getDuration("10 hours"));
- assertEquals(10*h, getDuration(" 10 hours "));
- assertEquals(10*h, getDuration("10H"));
- assertEquals(10*h, getDuration("10 H"));
- assertEquals(10*h, getDuration(" 10 H "));
-
- assertEquals(10*d, getDuration("10d"));
- assertEquals(10*d, getDuration("10 d"));
- assertEquals(10*d, getDuration(" 10 d "));
- assertEquals(10*d, getDuration("10day"));
- assertEquals(10*d, getDuration("10 day"));
- assertEquals(10*d, getDuration(" 10 day "));
- assertEquals(10*d, getDuration("10days"));
- assertEquals(10*d, getDuration("10 days"));
- assertEquals(10*d, getDuration(" 10 days "));
- assertEquals(10*d, getDuration("10D"));
- assertEquals(10*d, getDuration("10 D"));
- assertEquals(10*d, getDuration(" 10 D "));
-
- assertEquals(10*w, getDuration("10w"));
- assertEquals(10*w, getDuration("10 w"));
- assertEquals(10*w, getDuration(" 10 w "));
- assertEquals(10*w, getDuration("10week"));
- assertEquals(10*w, getDuration("10 week"));
- assertEquals(10*w, getDuration(" 10 week "));
- assertEquals(10*w, getDuration("10weeks"));
- assertEquals(10*w, getDuration("10 weeks"));
- assertEquals(10*w, getDuration(" 10 weeks "));
- assertEquals(10*w, getDuration("10W"));
- assertEquals(10*w, getDuration("10 W"));
- assertEquals(10*w, getDuration(" 10 W "));
- }
-
-
//====================================================================================================
- // getDuration(String)
-
//====================================================================================================
- @Test void a31_stripInvalidHttpHeaderChars() {
- assertEquals("xxx", stripInvalidHttpHeaderChars("xxx"));
- assertEquals("\t []^x",
stripInvalidHttpHeaderChars("\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u0020\\[]^x"));
- }
-
-
//====================================================================================================
- // abbreviate(String,int)
-
//====================================================================================================
- @Test void a32_abbrevate() {
- assertNull(abbreviate(null, 0));
- assertEquals("foo", abbreviate("foo", 3));
- assertEquals("...", abbreviate("fooo", 3));
- assertEquals("f...", abbreviate("foooo", 4));
- assertEquals("foo", abbreviate("foo", 2));
- }
-
-
//====================================================================================================
- // splitMethodArgs(String)
-
//====================================================================================================
- @Test void a33_splitMethodArgs() {
- assertList(StringUtils.splitMethodArgs("java.lang.String"),
"java.lang.String");
-
assertList(StringUtils.splitMethodArgs("java.lang.String,java.lang.Integer"),
"java.lang.String", "java.lang.Integer");
- assertList(StringUtils.splitMethodArgs("x,y"), "x","y");
- assertList(StringUtils.splitMethodArgs("x,y<a,b>,z"), "x",
"y<a,b>", "z");
- assertList(StringUtils.splitMethodArgs("x,y<a<b,c>,d<e,f>>,z"),
"x", "y<a<b,c>,d<e,f>>", "z");
- }
-
-
//====================================================================================================
- // fixUrl(String)
-
//====================================================================================================
- @Test void a34_fixUrl() {
- assertEquals(null, fixUrl(null));
- assertEquals("", fixUrl(""));
- assertEquals("xxx", fixUrl("xxx"));
- assertEquals("+x+x+", fixUrl(" x x "));
- assertEquals("++x++x++", fixUrl(" x x "));
- assertEquals("foo%7Bbar%7Dbaz", fixUrl("foo{bar}baz"));
- assertEquals("%7Dfoo%7Bbar%7Dbaz%7B", fixUrl("}foo{bar}baz{"));
- }
-
-
//====================================================================================================
- // diffPosition(String,String)
-
//====================================================================================================
- @Test void a35_diffPosition() {
- assertEquals(-1, diffPosition("a", "a"));
- assertEquals(-1, diffPosition(null, null));
- assertEquals(0, diffPosition("a", "b"));
- assertEquals(1, diffPosition("aa", "ab"));
- assertEquals(1, diffPosition("aaa", "ab"));
- assertEquals(1, diffPosition("aa", "abb"));
- assertEquals(0, diffPosition("a", null));
- assertEquals(0, diffPosition(null, "b"));
- }
-
-
//====================================================================================================
- // diffPositionIc(String,String)
-
//====================================================================================================
- @Test void a36_diffPositionIc() {
- assertEquals(-1, diffPositionIc("a", "a"));
- assertEquals(-1, diffPositionIc("a", "A"));
- assertEquals(-1, diffPositionIc(null, null));
- assertEquals(0, diffPositionIc("a", "b"));
- assertEquals(1, diffPositionIc("aa", "Ab"));
- assertEquals(1, diffPositionIc("aaa", "Ab"));
- assertEquals(1, diffPositionIc("aa", "Abb"));
- assertEquals(0, diffPositionIc("a", null));
- assertEquals(0, diffPositionIc(null, "b"));
- }
-
-
//====================================================================================================
- // splitNested(String)
-
//====================================================================================================
- @Test void a37_splitNested() {
- assertNull(StringUtils.splitNested(null));
- assertEmpty(StringUtils.splitNested(""));
- assertList(StringUtils.splitNested("a"), "a");
- assertList(StringUtils.splitNested("a,b,c"), "a", "b", "c");
- assertList(StringUtils.splitNested("a{b,c},d"), "a{b,c}", "d");
- assertList(StringUtils.splitNested("a,b{c,d}"), "a", "b{c,d}");
- assertList(StringUtils.splitNested("a,b{c,d{e,f}}"), "a",
"b{c,d{e,f}}");
- assertList(StringUtils.splitNested("a { b , c } , d "), "a { b
, c }", "d");
- assertList(StringUtils.splitNested("a\\,b"), "a,b");
- assertList(StringUtils.splitNested("a\\\\,b"), "a\\", "b");
- }
-
-
//====================================================================================================
- // splitNestedInner(String)
-
//====================================================================================================
- @Test void a38_splitNestedInner() {
- assertThrowsWithMessage(IllegalArgumentException.class, "String
was null.", ()->StringUtils.splitNestedInner(null));
- assertThrowsWithMessage(IllegalArgumentException.class, "String
was empty.", ()->StringUtils.splitNestedInner(""));
- assertList(StringUtils.splitNestedInner("a{b}"), "b");
- assertList(StringUtils.splitNestedInner(" a { b } "), "b");
- assertList(StringUtils.splitNestedInner("a{b,c}"), "b", "c");
- assertList(StringUtils.splitNestedInner("a{b{c,d},e{f,g}}"),
"b{c,d}", "e{f,g}");
- }
-
-
//====================================================================================================
- // toHex2(int)
-
//====================================================================================================
- @Test void a38_toHex2() {
- // Test zero
- assertString("00", toHex2(0));
-
- // Test small positive numbers
- assertString("01", toHex2(1));
- assertString("0F", toHex2(15));
- assertString("10", toHex2(16));
- assertString("FF", toHex2(255));
-
- // Test maximum valid value
- assertString("FF", toHex2(255));
-
- // Test values outside valid range - should throw exception
- assertThrowsWithMessage(NumberFormatException.class, "toHex2
can only be used on numbers between 0 and 255", ()->toHex2(256));
- assertThrowsWithMessage(NumberFormatException.class, "toHex2
can only be used on numbers between 0 and 255", ()->toHex2(511));
- assertThrowsWithMessage(NumberFormatException.class, "toHex2
can only be used on numbers between 0 and 255", ()->toHex2(Integer.MAX_VALUE));
-
- // Test negative numbers - should throw exception
- assertThrowsWithMessage(NumberFormatException.class, "toHex2
can only be used on numbers between 0 and 255", ()->toHex2(-1));
- assertThrowsWithMessage(NumberFormatException.class, "toHex2
can only be used on numbers between 0 and 255", ()->toHex2(-100));
- assertThrowsWithMessage(NumberFormatException.class, "toHex2
can only be used on numbers between 0 and 255", ()->toHex2(Integer.MIN_VALUE));
-
- // Test edge cases
- assertString("0A", toHex2(10));
- assertString("0B", toHex2(11));
- assertString("0C", toHex2(12));
- assertString("0D", toHex2(13));
- assertString("0E", toHex2(14));
- }
-
-
//====================================================================================================
- // toHex4(int)
-
//====================================================================================================
- @Test void a39_toHex4() {
- // Test zero
- assertString("0000", toHex4(0));
-
- // Test small positive numbers
- assertString("0001", toHex4(1));
- assertString("000F", toHex4(15));
- assertString("0010", toHex4(16));
- assertString("00FF", toHex4(255));
-
- // Test larger numbers
- assertString("0100", toHex4(256));
- assertString("1000", toHex4(4096));
- assertString("FFFF", toHex4(65535));
-
- // Test maximum 16-bit value
- assertString("FFFF", toHex4(65535));
-
- // Test larger values (these get truncated to 4 hex characters)
- assertString("0000", toHex4(65536));
- assertString("FFFF", toHex4(1048575));
-
- // Test maximum int value (this gets truncated to 4 hex
characters)
- assertString("FFFF", toHex4(Integer.MAX_VALUE));
-
- // Test negative numbers - should throw exception
- assertThrowsWithMessage(NumberFormatException.class, "toHex4
can only be used on non-negative numbers", ()->toHex4(-1));
- assertThrowsWithMessage(NumberFormatException.class, "toHex4
can only be used on non-negative numbers", ()->toHex4(-100));
- assertThrowsWithMessage(NumberFormatException.class, "toHex4
can only be used on non-negative numbers", ()->toHex4(Integer.MIN_VALUE));
-
- // Test edge cases
- assertString("000A", toHex4(10));
- assertString("000B", toHex4(11));
- assertString("000C", toHex4(12));
- assertString("000D", toHex4(13));
- assertString("000E", toHex4(14));
- }
-
-
//====================================================================================================
- // toHex8(long)
-
//====================================================================================================
- @Test void a40_toHex8() {
- // Test zero
- assertString("00000000", toHex8(0));
-
- // Test small positive numbers
- assertString("00000001", toHex8(1));
- assertString("0000000F", toHex8(15));
- assertString("00000010", toHex8(16));
- assertString("000000FF", toHex8(255));
-
- // Test larger numbers
- assertString("00000100", toHex8(256));
- assertString("00001000", toHex8(4096));
- assertString("00010000", toHex8(65536));
- assertString("00100000", toHex8(1048576));
- assertString("01000000", toHex8(16777216));
- assertString("10000000", toHex8(268435456));
-
- // Test maximum 32-bit value
- assertString("FFFFFFFF", toHex8(4294967295L));
-
- // Test larger values (these get truncated to 8 hex characters)
- assertString("00000000", toHex8(4294967296L));
- assertString("FFFFFFFF", toHex8(68719476735L));
-
- // Test maximum long value (this gets truncated to 8 hex
characters)
- assertString("FFFFFFFF", toHex8(Long.MAX_VALUE));
-
- // Test negative numbers - should throw exception
- assertThrowsWithMessage(NumberFormatException.class, "toHex8
can only be used on non-negative numbers", ()->toHex8(-1));
- assertThrowsWithMessage(NumberFormatException.class, "toHex8
can only be used on non-negative numbers", ()->toHex8(-100));
- assertThrowsWithMessage(NumberFormatException.class, "toHex8
can only be used on non-negative numbers", ()->toHex8(Long.MIN_VALUE));
-
- // Test edge cases
- assertString("0000000A", toHex8(10));
- assertString("0000000B", toHex8(11));
- assertString("0000000C", toHex8(12));
- assertString("0000000D", toHex8(13));
- assertString("0000000E", toHex8(14));
- }
-
-
//====================================================================================================
- // String validation methods
-
//====================================================================================================
-
- @Test void a41_isBlank() {
- assertTrue(StringUtils.isBlank(null));
- assertTrue(StringUtils.isBlank(""));
- assertTrue(StringUtils.isBlank(" "));
- assertTrue(StringUtils.isBlank("\t\n"));
- assertFalse(StringUtils.isBlank("hello"));
- assertFalse(StringUtils.isBlank(" hello "));
- assertFalse(StringUtils.isBlank("a"));
- }
-
- @Test void a42_isNotBlank() {
- assertFalse(isNotBlank(null));
- assertFalse(isNotBlank(""));
- assertFalse(isNotBlank(" "));
- assertFalse(isNotBlank("\t\n"));
- assertTrue(isNotBlank("hello"));
- assertTrue(isNotBlank(" hello "));
- assertTrue(isNotBlank("a"));
- }
-
- @Test void a43_isEmpty() {
- assertTrue(Utils.isEmpty((String)null));
- assertTrue(Utils.isEmpty(""));
- assertFalse(Utils.isEmpty(" "));
- assertFalse(Utils.isEmpty("hello"));
- assertFalse(Utils.isEmpty("a"));
- }
-
- @Test void a44_hasText() {
- assertFalse(hasText(null));
- assertFalse(hasText(""));
- assertFalse(hasText(" "));
- assertFalse(hasText("\t\n"));
- assertTrue(hasText("hello"));
- assertTrue(hasText(" hello "));
- assertTrue(hasText("a"));
- }
-
- @Test void a45_isAlpha() {
- assertFalse(isAlpha(null));
- assertFalse(isAlpha(""));
- assertTrue(isAlpha("abc"));
- assertTrue(isAlpha("ABC"));
- assertTrue(isAlpha("AbCdEf"));
- assertFalse(isAlpha("abc123"));
- assertFalse(isAlpha("abc def"));
- assertFalse(isAlpha("abc-def"));
- assertFalse(isAlpha("123"));
- }
-
- @Test void a46_isAlphaNumeric() {
- assertFalse(isAlphaNumeric(null));
- assertFalse(isAlphaNumeric(""));
- assertTrue(isAlphaNumeric("abc"));
- assertTrue(isAlphaNumeric("123"));
- assertTrue(isAlphaNumeric("abc123"));
- assertTrue(isAlphaNumeric("ABC123"));
- assertFalse(isAlphaNumeric("abc def"));
- assertFalse(isAlphaNumeric("abc-123"));
- assertFalse(isAlphaNumeric("abc_123"));
- }
-
- @Test void a47_isDigit() {
- assertFalse(isDigit(null));
- assertFalse(isDigit(""));
- assertTrue(isDigit("123"));
- assertTrue(isDigit("0"));
- assertTrue(isDigit("999"));
- assertFalse(isDigit("abc"));
- assertFalse(isDigit("abc123"));
- assertFalse(isDigit("12.3"));
- assertFalse(isDigit("12-3"));
- }
-
- @Test void a48_isWhitespace() {
- assertFalse(isWhitespace(null));
- assertTrue(isWhitespace(""));
- assertTrue(isWhitespace(" "));
- assertTrue(isWhitespace("\t\n"));
- assertTrue(isWhitespace("\r\n\t "));
- assertFalse(isWhitespace(" a "));
- assertFalse(isWhitespace("hello"));
- }
-
-
//====================================================================================================
- // String manipulation methods
-
//====================================================================================================
-
- @Test void a49_capitalize() {
- assertNull(capitalize(null));
- assertEquals("", capitalize(""));
- assertEquals("Hello", capitalize("hello"));
- assertEquals("Hello", capitalize("Hello"));
- assertEquals("HELLO", capitalize("HELLO"));
- assertEquals("A", capitalize("a"));
- assertEquals("123", capitalize("123"));
- }
-
- @Test void a50_uncapitalize() {
- assertNull(uncapitalize(null));
- assertEquals("", uncapitalize(""));
- assertEquals("hello", uncapitalize("hello"));
- assertEquals("hello", uncapitalize("Hello"));
- assertEquals("hELLO", uncapitalize("HELLO"));
- assertEquals("a", uncapitalize("A"));
- assertEquals("123", uncapitalize("123"));
- }
-
- @Test void a51_reverse() {
- assertNull(StringUtils.reverse(null));
- assertEquals("", reverse(""));
- assertEquals("olleh", reverse("hello"));
- assertEquals("321", reverse("123"));
- assertEquals("cba", reverse("abc"));
- }
-
- @Test void a52_remove() {
- assertNull(remove(null, "x"));
- assertEquals("hello", remove("hello", null));
- assertEquals("hello", remove("hello", ""));
- assertEquals("hell wrld", remove("hello world", "o"));
- assertEquals("hello world", remove("hello world", "xyz"));
- assertEquals("", remove("xxx", "x"));
- }
-
- @Test void a53_removeStart() {
- assertNull(removeStart(null, "x"));
- assertEquals("hello", removeStart("hello", null));
- assertEquals("hello", removeStart("hello", ""));
- assertEquals(" world", removeStart("hello world", "hello"));
- assertEquals("hello world", removeStart("hello world", "xyz"));
- assertEquals("", removeStart("hello", "hello"));
- }
-
- @Test void a54_removeEnd() {
- assertNull(removeEnd(null, "x"));
- assertEquals("hello", removeEnd("hello", null));
- assertEquals("hello", removeEnd("hello", ""));
- assertEquals("hello ", removeEnd("hello world", "world"));
- assertEquals("hello world", removeEnd("hello world", "xyz"));
- assertEquals("", removeEnd("hello", "hello"));
- }
-
- @Test void a55_substringBefore() {
- assertNull(substringBefore(null, "."));
- assertEquals("hello.world", substringBefore("hello.world",
null));
- assertEquals("hello", substringBefore("hello.world", "."));
- assertEquals("hello.world", substringBefore("hello.world",
"xyz"));
- assertEquals("", substringBefore(".world", "."));
- }
-
- @Test void a56_substringAfter() {
- assertNull(substringAfter(null, "."));
- assertEquals("", substringAfter("hello.world", null));
- assertEquals("world", substringAfter("hello.world", "."));
- assertEquals("", substringAfter("hello.world", "xyz"));
- assertEquals("world", substringAfter("hello.world", "."));
- }
-
- @Test void a57_substringBetween() {
- assertNull(substringBetween(null, "<", ">"));
- assertNull(substringBetween("<hello>", null, ">"));
- assertNull(substringBetween("<hello>", "<", null));
- assertEquals("hello", substringBetween("<hello>", "<", ">"));
- assertNull(substringBetween("<hello>", "[", "]"));
- assertNull(substringBetween("hello", "<", ">"));
- assertEquals("", substringBetween("<>", "<", ">"));
- }
-
- @Test void a58_left() {
- assertNull(left(null, 3));
- assertEquals("", left("", 3));
- assertEquals("hel", left("hello", 3));
- assertEquals("hello", left("hello", 10));
- assertEquals("", left("hello", 0));
- assertEquals("", left("hello", -1));
- }
-
- @Test void a59_right() {
- assertNull(right(null, 3));
- assertEquals("", right("", 3));
- assertEquals("llo", right("hello", 3));
- assertEquals("hello", right("hello", 10));
- assertEquals("", right("hello", 0));
- assertEquals("", right("hello", -1));
- }
-
- @Test void a60_mid() {
- assertNull(mid(null, 1, 3));
- assertEquals("", mid("", 1, 3));
- assertEquals("ell", mid("hello", 1, 3));
- assertEquals("ello", mid("hello", 1, 10));
- assertEquals("", mid("hello", 10, 3));
- assertEquals("", mid("hello", -1, 3));
- assertEquals("", mid("hello", 1, -1));
- }
-
- @Test void a61_padLeft() {
- assertEquals(" ", padLeft(null, 5, ' '));
- assertEquals(" ", padLeft("", 5, ' '));
- assertEquals(" hello", padLeft("hello", 8, ' '));
- assertEquals("hello", padLeft("hello", 3, ' '));
- assertEquals("00123", padLeft("123", 5, '0'));
- }
-
- @Test void a62_padRight() {
- assertEquals(" ", padRight(null, 5, ' '));
- assertEquals(" ", padRight("", 5, ' '));
- assertEquals("hello ", padRight("hello", 8, ' '));
- assertEquals("hello", padRight("hello", 3, ' '));
- assertEquals("12300", padRight("123", 5, '0'));
- }
-
- @Test void a63_padCenter() {
- assertEquals(" ", padCenter(null, 5, ' '));
- assertEquals(" ", padCenter("", 5, ' '));
- assertEquals(" hi ", padCenter("hi", 6, ' '));
- assertEquals(" hi ", padCenter("hi", 7, ' '));
- assertEquals("hello", padCenter("hello", 3, ' '));
- assertEquals(" hello ", padCenter("hello", 7, ' '));
- }
-
-
//====================================================================================================
- // String joining and splitting methods
-
//====================================================================================================
-
- @Test void a64_joinObjectArray() {
- assertNull(StringUtils.join((Object[])null, ","));
- assertEquals("", StringUtils.join(a(), ","));
- assertEquals("a,b,c", StringUtils.join(a("a", "b", "c"), ","));
- assertEquals("1-2-3", StringUtils.join(a(1, 2, 3), "-"));
- assertEquals("abc", StringUtils.join(a("a", "b", "c"), ""));
- assertEquals("a,null,c", StringUtils.join(a("a", null, "c"),
","));
- assertEquals("a;b;c", StringUtils.join(a("a", "b", "c"), ";"));
- }
-
- @Test void a65_joinIntArray() {
- assertEquals("", StringUtils.join((int[])null, ","));
- assertEquals("", StringUtils.join(ints(), ","));
- assertEquals("1,2,3", StringUtils.join(ints(1, 2, 3), ","));
- assertEquals("1-2-3", StringUtils.join(ints(1, 2, 3), "-"));
- assertEquals("123", StringUtils.join(ints(1, 2, 3), ""));
- }
-
- @Test void a66_joinCollection() {
- assertNull(StringUtils.join((Collection<?>)null, ","));
- assertEquals("", StringUtils.join(Collections.emptyList(),
","));
- assertEquals("a,b,c", StringUtils.join(l("a", "b", "c"), ","));
- assertEquals("1-2-3", StringUtils.join(l(1, 2, 3), "-"));
- assertEquals("a,null,c", StringUtils.join(l("a", null, "c"),
","));
- }
-
- @Test void a67_joinObjectArrayChar() {
- assertEquals("a,b,c", StringUtils.join(ao("a", "b", "c"), ','));
- assertEquals("1-2-3", StringUtils.join(ao(1, 2, 3), '-'));
- }
-
- @Test void a68_joinIntArrayChar() {
- assertEquals("1,2,3", StringUtils.join(ints(1, 2, 3), ','));
- assertEquals("1-2-3", StringUtils.join(ints(1, 2, 3), '-'));
- }
-
- @Test void a69_joinCollectionChar() {
- assertEquals("a,b,c", StringUtils.join(l("a", "b", "c"), ','));
- assertEquals("1-2-3", StringUtils.join(l(1, 2, 3), '-'));
- }
-
-
//====================================================================================================
- // String cleaning and sanitization methods
-
//====================================================================================================
-
- @Test void a72_clean() {
- assertNull(clean(null));
- assertEquals("", clean(""));
- assertEquals("hello world", clean("hello\u0000\u0001world"));
- assertEquals("hello world", clean("hello \t\n world"));
- assertEquals("test", clean("test"));
- }
-
- @Test void a73_normalizeWhitespace() {
- assertNull(normalizeWhitespace(null));
- assertEquals("", normalizeWhitespace(""));
- assertEquals("hello world", normalizeWhitespace("hello \t\n
world"));
- assertEquals("hello world", normalizeWhitespace(" hello world
"));
- assertEquals("a b c", normalizeWhitespace("a b c"));
- }
-
- @Test void a74_removeControlChars() {
- assertNull(removeControlChars(null));
- assertEquals("", removeControlChars(""));
- assertEquals("hello world",
removeControlChars("hello\u0000\u0001world"));
- assertEquals("hello\nworld",
removeControlChars("hello\nworld"));
- assertEquals("test", removeControlChars("test"));
- }
-
- @Test void a75_removeNonPrintable() {
- assertNull(removeNonPrintable(null));
- assertEquals("", removeNonPrintable(""));
- assertEquals("helloworld",
removeNonPrintable("hello\u0000world"));
- assertEquals("test", removeNonPrintable("test"));
- }
-
- @Test void a76_swapCase() {
- assertNull(swapCase(null));
- assertEquals("", swapCase(""));
- assertEquals("hELLO wORLD", swapCase("Hello World"));
- assertEquals("abc123XYZ", swapCase("ABC123xyz"));
- assertEquals("123", swapCase("123"));
- }
-}
\ No newline at end of file