You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by gi...@apache.org on 2025/12/02 14:24:02 UTC

(juneau) branch asf-staging updated: Deploy documentation staging from e77a2d1277f2ca0c40eb5086ea555fccbb20a7ff e77a2d1277f2ca0c40eb5086ea555fccbb20a7ff

This is an automated email from the ASF dual-hosted git repository.

github-bot pushed a commit to branch asf-staging
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/asf-staging by this push:
     new e9cf42f399 Deploy documentation staging from e77a2d1277f2ca0c40eb5086ea555fccbb20a7ff e77a2d1277f2ca0c40eb5086ea555fccbb20a7ff
e9cf42f399 is described below

commit e9cf42f399f5b85dc733da36d6d0f1ab0a9cd0fa
Author: github-actions[bot] <gi...@users.noreply.github.com>
AuthorDate: Tue Dec 2 14:23:56 2025 +0000

    Deploy documentation staging from e77a2d1277f2ca0c40eb5086ea555fccbb20a7ff e77a2d1277f2ca0c40eb5086ea555fccbb20a7ff
---
 .../juneau/commons/utils/StringUtils_Test.html     |  711 ++++----
 .../apache/juneau/commons/utils/StringUtils.html   | 1783 ++++++++++----------
 2 files changed, 1247 insertions(+), 1247 deletions(-)

diff --git a/site/xref-test/org/apache/juneau/commons/utils/StringUtils_Test.html b/site/xref-test/org/apache/juneau/commons/utils/StringUtils_Test.html
index 30e62a2057..f0dca63126 100644
--- a/site/xref-test/org/apache/juneau/commons/utils/StringUtils_Test.html
+++ b/site/xref-test/org/apache/juneau/commons/utils/StringUtils_Test.html
@@ -6571,360 +6571,363 @@
 <a class="jxr_linenumber" name="L6563" href="#L6563">6563</a> 		<em class="jxr_comment">// - First '\' sees second '\', appends '\' and skips second '\'</em>
 <a class="jxr_linenumber" name="L6564" href="#L6564">6564</a> 		<em class="jxr_comment">// - Then appends the second '\' from the string, then 'b'</em>
 <a class="jxr_linenumber" name="L6565" href="#L6565">6565</a> 		<em class="jxr_comment">// Result: "a&#92;&#92;&#92;&#92;b" (both backslashes preserved)</em>
-<a class="jxr_linenumber" name="L6566" href="#L6566">6566</a> 		assertEquals(<span class="jxr_string">"a&#92;&#92;&#92;&#92;b"</span>, unescapeChars(<span class="jxr_string">"a&#92;&#92;&#92;&#92;b"</span>, AsciiSet.of(<span class="jxr_string">","</span>))); <em class="jxr_comment">// '\' not in escaped set</em>
-<a class="jxr_linenumber" name="L6567" href="#L6567">6567</a> 	}
-<a class="jxr_linenumber" name="L6568" href="#L6568">6568</a> 
-<a class="jxr_linenumber" name="L6569" href="#L6569">6569</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6570" href="#L6570">6570</a> 	<em class="jxr_comment">// unescapeHtml(String)</em>
-<a class="jxr_linenumber" name="L6571" href="#L6571">6571</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6572" href="#L6572">6572</a> 	@Test
-<a class="jxr_linenumber" name="L6573" href="#L6573">6573</a> 	<strong class="jxr_keyword">void</strong> a223_unescapeHtml() {
-<a class="jxr_linenumber" name="L6574" href="#L6574">6574</a> 		assertNull(unescapeHtml(<strong class="jxr_keyword">null</strong>));
-<a class="jxr_linenumber" name="L6575" href="#L6575">6575</a> 		assertEquals(<span class="jxr_string">""</span>, unescapeHtml(<span class="jxr_string">""</span>));
-<a class="jxr_linenumber" name="L6576" href="#L6576">6576</a> 		assertEquals(<span class="jxr_string">"Hello World"</span>, unescapeHtml(<span class="jxr_string">"Hello World"</span>));
-<a class="jxr_linenumber" name="L6577" href="#L6577">6577</a> 		assertEquals(<span class="jxr_string">"&lt;script&gt;"</span>, unescapeHtml(<span class="jxr_string">"&amp;lt;script&amp;gt;"</span>));
-<a class="jxr_linenumber" name="L6578" href="#L6578">6578</a> 		assertEquals(<span class="jxr_string">"\&quot;Hello\&quot;"</span>, unescapeHtml(<span class="jxr_string">"&amp;quot;Hello&amp;quot;"</span>));
-<a class="jxr_linenumber" name="L6579" href="#L6579">6579</a> 		assertEquals(<span class="jxr_string">"It's a test"</span>, unescapeHtml(<span class="jxr_string">"It&amp;#39;s a test"</span>));
-<a class="jxr_linenumber" name="L6580" href="#L6580">6580</a> 		assertEquals(<span class="jxr_string">"It's a test"</span>, unescapeHtml(<span class="jxr_string">"It&amp;apos;s a test"</span>));
-<a class="jxr_linenumber" name="L6581" href="#L6581">6581</a> 		assertEquals(<span class="jxr_string">"&amp;"</span>, unescapeHtml(<span class="jxr_string">"&amp;amp;"</span>));
-<a class="jxr_linenumber" name="L6582" href="#L6582">6582</a> 		assertEquals(<span class="jxr_string">"&lt;tag&gt;text&lt;/tag&gt;"</span>, unescapeHtml(<span class="jxr_string">"&amp;lt;tag&amp;gt;text&amp;lt;/tag&amp;gt;"</span>));
-<a class="jxr_linenumber" name="L6583" href="#L6583">6583</a> 		<em class="jxr_comment">// Test round-trip</em>
-<a class="jxr_linenumber" name="L6584" href="#L6584">6584</a> 		assertEquals(<span class="jxr_string">"Hello &amp; World"</span>, unescapeHtml(escapeHtml(<span class="jxr_string">"Hello &amp; World"</span>)));
-<a class="jxr_linenumber" name="L6585" href="#L6585">6585</a> 	}
-<a class="jxr_linenumber" name="L6586" href="#L6586">6586</a> 
-<a class="jxr_linenumber" name="L6587" href="#L6587">6587</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6588" href="#L6588">6588</a> 	<em class="jxr_comment">// unescapeXml(String)</em>
-<a class="jxr_linenumber" name="L6589" href="#L6589">6589</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6590" href="#L6590">6590</a> 	@Test
-<a class="jxr_linenumber" name="L6591" href="#L6591">6591</a> 	<strong class="jxr_keyword">void</strong> a224_unescapeXml() {
-<a class="jxr_linenumber" name="L6592" href="#L6592">6592</a> 		assertNull(unescapeXml(<strong class="jxr_keyword">null</strong>));
-<a class="jxr_linenumber" name="L6593" href="#L6593">6593</a> 		assertEquals(<span class="jxr_string">""</span>, unescapeXml(<span class="jxr_string">""</span>));
-<a class="jxr_linenumber" name="L6594" href="#L6594">6594</a> 		assertEquals(<span class="jxr_string">"Hello World"</span>, unescapeXml(<span class="jxr_string">"Hello World"</span>));
-<a class="jxr_linenumber" name="L6595" href="#L6595">6595</a> 		assertEquals(<span class="jxr_string">"&lt;tag&gt;"</span>, unescapeXml(<span class="jxr_string">"&amp;lt;tag&amp;gt;"</span>));
-<a class="jxr_linenumber" name="L6596" href="#L6596">6596</a> 		assertEquals(<span class="jxr_string">"\&quot;Hello\&quot;"</span>, unescapeXml(<span class="jxr_string">"&amp;quot;Hello&amp;quot;"</span>));
-<a class="jxr_linenumber" name="L6597" href="#L6597">6597</a> 		assertEquals(<span class="jxr_string">"'test'"</span>, unescapeXml(<span class="jxr_string">"&amp;apos;test&amp;apos;"</span>));
-<a class="jxr_linenumber" name="L6598" href="#L6598">6598</a> 		assertEquals(<span class="jxr_string">"&amp;"</span>, unescapeXml(<span class="jxr_string">"&amp;amp;"</span>));
-<a class="jxr_linenumber" name="L6599" href="#L6599">6599</a> 		assertEquals(<span class="jxr_string">"&lt;tag&gt;text&lt;/tag&gt;"</span>, unescapeXml(<span class="jxr_string">"&amp;lt;tag&amp;gt;text&amp;lt;/tag&amp;gt;"</span>));
-<a class="jxr_linenumber" name="L6600" href="#L6600">6600</a> 	}
-<a class="jxr_linenumber" name="L6601" href="#L6601">6601</a> 
-<a class="jxr_linenumber" name="L6602" href="#L6602">6602</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6603" href="#L6603">6603</a> 	<em class="jxr_comment">// unicodeSequence(char)</em>
-<a class="jxr_linenumber" name="L6604" href="#L6604">6604</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6605" href="#L6605">6605</a> 	@Test
-<a class="jxr_linenumber" name="L6606" href="#L6606">6606</a> 	<strong class="jxr_keyword">void</strong> a225_unicodeSequence() {
-<a class="jxr_linenumber" name="L6607" href="#L6607">6607</a> 		assertEquals(<span class="jxr_string">"&#92;&#92;u0041"</span>, unicodeSequence('A'));
-<a class="jxr_linenumber" name="L6608" href="#L6608">6608</a> 		assertEquals(<span class="jxr_string">"&#92;&#92;u0061"</span>, unicodeSequence('a'));
-<a class="jxr_linenumber" name="L6609" href="#L6609">6609</a> 		assertEquals(<span class="jxr_string">"&#92;&#92;u0030"</span>, unicodeSequence('0'));
-<a class="jxr_linenumber" name="L6610" href="#L6610">6610</a> 		assertEquals(<span class="jxr_string">"&#92;&#92;u0000"</span>, unicodeSequence('\u0000'));
-<a class="jxr_linenumber" name="L6611" href="#L6611">6611</a> 		assertEquals(<span class="jxr_string">"&#92;&#92;u00FF"</span>, unicodeSequence('\u00FF'));
-<a class="jxr_linenumber" name="L6612" href="#L6612">6612</a> 		assertEquals(<span class="jxr_string">"&#92;&#92;uFFFF"</span>, unicodeSequence('\uFFFF'));
-<a class="jxr_linenumber" name="L6613" href="#L6613">6613</a> 	}
-<a class="jxr_linenumber" name="L6614" href="#L6614">6614</a> 
-<a class="jxr_linenumber" name="L6615" href="#L6615">6615</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6616" href="#L6616">6616</a> 	<em class="jxr_comment">// upperCase(String)</em>
-<a class="jxr_linenumber" name="L6617" href="#L6617">6617</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6618" href="#L6618">6618</a> 	@Test
-<a class="jxr_linenumber" name="L6619" href="#L6619">6619</a> 	<strong class="jxr_keyword">void</strong> a226_upperCase() {
-<a class="jxr_linenumber" name="L6620" href="#L6620">6620</a> 		assertNull(upperCase(<strong class="jxr_keyword">null</strong>));
-<a class="jxr_linenumber" name="L6621" href="#L6621">6621</a> 		assertEquals(<span class="jxr_string">""</span>, upperCase(<span class="jxr_string">""</span>));
-<a class="jxr_linenumber" name="L6622" href="#L6622">6622</a> 		assertEquals(<span class="jxr_string">"HELLO"</span>, upperCase(<span class="jxr_string">"hello"</span>));
-<a class="jxr_linenumber" name="L6623" href="#L6623">6623</a> 		assertEquals(<span class="jxr_string">"HELLO WORLD"</span>, upperCase(<span class="jxr_string">"Hello World"</span>));
-<a class="jxr_linenumber" name="L6624" href="#L6624">6624</a> 		assertEquals(<span class="jxr_string">"123"</span>, upperCase(<span class="jxr_string">"123"</span>));
-<a class="jxr_linenumber" name="L6625" href="#L6625">6625</a> 		assertEquals(<span class="jxr_string">"ABC"</span>, upperCase(<span class="jxr_string">"abc"</span>));
-<a class="jxr_linenumber" name="L6626" href="#L6626">6626</a> 	}
-<a class="jxr_linenumber" name="L6627" href="#L6627">6627</a> 
-<a class="jxr_linenumber" name="L6628" href="#L6628">6628</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6629" href="#L6629">6629</a> 	<em class="jxr_comment">// urlDecode(String)</em>
-<a class="jxr_linenumber" name="L6630" href="#L6630">6630</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6631" href="#L6631">6631</a> 	@Test
-<a class="jxr_linenumber" name="L6632" href="#L6632">6632</a> 	<strong class="jxr_keyword">void</strong> a227_urlDecode() {
-<a class="jxr_linenumber" name="L6633" href="#L6633">6633</a> 		assertNull(urlDecode(<strong class="jxr_keyword">null</strong>));
-<a class="jxr_linenumber" name="L6634" href="#L6634">6634</a> 		assertEquals(<span class="jxr_string">""</span>, urlDecode(<span class="jxr_string">""</span>));
-<a class="jxr_linenumber" name="L6635" href="#L6635">6635</a> 		assertEquals(<span class="jxr_string">"Hello World"</span>, urlDecode(<span class="jxr_string">"Hello+World"</span>));
-<a class="jxr_linenumber" name="L6636" href="#L6636">6636</a> 		assertEquals(<span class="jxr_string">"Hello World"</span>, urlDecode(<span class="jxr_string">"Hello%20World"</span>));
-<a class="jxr_linenumber" name="L6637" href="#L6637">6637</a> 		assertEquals(<span class="jxr_string">"test@example.com"</span>, urlDecode(<span class="jxr_string">"test%40example.com"</span>));
-<a class="jxr_linenumber" name="L6638" href="#L6638">6638</a> 		assertEquals(<span class="jxr_string">"a=b&amp;c=d"</span>, urlDecode(<span class="jxr_string">"a%3Db%26c%3Dd"</span>));
-<a class="jxr_linenumber" name="L6639" href="#L6639">6639</a> 		<em class="jxr_comment">// No encoding needed - returns as-is</em>
-<a class="jxr_linenumber" name="L6640" href="#L6640">6640</a> 		assertEquals(<span class="jxr_string">"Hello"</span>, urlDecode(<span class="jxr_string">"Hello"</span>));
-<a class="jxr_linenumber" name="L6641" href="#L6641">6641</a> 	}
-<a class="jxr_linenumber" name="L6642" href="#L6642">6642</a> 
-<a class="jxr_linenumber" name="L6643" href="#L6643">6643</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6644" href="#L6644">6644</a> 	<em class="jxr_comment">// urlEncode(String)</em>
-<a class="jxr_linenumber" name="L6645" href="#L6645">6645</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6646" href="#L6646">6646</a> 	@Test
-<a class="jxr_linenumber" name="L6647" href="#L6647">6647</a> 	<strong class="jxr_keyword">void</strong> a228_urlEncode() {
-<a class="jxr_linenumber" name="L6648" href="#L6648">6648</a> 		assertNull(urlEncode(<strong class="jxr_keyword">null</strong>));
-<a class="jxr_linenumber" name="L6649" href="#L6649">6649</a> 		assertEquals(<span class="jxr_string">""</span>, urlEncode(<span class="jxr_string">""</span>));
-<a class="jxr_linenumber" name="L6650" href="#L6650">6650</a> 		assertEquals(<span class="jxr_string">"Hello+World"</span>, urlEncode(<span class="jxr_string">"Hello World"</span>));
-<a class="jxr_linenumber" name="L6651" href="#L6651">6651</a> 		assertEquals(<span class="jxr_string">"test%40example.com"</span>, urlEncode(<span class="jxr_string">"test@example.com"</span>));
-<a class="jxr_linenumber" name="L6652" href="#L6652">6652</a> 		assertEquals(<span class="jxr_string">"a%3Db%26c%3Dd"</span>, urlEncode(<span class="jxr_string">"a=b&amp;c=d"</span>));
-<a class="jxr_linenumber" name="L6653" href="#L6653">6653</a> 		<em class="jxr_comment">// No encoding needed - returns as-is</em>
-<a class="jxr_linenumber" name="L6654" href="#L6654">6654</a> 		assertEquals(<span class="jxr_string">"Hello"</span>, urlEncode(<span class="jxr_string">"Hello"</span>));
-<a class="jxr_linenumber" name="L6655" href="#L6655">6655</a> 		assertEquals(<span class="jxr_string">"test123"</span>, urlEncode(<span class="jxr_string">"test123"</span>));
-<a class="jxr_linenumber" name="L6656" href="#L6656">6656</a> 
-<a class="jxr_linenumber" name="L6657" href="#L6657">6657</a> 		<em class="jxr_comment">// Test</em>
-<a class="jxr_linenumber" name="L6658" href="#L6658">6658</a> 		<strong class="jxr_keyword">var</strong> result1 = urlEncode(<span class="jxr_string">"test@example.com"</span>);
-<a class="jxr_linenumber" name="L6659" href="#L6659">6659</a> 		assertTrue(result1.contains(<span class="jxr_string">"%40"</span>)); <em class="jxr_comment">// @ is encoded</em>
-<a class="jxr_linenumber" name="L6660" href="#L6660">6660</a> 
-<a class="jxr_linenumber" name="L6661" href="#L6661">6661</a> 		<em class="jxr_comment">// Test</em>
-<a class="jxr_linenumber" name="L6662" href="#L6662">6662</a> 		<strong class="jxr_keyword">var</strong> result2 = urlEncode(<span class="jxr_string">"café"</span>);
-<a class="jxr_linenumber" name="L6663" href="#L6663">6663</a> 		assertNotNull(result2);
-<a class="jxr_linenumber" name="L6664" href="#L6664">6664</a> 		assertTrue(result2.contains(<span class="jxr_string">"%"</span>)); <em class="jxr_comment">// Contains encoded characters</em>
-<a class="jxr_linenumber" name="L6665" href="#L6665">6665</a> 
-<a class="jxr_linenumber" name="L6666" href="#L6666">6666</a> 		<strong class="jxr_keyword">var</strong> result3 = urlEncode(<span class="jxr_string">"测试"</span>);
-<a class="jxr_linenumber" name="L6667" href="#L6667">6667</a> 		assertNotNull(result3);
-<a class="jxr_linenumber" name="L6668" href="#L6668">6668</a> 		assertTrue(result3.contains(<span class="jxr_string">"%"</span>)); <em class="jxr_comment">// Contains UTF-8 encoded characters</em>
-<a class="jxr_linenumber" name="L6669" href="#L6669">6669</a> 	}
-<a class="jxr_linenumber" name="L6670" href="#L6670">6670</a> 
-<a class="jxr_linenumber" name="L6671" href="#L6671">6671</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6672" href="#L6672">6672</a> 	<em class="jxr_comment">// urlEncodeLax(String)</em>
-<a class="jxr_linenumber" name="L6673" href="#L6673">6673</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6674" href="#L6674">6674</a> 	@Test
-<a class="jxr_linenumber" name="L6675" href="#L6675">6675</a> 	<strong class="jxr_keyword">void</strong> a229_urlEncodeLax() {
-<a class="jxr_linenumber" name="L6676" href="#L6676">6676</a> 		assertNull(urlEncodeLax(<strong class="jxr_keyword">null</strong>));
-<a class="jxr_linenumber" name="L6677" href="#L6677">6677</a> 		assertEquals(<span class="jxr_string">""</span>, urlEncodeLax(<span class="jxr_string">""</span>));
-<a class="jxr_linenumber" name="L6678" href="#L6678">6678</a> 		<em class="jxr_comment">// Lax encoding - fewer characters are encoded</em>
-<a class="jxr_linenumber" name="L6679" href="#L6679">6679</a> 		assertEquals(<span class="jxr_string">"Hello+World"</span>, urlEncodeLax(<span class="jxr_string">"Hello World"</span>));
-<a class="jxr_linenumber" name="L6680" href="#L6680">6680</a> 		<em class="jxr_comment">// @ might not be encoded in lax mode</em>
-<a class="jxr_linenumber" name="L6681" href="#L6681">6681</a> 		<strong class="jxr_keyword">var</strong> result1 = urlEncodeLax(<span class="jxr_string">"test@example.com"</span>);
-<a class="jxr_linenumber" name="L6682" href="#L6682">6682</a> 		assertNotNull(result1);
-<a class="jxr_linenumber" name="L6683" href="#L6683">6683</a> 		<em class="jxr_comment">// No encoding needed - returns as-is</em>
-<a class="jxr_linenumber" name="L6684" href="#L6684">6684</a> 		assertEquals(<span class="jxr_string">"Hello"</span>, urlEncodeLax(<span class="jxr_string">"Hello"</span>));
-<a class="jxr_linenumber" name="L6685" href="#L6685">6685</a> 		assertEquals(<span class="jxr_string">"test123"</span>, urlEncodeLax(<span class="jxr_string">"test123"</span>));
-<a class="jxr_linenumber" name="L6686" href="#L6686">6686</a> 
-<a class="jxr_linenumber" name="L6687" href="#L6687">6687</a> 		<em class="jxr_comment">// Test that need encoding</em>
-<a class="jxr_linenumber" name="L6688" href="#L6688">6688</a> 		<em class="jxr_comment">// Characters not in URL_UNENCODED_LAX_CHARS and not space</em>
-<a class="jxr_linenumber" name="L6689" href="#L6689">6689</a> 		<strong class="jxr_keyword">var</strong> result2 = urlEncodeLax(<span class="jxr_string">"test#value"</span>);
-<a class="jxr_linenumber" name="L6690" href="#L6690">6690</a> 		assertNotNull(result2);
-<a class="jxr_linenumber" name="L6691" href="#L6691">6691</a> 		assertTrue(result2.contains(<span class="jxr_string">"%23"</span>)); <em class="jxr_comment">// # is encoded as %23</em>
-<a class="jxr_linenumber" name="L6692" href="#L6692">6692</a> 		<strong class="jxr_keyword">var</strong> result3 = urlEncodeLax(<span class="jxr_string">"test%value"</span>);
-<a class="jxr_linenumber" name="L6693" href="#L6693">6693</a> 		assertNotNull(result3);
-<a class="jxr_linenumber" name="L6694" href="#L6694">6694</a> 		assertTrue(result3.contains(<span class="jxr_string">"%25"</span>)); <em class="jxr_comment">// % is encoded as %25</em>
-<a class="jxr_linenumber" name="L6695" href="#L6695">6695</a> 		<strong class="jxr_keyword">var</strong> result4 = urlEncodeLax(<span class="jxr_string">"test&amp;value"</span>);
-<a class="jxr_linenumber" name="L6696" href="#L6696">6696</a> 		assertNotNull(result4);
-<a class="jxr_linenumber" name="L6697" href="#L6697">6697</a> 		assertTrue(result4.contains(<span class="jxr_string">"%26"</span>)); <em class="jxr_comment">// &amp; is encoded as %26</em>
-<a class="jxr_linenumber" name="L6698" href="#L6698">6698</a> 
-<a class="jxr_linenumber" name="L6699" href="#L6699">6699</a> 		<em class="jxr_comment">// Test that need encoding</em>
-<a class="jxr_linenumber" name="L6700" href="#L6700">6700</a> 		<em class="jxr_comment">// Unicode characters are encoded using URLEncoder.encode</em>
-<a class="jxr_linenumber" name="L6701" href="#L6701">6701</a> 		<strong class="jxr_keyword">var</strong> result5 = urlEncodeLax(<span class="jxr_string">"testévalue"</span>);
-<a class="jxr_linenumber" name="L6702" href="#L6702">6702</a> 		assertNotNull(result5);
-<a class="jxr_linenumber" name="L6703" href="#L6703">6703</a> 		assertTrue(result5.contains(<span class="jxr_string">"%"</span>)); <em class="jxr_comment">// é should be encoded</em>
-<a class="jxr_linenumber" name="L6704" href="#L6704">6704</a> 		<strong class="jxr_keyword">var</strong> result6 = urlEncodeLax(<span class="jxr_string">"test中文"</span>);
-<a class="jxr_linenumber" name="L6705" href="#L6705">6705</a> 		assertNotNull(result6);
-<a class="jxr_linenumber" name="L6706" href="#L6706">6706</a> 		assertTrue(result6.contains(<span class="jxr_string">"%"</span>)); <em class="jxr_comment">// Chinese characters should be encoded</em>
-<a class="jxr_linenumber" name="L6707" href="#L6707">6707</a> 		<strong class="jxr_keyword">var</strong> result7 = urlEncodeLax(<span class="jxr_string">"test🎉"</span>);
-<a class="jxr_linenumber" name="L6708" href="#L6708">6708</a> 		assertNotNull(result7);
-<a class="jxr_linenumber" name="L6709" href="#L6709">6709</a> 		assertTrue(result7.contains(<span class="jxr_string">"%"</span>)); <em class="jxr_comment">// Emoji should be encoded</em>
-<a class="jxr_linenumber" name="L6710" href="#L6710">6710</a> 	}
-<a class="jxr_linenumber" name="L6711" href="#L6711">6711</a> 
-<a class="jxr_linenumber" name="L6712" href="#L6712">6712</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6713" href="#L6713">6713</a> 	<em class="jxr_comment">// urlEncodePath(Object)</em>
-<a class="jxr_linenumber" name="L6714" href="#L6714">6714</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6715" href="#L6715">6715</a> 	@Test
-<a class="jxr_linenumber" name="L6716" href="#L6716">6716</a> 	<strong class="jxr_keyword">void</strong> a230_urlEncodePath() {
-<a class="jxr_linenumber" name="L6717" href="#L6717">6717</a> 		<em class="jxr_comment">// Null input</em>
-<a class="jxr_linenumber" name="L6718" href="#L6718">6718</a> 		assertNull(urlEncodePath(<strong class="jxr_keyword">null</strong>));
-<a class="jxr_linenumber" name="L6719" href="#L6719">6719</a> 
-<a class="jxr_linenumber" name="L6720" href="#L6720">6720</a> 		<em class="jxr_comment">// Path encoding - doesn't encode slashes</em>
-<a class="jxr_linenumber" name="L6721" href="#L6721">6721</a> 		<strong class="jxr_keyword">var</strong> result1 = urlEncodePath(<span class="jxr_string">"/path/to/file"</span>);
-<a class="jxr_linenumber" name="L6722" href="#L6722">6722</a> 		assertNotNull(result1);
-<a class="jxr_linenumber" name="L6723" href="#L6723">6723</a> 		assertTrue(result1.contains(<span class="jxr_string">"/"</span>));
-<a class="jxr_linenumber" name="L6724" href="#L6724">6724</a> 
-<a class="jxr_linenumber" name="L6725" href="#L6725">6725</a> 		<em class="jxr_comment">// Spaces are encoded</em>
-<a class="jxr_linenumber" name="L6726" href="#L6726">6726</a> 		<strong class="jxr_keyword">var</strong> result2 = urlEncodePath(<span class="jxr_string">"path with spaces"</span>);
-<a class="jxr_linenumber" name="L6727" href="#L6727">6727</a> 		assertNotNull(result2);
-<a class="jxr_linenumber" name="L6728" href="#L6728">6728</a> 		assertTrue(result2.contains(<span class="jxr_string">"+"</span>) || result2.contains(<span class="jxr_string">"%20"</span>));
-<a class="jxr_linenumber" name="L6729" href="#L6729">6729</a> 
-<a class="jxr_linenumber" name="L6730" href="#L6730">6730</a> 		<em class="jxr_comment">// Special characters are encoded</em>
-<a class="jxr_linenumber" name="L6731" href="#L6731">6731</a> 		<strong class="jxr_keyword">var</strong> result3 = urlEncodePath(<span class="jxr_string">"file@name"</span>);
-<a class="jxr_linenumber" name="L6732" href="#L6732">6732</a> 		assertNotNull(result3);
-<a class="jxr_linenumber" name="L6733" href="#L6733">6733</a> 
-<a class="jxr_linenumber" name="L6734" href="#L6734">6734</a> 		<em class="jxr_comment">// Test code path</em>
-<a class="jxr_linenumber" name="L6735" href="#L6735">6735</a> 		<strong class="jxr_keyword">var</strong> result4 = urlEncodePath(<span class="jxr_string">"simplepath"</span>);
-<a class="jxr_linenumber" name="L6736" href="#L6736">6736</a> 		assertEquals(<span class="jxr_string">"simplepath"</span>, result4); <em class="jxr_comment">// No encoding needed, returns as-is</em>
-<a class="jxr_linenumber" name="L6737" href="#L6737">6737</a> 
-<a class="jxr_linenumber" name="L6738" href="#L6738">6738</a> 		<em class="jxr_comment">// Test</em>
-<a class="jxr_linenumber" name="L6739" href="#L6739">6739</a> 		<em class="jxr_comment">// The surrogate pair handling code is executed when encoding characters that contain surrogate pairs</em>
-<a class="jxr_linenumber" name="L6740" href="#L6740">6740</a> 		<em class="jxr_comment">// Use a string that contains a character needing encoding along with surrogate pairs</em>
-<a class="jxr_linenumber" name="L6741" href="#L6741">6741</a> 		<em class="jxr_comment">// to ensure the encoding path is taken and surrogate pair handling is executed</em>
-<a class="jxr_linenumber" name="L6742" href="#L6742">6742</a> 		<strong class="jxr_keyword">var</strong> emoji = <span class="jxr_string">"🎉"</span>; <em class="jxr_comment">// This contains surrogate pairs</em>
-<a class="jxr_linenumber" name="L6743" href="#L6743">6743</a> 		<strong class="jxr_keyword">var</strong> result5 = urlEncodePath(emoji);
-<a class="jxr_linenumber" name="L6744" href="#L6744">6744</a> 		assertNotNull(result5);
-<a class="jxr_linenumber" name="L6745" href="#L6745">6745</a> 		<em class="jxr_comment">// The surrogate pair code  is executed during encoding</em>
-<a class="jxr_linenumber" name="L6746" href="#L6746">6746</a> 		<em class="jxr_comment">// Check that the result is different from input (encoding occurred) or contains encoded characters</em>
-<a class="jxr_linenumber" name="L6747" href="#L6747">6747</a> 		assertTrue(result5.length() &gt; 0);
-<a class="jxr_linenumber" name="L6748" href="#L6748">6748</a> 		<em class="jxr_comment">// Also test with a string that combines regular characters with surrogate pairs</em>
-<a class="jxr_linenumber" name="L6749" href="#L6749">6749</a> 		<strong class="jxr_keyword">var</strong> result5b = urlEncodePath(<span class="jxr_string">"test🎉file"</span>);
-<a class="jxr_linenumber" name="L6750" href="#L6750">6750</a> 		assertNotNull(result5b);
-<a class="jxr_linenumber" name="L6751" href="#L6751">6751</a> 		assertTrue(result5b.length() &gt; 0);
-<a class="jxr_linenumber" name="L6752" href="#L6752">6752</a> 
-<a class="jxr_linenumber" name="L6753" href="#L6753">6753</a> 		<em class="jxr_comment">// Test - uppercase hex digits (caseDiff applied)</em>
-<a class="jxr_linenumber" name="L6754" href="#L6754">6754</a> 		<em class="jxr_comment">// forDigit returns lowercase 'a'-'f' for hex digits 10-15, which need to be converted to uppercase</em>
-<a class="jxr_linenumber" name="L6755" href="#L6755">6755</a> 		<em class="jxr_comment">// We need characters that produce bytes with hex values containing a-f</em>
-<a class="jxr_linenumber" name="L6756" href="#L6756">6756</a> 		<em class="jxr_comment">// For example, byte 0x0A produces hex "a", byte 0x0B produces "b", etc.</em>
-<a class="jxr_linenumber" name="L6757" href="#L6757">6757</a> 		<em class="jxr_comment">// Use characters that when UTF-8 encoded produce bytes with values 0x0A-0x0F</em>
-<a class="jxr_linenumber" name="L6758" href="#L6758">6758</a> 		<em class="jxr_comment">// Actually, any non-ASCII character will produce multi-byte UTF-8 encoding</em>
-<a class="jxr_linenumber" name="L6759" href="#L6759">6759</a> 		<em class="jxr_comment">// Let's use a character that produces bytes with hex digits a-f</em>
-<a class="jxr_linenumber" name="L6760" href="#L6760">6760</a> 		<strong class="jxr_keyword">var</strong> result6 = urlEncodePath(<span class="jxr_string">"test@file"</span>);
-<a class="jxr_linenumber" name="L6761" href="#L6761">6761</a> 		assertNotNull(result6);
-<a class="jxr_linenumber" name="L6762" href="#L6762">6762</a> 		<em class="jxr_comment">// Check that hex digits are uppercase (A-F, not a-f)</em>
-<a class="jxr_linenumber" name="L6763" href="#L6763">6763</a> 		<em class="jxr_comment">// The encoding should contain %40 for @</em>
-<a class="jxr_linenumber" name="L6764" href="#L6764">6764</a> 		assertTrue(result6.contains(<span class="jxr_string">"%40"</span>) || result6.contains(<span class="jxr_string">"%"</span>));
-<a class="jxr_linenumber" name="L6765" href="#L6765">6765</a> 		<em class="jxr_comment">// Verify all hex sequences are uppercase</em>
-<a class="jxr_linenumber" name="L6766" href="#L6766">6766</a> 		<strong class="jxr_keyword">var</strong> hexPattern = java.util.regex.Pattern.compile(<span class="jxr_string">"%([0-9A-Fa-f]{2})"</span>);
-<a class="jxr_linenumber" name="L6767" href="#L6767">6767</a> 		<strong class="jxr_keyword">var</strong> matcher = hexPattern.matcher(result6);
-<a class="jxr_linenumber" name="L6768" href="#L6768">6768</a> 		<strong class="jxr_keyword">boolean</strong> foundHex = false;
-<a class="jxr_linenumber" name="L6769" href="#L6769">6769</a> 		<strong class="jxr_keyword">while</strong> (matcher.find()) {
-<a class="jxr_linenumber" name="L6770" href="#L6770">6770</a> 			foundHex = <strong class="jxr_keyword">true</strong>;
-<a class="jxr_linenumber" name="L6771" href="#L6771">6771</a> 			<strong class="jxr_keyword">var</strong> hex = matcher.group(1);
-<a class="jxr_linenumber" name="L6772" href="#L6772">6772</a> 			<em class="jxr_comment">// Verify it's uppercase (caseDiff converts lowercase to uppercase)</em>
-<a class="jxr_linenumber" name="L6773" href="#L6773">6773</a> 			assertEquals(hex.toUpperCase(), hex);
-<a class="jxr_linenumber" name="L6774" href="#L6774">6774</a> 		}
-<a class="jxr_linenumber" name="L6775" href="#L6775">6775</a> 		<em class="jxr_comment">// Test with a character that produces bytes with hex digits a-f</em>
-<a class="jxr_linenumber" name="L6776" href="#L6776">6776</a> 		<em class="jxr_comment">// Use a character that when UTF-8 encoded produces bytes with values that result in lowercase hex</em>
-<a class="jxr_linenumber" name="L6777" href="#L6777">6777</a> 		<em class="jxr_comment">// For example, characters that produce bytes 0x0A-0x0F, 0x1A-0x1F, etc.</em>
-<a class="jxr_linenumber" name="L6778" href="#L6778">6778</a> 		<em class="jxr_comment">// Chinese character or other multi-byte UTF-8 character should work</em>
-<a class="jxr_linenumber" name="L6779" href="#L6779">6779</a> 		<strong class="jxr_keyword">var</strong> result7 = urlEncodePath(<span class="jxr_string">"test中文"</span>);
-<a class="jxr_linenumber" name="L6780" href="#L6780">6780</a> 		assertNotNull(result7);
-<a class="jxr_linenumber" name="L6781" href="#L6781">6781</a> 		assertTrue(result7.contains(<span class="jxr_string">"%"</span>));
-<a class="jxr_linenumber" name="L6782" href="#L6782">6782</a> 		<em class="jxr_comment">// Verify hex digits are uppercase</em>
-<a class="jxr_linenumber" name="L6783" href="#L6783">6783</a> 		<strong class="jxr_keyword">var</strong> matcher2 = hexPattern.matcher(result7);
-<a class="jxr_linenumber" name="L6784" href="#L6784">6784</a> 		<strong class="jxr_keyword">while</strong> (matcher2.find()) {
-<a class="jxr_linenumber" name="L6785" href="#L6785">6785</a> 			<strong class="jxr_keyword">var</strong> hex = matcher2.group(1);
-<a class="jxr_linenumber" name="L6786" href="#L6786">6786</a> 			<em class="jxr_comment">// Verify it's uppercase (code path and 7724 convert lowercase to uppercase)</em>
-<a class="jxr_linenumber" name="L6787" href="#L6787">6787</a> 			assertEquals(hex.toUpperCase(), hex);
-<a class="jxr_linenumber" name="L6788" href="#L6788">6788</a> 		}
-<a class="jxr_linenumber" name="L6789" href="#L6789">6789</a> 		<em class="jxr_comment">// If we found hex sequences, verify they're uppercase</em>
-<a class="jxr_linenumber" name="L6790" href="#L6790">6790</a> 		<strong class="jxr_keyword">if</strong> (foundHex) {
-<a class="jxr_linenumber" name="L6791" href="#L6791">6791</a> 			<em class="jxr_comment">// All hex should be uppercase</em>
-<a class="jxr_linenumber" name="L6792" href="#L6792">6792</a> 			assertTrue(result6.equals(result6.toUpperCase()) || result6.matches(<span class="jxr_string">".*%[0-9A-F]{2}.*"</span>));
-<a class="jxr_linenumber" name="L6793" href="#L6793">6793</a> 		}
-<a class="jxr_linenumber" name="L6794" href="#L6794">6794</a> 	}
-<a class="jxr_linenumber" name="L6795" href="#L6795">6795</a> 
-<a class="jxr_linenumber" name="L6796" href="#L6796">6796</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6797" href="#L6797">6797</a> 	<em class="jxr_comment">// wordCount(String)</em>
-<a class="jxr_linenumber" name="L6798" href="#L6798">6798</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6799" href="#L6799">6799</a> 	@Test
-<a class="jxr_linenumber" name="L6800" href="#L6800">6800</a> 	<strong class="jxr_keyword">void</strong> a231_wordCount() {
-<a class="jxr_linenumber" name="L6801" href="#L6801">6801</a> 		assertEquals(0, wordCount(<strong class="jxr_keyword">null</strong>));
-<a class="jxr_linenumber" name="L6802" href="#L6802">6802</a> 		assertEquals(0, wordCount(<span class="jxr_string">""</span>));
-<a class="jxr_linenumber" name="L6803" href="#L6803">6803</a> 		assertEquals(0, wordCount(<span class="jxr_string">"   "</span>));
-<a class="jxr_linenumber" name="L6804" href="#L6804">6804</a> 		assertEquals(1, wordCount(<span class="jxr_string">"hello"</span>));
-<a class="jxr_linenumber" name="L6805" href="#L6805">6805</a> 		assertEquals(2, wordCount(<span class="jxr_string">"Hello world"</span>));
-<a class="jxr_linenumber" name="L6806" href="#L6806">6806</a> 		assertEquals(4, wordCount(<span class="jxr_string">"The quick brown fox"</span>));
-<a class="jxr_linenumber" name="L6807" href="#L6807">6807</a> 		assertEquals(5, wordCount(<span class="jxr_string">"Hello, world! How are you?"</span>));
-<a class="jxr_linenumber" name="L6808" href="#L6808">6808</a> 		assertEquals(3, wordCount(<span class="jxr_string">"one\ttwo\nthree"</span>));
-<a class="jxr_linenumber" name="L6809" href="#L6809">6809</a> 		assertEquals(1, wordCount(<span class="jxr_string">"hello123"</span>));
-<a class="jxr_linenumber" name="L6810" href="#L6810">6810</a> 		<em class="jxr_comment">// Underscores are part of word characters, so "hello_world" is one word</em>
-<a class="jxr_linenumber" name="L6811" href="#L6811">6811</a> 		assertEquals(1, wordCount(<span class="jxr_string">"hello_world"</span>));
-<a class="jxr_linenumber" name="L6812" href="#L6812">6812</a> 		assertEquals(2, wordCount(<span class="jxr_string">"hello world"</span>));
-<a class="jxr_linenumber" name="L6813" href="#L6813">6813</a> 	}
-<a class="jxr_linenumber" name="L6814" href="#L6814">6814</a> 
-<a class="jxr_linenumber" name="L6815" href="#L6815">6815</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6816" href="#L6816">6816</a> 	<em class="jxr_comment">// wrap(String,int) and wrap(String,int,String)</em>
-<a class="jxr_linenumber" name="L6817" href="#L6817">6817</a> 	<em class="jxr_comment">//====================================================================================================</em>
-<a class="jxr_linenumber" name="L6818" href="#L6818">6818</a> 	@Test
-<a class="jxr_linenumber" name="L6819" href="#L6819">6819</a> 	<strong class="jxr_keyword">void</strong> a232_wrap() {
-<a class="jxr_linenumber" name="L6820" href="#L6820">6820</a> 		<em class="jxr_comment">// wrap(String,int) - uses default newline "\n"</em>
-<a class="jxr_linenumber" name="L6821" href="#L6821">6821</a> 		assertNull(wrap(<strong class="jxr_keyword">null</strong>, 10));
-<a class="jxr_linenumber" name="L6822" href="#L6822">6822</a> 		assertEquals(<span class="jxr_string">""</span>, wrap(<span class="jxr_string">""</span>, 10));
-<a class="jxr_linenumber" name="L6823" href="#L6823">6823</a> 		assertEquals(<span class="jxr_string">"hello\nworld"</span>, wrap(<span class="jxr_string">"hello world"</span>, 10));
-<a class="jxr_linenumber" name="L6824" href="#L6824">6824</a> 		assertEquals(<span class="jxr_string">"hello\nworld\ntest"</span>, wrap(<span class="jxr_string">"hello world test"</span>, 10));
-<a class="jxr_linenumber" name="L6825" href="#L6825">6825</a> 		assertEquals(<span class="jxr_string">"hello world"</span>, wrap(<span class="jxr_string">"hello world"</span>, 20));
-<a class="jxr_linenumber" name="L6826" href="#L6826">6826</a> 		assertEquals(<span class="jxr_string">"hello\nworld"</span>, wrap(<span class="jxr_string">"hello world"</span>, 5));
-<a class="jxr_linenumber" name="L6827" href="#L6827">6827</a> 		assertEquals(<span class="jxr_string">"supercalifragilisticexpialidocious"</span>, wrap(<span class="jxr_string">"supercalifragilisticexpialidocious"</span>, 10));
-<a class="jxr_linenumber" name="L6828" href="#L6828">6828</a> 		assertEquals(<span class="jxr_string">"hello\nworld"</span>, wrap(<span class="jxr_string">"hello  world"</span>, 10));
-<a class="jxr_linenumber" name="L6829" href="#L6829">6829</a> 		assertEquals(<span class="jxr_string">"line1\nline2"</span>, wrap(<span class="jxr_string">"line1\nline2"</span>, 10));
-<a class="jxr_linenumber" name="L6830" href="#L6830">6830</a> 		assertEquals(<span class="jxr_string">"a\nb\nc"</span>, wrap(<span class="jxr_string">"a b c"</span>, 1));
-<a class="jxr_linenumber" name="L6831" href="#L6831">6831</a> 		assertThrows(IllegalArgumentException.<strong class="jxr_keyword">class</strong>, () -&gt; wrap(<span class="jxr_string">"test"</span>, 0));
-<a class="jxr_linenumber" name="L6832" href="#L6832">6832</a> 		assertThrows(IllegalArgumentException.<strong class="jxr_keyword">class</strong>, () -&gt; wrap(<span class="jxr_string">"test"</span>, -1));
-<a class="jxr_linenumber" name="L6833" href="#L6833">6833</a> 
-<a class="jxr_linenumber" name="L6834" href="#L6834">6834</a> 		<em class="jxr_comment">// wrap(String,int,String) - with custom newline</em>
-<a class="jxr_linenumber" name="L6835" href="#L6835">6835</a> 		assertNull(wrap(<strong class="jxr_keyword">null</strong>, 10, <span class="jxr_string">"&lt;br&gt;"</span>));
-<a class="jxr_linenumber" name="L6836" href="#L6836">6836</a> 		assertEquals(<span class="jxr_string">""</span>, wrap(<span class="jxr_string">""</span>, 10, <span class="jxr_string">"&lt;br&gt;"</span>));
-<a class="jxr_linenumber" name="L6837" href="#L6837">6837</a> 		assertEquals(<span class="jxr_string">"hello&lt;br&gt;world"</span>, wrap(<span class="jxr_string">"hello world"</span>, 10, <span class="jxr_string">"&lt;br&gt;"</span>));
-<a class="jxr_linenumber" name="L6838" href="#L6838">6838</a> 		assertEquals(<span class="jxr_string">"hello&lt;br&gt;world&lt;br&gt;test"</span>, wrap(<span class="jxr_string">"hello world test"</span>, 10, <span class="jxr_string">"&lt;br&gt;"</span>));
-<a class="jxr_linenumber" name="L6839" href="#L6839">6839</a> 		assertEquals(<span class="jxr_string">"hello world"</span>, wrap(<span class="jxr_string">"hello world"</span>, 20, <span class="jxr_string">"&lt;br&gt;"</span>));
-<a class="jxr_linenumber" name="L6840" href="#L6840">6840</a> 		assertEquals(<span class="jxr_string">"hello&lt;br&gt;world"</span>, wrap(<span class="jxr_string">"hello world"</span>, 5, <span class="jxr_string">"&lt;br&gt;"</span>));
-<a class="jxr_linenumber" name="L6841" href="#L6841">6841</a> 		assertEquals(<span class="jxr_string">"supercalifragilisticexpialidocious"</span>, wrap(<span class="jxr_string">"supercalifragilisticexpialidocious"</span>, 10, <span class="jxr_string">"&lt;br&gt;"</span>));
-<a class="jxr_linenumber" name="L6842" href="#L6842">6842</a> 		assertEquals(<span class="jxr_string">"line1&lt;br&gt;line2"</span>, wrap(<span class="jxr_string">"line1\nline2"</span>, 10, <span class="jxr_string">"&lt;br&gt;"</span>));
-<a class="jxr_linenumber" name="L6843" href="#L6843">6843</a> 		assertEquals(<span class="jxr_string">"a&lt;br&gt;b&lt;br&gt;c"</span>, wrap(<span class="jxr_string">"a b c"</span>, 1, <span class="jxr_string">"&lt;br&gt;"</span>));
-<a class="jxr_linenumber" name="L6844" href="#L6844">6844</a> 		assertThrows(IllegalArgumentException.<strong class="jxr_keyword">class</strong>, () -&gt; wrap(<span class="jxr_string">"test"</span>, 0, <span class="jxr_string">"\n"</span>));
-<a class="jxr_linenumber" name="L6845" href="#L6845">6845</a> 		assertThrows(IllegalArgumentException.<strong class="jxr_keyword">class</strong>, () -&gt; wrap(<span class="jxr_string">"test"</span>, -1, <span class="jxr_string">"\n"</span>));
-<a class="jxr_linenumber" name="L6846" href="#L6846">6846</a> 		assertThrows(IllegalArgumentException.<strong class="jxr_keyword">class</strong>, () -&gt; wrap(<span class="jxr_string">"test"</span>, 10, <strong class="jxr_keyword">null</strong>));
-<a class="jxr_linenumber" name="L6847" href="#L6847">6847</a> 
-<a class="jxr_linenumber" name="L6848" href="#L6848">6848</a> 		<em class="jxr_comment">// Test</em>
-<a class="jxr_linenumber" name="L6849" href="#L6849">6849</a> 		<strong class="jxr_keyword">var</strong> result1 = wrap(<span class="jxr_string">"line1\n\nline2"</span>, 10, <span class="jxr_string">"\n"</span>);
-<a class="jxr_linenumber" name="L6850" href="#L6850">6850</a> 		assertTrue(result1.contains(<span class="jxr_string">"\n\n"</span>)); <em class="jxr_comment">// Empty line preserved</em>
-<a class="jxr_linenumber" name="L6851" href="#L6851">6851</a> 
-<a class="jxr_linenumber" name="L6852" href="#L6852">6852</a> 		<em class="jxr_comment">// Test)</em>
-<a class="jxr_linenumber" name="L6853" href="#L6853">6853</a> 		<em class="jxr_comment">// Multiple spaces create empty words that should be skipped</em>
-<a class="jxr_linenumber" name="L6854" href="#L6854">6854</a> 		<strong class="jxr_keyword">var</strong> result2 = wrap(<span class="jxr_string">"word1  word2"</span>, 10, <span class="jxr_string">"\n"</span>);
-<a class="jxr_linenumber" name="L6855" href="#L6855">6855</a> 		assertTrue(result2.contains(<span class="jxr_string">"word1"</span>));
-<a class="jxr_linenumber" name="L6856" href="#L6856">6856</a> 		assertTrue(result2.contains(<span class="jxr_string">"word2"</span>));
-<a class="jxr_linenumber" name="L6857" href="#L6857">6857</a> 		<em class="jxr_comment">// Test with multiple consecutive spaces</em>
-<a class="jxr_linenumber" name="L6858" href="#L6858">6858</a> 		<strong class="jxr_keyword">var</strong> result2b = wrap(<span class="jxr_string">"a   b   c"</span>, 10, <span class="jxr_string">"\n"</span>);
-<a class="jxr_linenumber" name="L6859" href="#L6859">6859</a> 		assertTrue(result2b.contains(<span class="jxr_string">"a"</span>));
-<a class="jxr_linenumber" name="L6860" href="#L6860">6860</a> 		assertTrue(result2b.contains(<span class="jxr_string">"b"</span>));
-<a class="jxr_linenumber" name="L6861" href="#L6861">6861</a> 		assertTrue(result2b.contains(<span class="jxr_string">"c"</span>));
-<a class="jxr_linenumber" name="L6862" href="#L6862">6862</a> 		<em class="jxr_comment">// Test with leading spaces - split(" +") creates empty string at start</em>
-<a class="jxr_linenumber" name="L6863" href="#L6863">6863</a> 		<strong class="jxr_keyword">var</strong> result2c = wrap(<span class="jxr_string">"  hello world"</span>, 10, <span class="jxr_string">"\n"</span>);
-<a class="jxr_linenumber" name="L6864" href="#L6864">6864</a> 		assertTrue(result2c.contains(<span class="jxr_string">"hello"</span>));
-<a class="jxr_linenumber" name="L6865" href="#L6865">6865</a> 		assertTrue(result2c.contains(<span class="jxr_string">"world"</span>));
-<a class="jxr_linenumber" name="L6866" href="#L6866">6866</a> 		<em class="jxr_comment">// Test with trailing spaces - split(" +") creates empty string at end</em>
-<a class="jxr_linenumber" name="L6867" href="#L6867">6867</a> 		<strong class="jxr_keyword">var</strong> result2d = wrap(<span class="jxr_string">"hello world  "</span>, 10, <span class="jxr_string">"\n"</span>);
-<a class="jxr_linenumber" name="L6868" href="#L6868">6868</a> 		assertTrue(result2d.contains(<span class="jxr_string">"hello"</span>));
-<a class="jxr_linenumber" name="L6869" href="#L6869">6869</a> 		assertTrue(result2d.contains(<span class="jxr_string">"world"</span>));
-<a class="jxr_linenumber" name="L6870" href="#L6870">6870</a> 		<em class="jxr_comment">// Test with both leading and trailing spaces</em>
-<a class="jxr_linenumber" name="L6871" href="#L6871">6871</a> 		<strong class="jxr_keyword">var</strong> result2e = wrap(<span class="jxr_string">"  hello world  "</span>, 10, <span class="jxr_string">"\n"</span>);
-<a class="jxr_linenumber" name="L6872" href="#L6872">6872</a> 		assertTrue(result2e.contains(<span class="jxr_string">"hello"</span>));
-<a class="jxr_linenumber" name="L6873" href="#L6873">6873</a> 		assertTrue(result2e.contains(<span class="jxr_string">"world"</span>));
-<a class="jxr_linenumber" name="L6874" href="#L6874">6874</a> 
-<a class="jxr_linenumber" name="L6875" href="#L6875">6875</a> 		<em class="jxr_comment">// Test</em>
-<a class="jxr_linenumber" name="L6876" href="#L6876">6876</a> 		<em class="jxr_comment">// This tests breaking a long word when it's the first word on a line</em>
-<a class="jxr_linenumber" name="L6877" href="#L6877">6877</a> 		<em class="jxr_comment">// Code path: result.length() &gt; 0 (result already has content)</em>
-<a class="jxr_linenumber" name="L6878" href="#L6878">6878</a> 		<em class="jxr_comment">// Code path: while loop that breaks word into chunks</em>
-<a class="jxr_linenumber" name="L6879" href="#L6879">6879</a> 		<em class="jxr_comment">//   Code path: wordPos &gt; 0 (not first iteration)</em>
-<a class="jxr_linenumber" name="L6880" href="#L6880">6880</a> 		<em class="jxr_comment">//   Code path: remaining &lt;= wrapLength (remaining fits)</em>
-<a class="jxr_linenumber" name="L6881" href="#L6881">6881</a> 		<em class="jxr_comment">//   Code path: append remaining</em>
-<a class="jxr_linenumber" name="L6882" href="#L6882">6882</a> 		<em class="jxr_comment">//   Code path: break</em>
-<a class="jxr_linenumber" name="L6883" href="#L6883">6883</a> 		<em class="jxr_comment">//   Code path: append chunk</em>
-<a class="jxr_linenumber" name="L6884" href="#L6884">6884</a> 		<em class="jxr_comment">//   Code path: advance position</em>
-<a class="jxr_linenumber" name="L6885" href="#L6885">6885</a> 		<strong class="jxr_keyword">var</strong> result3 = wrap(<span class="jxr_string">"short verylongword here"</span>, 5, <span class="jxr_string">"\n"</span>);
-<a class="jxr_linenumber" name="L6886" href="#L6886">6886</a> 		assertFalse(result3.contains(<span class="jxr_string">"verylongword"</span>)); <em class="jxr_comment">// Word should be split into chunks</em>
-<a class="jxr_linenumber" name="L6887" href="#L6887">6887</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> line : result3.split(<span class="jxr_string">"\n"</span>)) {
-<a class="jxr_linenumber" name="L6888" href="#L6888">6888</a> 			<strong class="jxr_keyword">if</strong> (! line.isEmpty())
-<a class="jxr_linenumber" name="L6889" href="#L6889">6889</a> 				assertTrue(line.length() &lt;= 5);
-<a class="jxr_linenumber" name="L6890" href="#L6890">6890</a> 		}
-<a class="jxr_linenumber" name="L6891" href="#L6891">6891</a> 		<em class="jxr_comment">// Test with result already having content  &gt; 0)</em>
-<a class="jxr_linenumber" name="L6892" href="#L6892">6892</a> 		<em class="jxr_comment">// After a previous line, a long word that needs breaking as first word on new line</em>
-<a class="jxr_linenumber" name="L6893" href="#L6893">6893</a> 		<em class="jxr_comment">// This happens when a previous line was completed and we start a new line</em>
-<a class="jxr_linenumber" name="L6894" href="#L6894">6894</a> 		<strong class="jxr_keyword">var</strong> result3b = wrap(<span class="jxr_string">"first\nverylongword here"</span>, 5, <span class="jxr_string">"\n"</span>);
-<a class="jxr_linenumber" name="L6895" href="#L6895">6895</a> 		<em class="jxr_comment">// After "first\n", "verylongword" is the first word on the new line and needs breaking</em>
-<a class="jxr_linenumber" name="L6896" href="#L6896">6896</a> 		assertTrue(result3b.contains(<span class="jxr_string">"first"</span>));
-<a class="jxr_linenumber" name="L6897" href="#L6897">6897</a> 		assertFalse(result3b.contains(<span class="jxr_string">"verylongword"</span>)); <em class="jxr_comment">// Long word should be broken</em>
-<a class="jxr_linenumber" name="L6898" href="#L6898">6898</a> 		<em class="jxr_comment">// Test word that breaks into multiple chunks (covers code path)</em>
-<a class="jxr_linenumber" name="L6899" href="#L6899">6899</a> 		<em class="jxr_comment">// Word length 15, wrapLength 5 -&gt; 3 chunks of 5, 5, 5</em>
-<a class="jxr_linenumber" name="L6900" href="#L6900">6900</a> 		<em class="jxr_comment">// This tests: wordPos &gt; 0 , append chunk , advance position </em>
-<a class="jxr_linenumber" name="L6901" href="#L6901">6901</a> 		<em class="jxr_comment">// And: remaining &lt;= wrapLength , append remaining , break </em>
-<a class="jxr_linenumber" name="L6902" href="#L6902">6902</a> 		<strong class="jxr_keyword">var</strong> result3c = wrap(<span class="jxr_string">"abcdefghijklmno here"</span>, 5, <span class="jxr_string">"\n"</span>);
-<a class="jxr_linenumber" name="L6903" href="#L6903">6903</a> 		assertTrue(result3c.contains(<span class="jxr_string">"abcde"</span>)); <em class="jxr_comment">// First chunk (wordPos == 0, no newline before)</em>
-<a class="jxr_linenumber" name="L6904" href="#L6904">6904</a> 		assertTrue(result3c.contains(<span class="jxr_string">"fghij"</span>)); <em class="jxr_comment">// Second chunk (wordPos &gt; 0, newline before, code path)</em>
-<a class="jxr_linenumber" name="L6905" href="#L6905">6905</a> 		assertTrue(result3c.contains(<span class="jxr_string">"klmno"</span>)); <em class="jxr_comment">// Third chunk (remaining &lt;= wrapLength, code path)</em>
-<a class="jxr_linenumber" name="L6906" href="#L6906">6906</a> 
-<a class="jxr_linenumber" name="L6907" href="#L6907">6907</a> 		<em class="jxr_comment">// Test</em>
-<a class="jxr_linenumber" name="L6908" href="#L6908">6908</a> 		<strong class="jxr_keyword">var</strong> result4 = wrap(<span class="jxr_string">"short word verylongword here"</span>, 10, <span class="jxr_string">"\n"</span>);
-<a class="jxr_linenumber" name="L6909" href="#L6909">6909</a> 		assertFalse(result4.contains(<span class="jxr_string">"verylongword"</span>)); <em class="jxr_comment">// Word should be split into chunks</em>
-<a class="jxr_linenumber" name="L6910" href="#L6910">6910</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> line : result4.split(<span class="jxr_string">"\n"</span>)) {
-<a class="jxr_linenumber" name="L6911" href="#L6911">6911</a> 			<strong class="jxr_keyword">if</strong> (! line.isEmpty())
-<a class="jxr_linenumber" name="L6912" href="#L6912">6912</a> 				assertTrue(line.length() &lt;= 10);
-<a class="jxr_linenumber" name="L6913" href="#L6913">6913</a> 		}
-<a class="jxr_linenumber" name="L6914" href="#L6914">6914</a> 
-<a class="jxr_linenumber" name="L6915" href="#L6915">6915</a> 		<em class="jxr_comment">// Test &gt; 0)</em>
-<a class="jxr_linenumber" name="L6916" href="#L6916">6916</a> 		<strong class="jxr_keyword">var</strong> result5 = wrap(<span class="jxr_string">"short word"</span>, 20, <span class="jxr_string">"\n"</span>);
-<a class="jxr_linenumber" name="L6917" href="#L6917">6917</a> 		assertEquals(<span class="jxr_string">"short word"</span>, result5); <em class="jxr_comment">// Remaining line appended</em>
-<a class="jxr_linenumber" name="L6918" href="#L6918">6918</a> 	}
-<a class="jxr_linenumber" name="L6919" href="#L6919">6919</a> }
+<a class="jxr_linenumber" name="L6566" href="#L6566">6566</a> 		System.out.println(<span class="jxr_string">"=== Testing unescapeChars with a&#92;&#92;&#92;&#92;b, backslash NOT in escaped set ==="</span>);
+<a class="jxr_linenumber" name="L6567" href="#L6567">6567</a> 		<strong class="jxr_keyword">var</strong> result2 = unescapeChars(<span class="jxr_string">"a&#92;&#92;&#92;&#92;b"</span>, AsciiSet.of(<span class="jxr_string">","</span>));
+<a class="jxr_linenumber" name="L6568" href="#L6568">6568</a> 		System.out.println(<span class="jxr_string">"Result: "</span> + java.util.Arrays.toString(result2.toCharArray()));
+<a class="jxr_linenumber" name="L6569" href="#L6569">6569</a> 		assertEquals(<span class="jxr_string">"a&#92;&#92;&#92;&#92;b"</span>, result2); <em class="jxr_comment">// '\' not in escaped set</em>
+<a class="jxr_linenumber" name="L6570" href="#L6570">6570</a> 	}
+<a class="jxr_linenumber" name="L6571" href="#L6571">6571</a> 
+<a class="jxr_linenumber" name="L6572" href="#L6572">6572</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6573" href="#L6573">6573</a> 	<em class="jxr_comment">// unescapeHtml(String)</em>
+<a class="jxr_linenumber" name="L6574" href="#L6574">6574</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6575" href="#L6575">6575</a> 	@Test
+<a class="jxr_linenumber" name="L6576" href="#L6576">6576</a> 	<strong class="jxr_keyword">void</strong> a223_unescapeHtml() {
+<a class="jxr_linenumber" name="L6577" href="#L6577">6577</a> 		assertNull(unescapeHtml(<strong class="jxr_keyword">null</strong>));
+<a class="jxr_linenumber" name="L6578" href="#L6578">6578</a> 		assertEquals(<span class="jxr_string">""</span>, unescapeHtml(<span class="jxr_string">""</span>));
+<a class="jxr_linenumber" name="L6579" href="#L6579">6579</a> 		assertEquals(<span class="jxr_string">"Hello World"</span>, unescapeHtml(<span class="jxr_string">"Hello World"</span>));
+<a class="jxr_linenumber" name="L6580" href="#L6580">6580</a> 		assertEquals(<span class="jxr_string">"&lt;script&gt;"</span>, unescapeHtml(<span class="jxr_string">"&amp;lt;script&amp;gt;"</span>));
+<a class="jxr_linenumber" name="L6581" href="#L6581">6581</a> 		assertEquals(<span class="jxr_string">"\&quot;Hello\&quot;"</span>, unescapeHtml(<span class="jxr_string">"&amp;quot;Hello&amp;quot;"</span>));
+<a class="jxr_linenumber" name="L6582" href="#L6582">6582</a> 		assertEquals(<span class="jxr_string">"It's a test"</span>, unescapeHtml(<span class="jxr_string">"It&amp;#39;s a test"</span>));
+<a class="jxr_linenumber" name="L6583" href="#L6583">6583</a> 		assertEquals(<span class="jxr_string">"It's a test"</span>, unescapeHtml(<span class="jxr_string">"It&amp;apos;s a test"</span>));
+<a class="jxr_linenumber" name="L6584" href="#L6584">6584</a> 		assertEquals(<span class="jxr_string">"&amp;"</span>, unescapeHtml(<span class="jxr_string">"&amp;amp;"</span>));
+<a class="jxr_linenumber" name="L6585" href="#L6585">6585</a> 		assertEquals(<span class="jxr_string">"&lt;tag&gt;text&lt;/tag&gt;"</span>, unescapeHtml(<span class="jxr_string">"&amp;lt;tag&amp;gt;text&amp;lt;/tag&amp;gt;"</span>));
+<a class="jxr_linenumber" name="L6586" href="#L6586">6586</a> 		<em class="jxr_comment">// Test round-trip</em>
+<a class="jxr_linenumber" name="L6587" href="#L6587">6587</a> 		assertEquals(<span class="jxr_string">"Hello &amp; World"</span>, unescapeHtml(escapeHtml(<span class="jxr_string">"Hello &amp; World"</span>)));
+<a class="jxr_linenumber" name="L6588" href="#L6588">6588</a> 	}
+<a class="jxr_linenumber" name="L6589" href="#L6589">6589</a> 
+<a class="jxr_linenumber" name="L6590" href="#L6590">6590</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6591" href="#L6591">6591</a> 	<em class="jxr_comment">// unescapeXml(String)</em>
+<a class="jxr_linenumber" name="L6592" href="#L6592">6592</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6593" href="#L6593">6593</a> 	@Test
+<a class="jxr_linenumber" name="L6594" href="#L6594">6594</a> 	<strong class="jxr_keyword">void</strong> a224_unescapeXml() {
+<a class="jxr_linenumber" name="L6595" href="#L6595">6595</a> 		assertNull(unescapeXml(<strong class="jxr_keyword">null</strong>));
+<a class="jxr_linenumber" name="L6596" href="#L6596">6596</a> 		assertEquals(<span class="jxr_string">""</span>, unescapeXml(<span class="jxr_string">""</span>));
+<a class="jxr_linenumber" name="L6597" href="#L6597">6597</a> 		assertEquals(<span class="jxr_string">"Hello World"</span>, unescapeXml(<span class="jxr_string">"Hello World"</span>));
+<a class="jxr_linenumber" name="L6598" href="#L6598">6598</a> 		assertEquals(<span class="jxr_string">"&lt;tag&gt;"</span>, unescapeXml(<span class="jxr_string">"&amp;lt;tag&amp;gt;"</span>));
+<a class="jxr_linenumber" name="L6599" href="#L6599">6599</a> 		assertEquals(<span class="jxr_string">"\&quot;Hello\&quot;"</span>, unescapeXml(<span class="jxr_string">"&amp;quot;Hello&amp;quot;"</span>));
+<a class="jxr_linenumber" name="L6600" href="#L6600">6600</a> 		assertEquals(<span class="jxr_string">"'test'"</span>, unescapeXml(<span class="jxr_string">"&amp;apos;test&amp;apos;"</span>));
+<a class="jxr_linenumber" name="L6601" href="#L6601">6601</a> 		assertEquals(<span class="jxr_string">"&amp;"</span>, unescapeXml(<span class="jxr_string">"&amp;amp;"</span>));
+<a class="jxr_linenumber" name="L6602" href="#L6602">6602</a> 		assertEquals(<span class="jxr_string">"&lt;tag&gt;text&lt;/tag&gt;"</span>, unescapeXml(<span class="jxr_string">"&amp;lt;tag&amp;gt;text&amp;lt;/tag&amp;gt;"</span>));
+<a class="jxr_linenumber" name="L6603" href="#L6603">6603</a> 	}
+<a class="jxr_linenumber" name="L6604" href="#L6604">6604</a> 
+<a class="jxr_linenumber" name="L6605" href="#L6605">6605</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6606" href="#L6606">6606</a> 	<em class="jxr_comment">// unicodeSequence(char)</em>
+<a class="jxr_linenumber" name="L6607" href="#L6607">6607</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6608" href="#L6608">6608</a> 	@Test
+<a class="jxr_linenumber" name="L6609" href="#L6609">6609</a> 	<strong class="jxr_keyword">void</strong> a225_unicodeSequence() {
+<a class="jxr_linenumber" name="L6610" href="#L6610">6610</a> 		assertEquals(<span class="jxr_string">"&#92;&#92;u0041"</span>, unicodeSequence('A'));
+<a class="jxr_linenumber" name="L6611" href="#L6611">6611</a> 		assertEquals(<span class="jxr_string">"&#92;&#92;u0061"</span>, unicodeSequence('a'));
+<a class="jxr_linenumber" name="L6612" href="#L6612">6612</a> 		assertEquals(<span class="jxr_string">"&#92;&#92;u0030"</span>, unicodeSequence('0'));
+<a class="jxr_linenumber" name="L6613" href="#L6613">6613</a> 		assertEquals(<span class="jxr_string">"&#92;&#92;u0000"</span>, unicodeSequence('\u0000'));
+<a class="jxr_linenumber" name="L6614" href="#L6614">6614</a> 		assertEquals(<span class="jxr_string">"&#92;&#92;u00FF"</span>, unicodeSequence('\u00FF'));
+<a class="jxr_linenumber" name="L6615" href="#L6615">6615</a> 		assertEquals(<span class="jxr_string">"&#92;&#92;uFFFF"</span>, unicodeSequence('\uFFFF'));
+<a class="jxr_linenumber" name="L6616" href="#L6616">6616</a> 	}
+<a class="jxr_linenumber" name="L6617" href="#L6617">6617</a> 
+<a class="jxr_linenumber" name="L6618" href="#L6618">6618</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6619" href="#L6619">6619</a> 	<em class="jxr_comment">// upperCase(String)</em>
+<a class="jxr_linenumber" name="L6620" href="#L6620">6620</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6621" href="#L6621">6621</a> 	@Test
+<a class="jxr_linenumber" name="L6622" href="#L6622">6622</a> 	<strong class="jxr_keyword">void</strong> a226_upperCase() {
+<a class="jxr_linenumber" name="L6623" href="#L6623">6623</a> 		assertNull(upperCase(<strong class="jxr_keyword">null</strong>));
+<a class="jxr_linenumber" name="L6624" href="#L6624">6624</a> 		assertEquals(<span class="jxr_string">""</span>, upperCase(<span class="jxr_string">""</span>));
+<a class="jxr_linenumber" name="L6625" href="#L6625">6625</a> 		assertEquals(<span class="jxr_string">"HELLO"</span>, upperCase(<span class="jxr_string">"hello"</span>));
+<a class="jxr_linenumber" name="L6626" href="#L6626">6626</a> 		assertEquals(<span class="jxr_string">"HELLO WORLD"</span>, upperCase(<span class="jxr_string">"Hello World"</span>));
+<a class="jxr_linenumber" name="L6627" href="#L6627">6627</a> 		assertEquals(<span class="jxr_string">"123"</span>, upperCase(<span class="jxr_string">"123"</span>));
+<a class="jxr_linenumber" name="L6628" href="#L6628">6628</a> 		assertEquals(<span class="jxr_string">"ABC"</span>, upperCase(<span class="jxr_string">"abc"</span>));
+<a class="jxr_linenumber" name="L6629" href="#L6629">6629</a> 	}
+<a class="jxr_linenumber" name="L6630" href="#L6630">6630</a> 
+<a class="jxr_linenumber" name="L6631" href="#L6631">6631</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6632" href="#L6632">6632</a> 	<em class="jxr_comment">// urlDecode(String)</em>
+<a class="jxr_linenumber" name="L6633" href="#L6633">6633</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6634" href="#L6634">6634</a> 	@Test
+<a class="jxr_linenumber" name="L6635" href="#L6635">6635</a> 	<strong class="jxr_keyword">void</strong> a227_urlDecode() {
+<a class="jxr_linenumber" name="L6636" href="#L6636">6636</a> 		assertNull(urlDecode(<strong class="jxr_keyword">null</strong>));
+<a class="jxr_linenumber" name="L6637" href="#L6637">6637</a> 		assertEquals(<span class="jxr_string">""</span>, urlDecode(<span class="jxr_string">""</span>));
+<a class="jxr_linenumber" name="L6638" href="#L6638">6638</a> 		assertEquals(<span class="jxr_string">"Hello World"</span>, urlDecode(<span class="jxr_string">"Hello+World"</span>));
+<a class="jxr_linenumber" name="L6639" href="#L6639">6639</a> 		assertEquals(<span class="jxr_string">"Hello World"</span>, urlDecode(<span class="jxr_string">"Hello%20World"</span>));
+<a class="jxr_linenumber" name="L6640" href="#L6640">6640</a> 		assertEquals(<span class="jxr_string">"test@example.com"</span>, urlDecode(<span class="jxr_string">"test%40example.com"</span>));
+<a class="jxr_linenumber" name="L6641" href="#L6641">6641</a> 		assertEquals(<span class="jxr_string">"a=b&amp;c=d"</span>, urlDecode(<span class="jxr_string">"a%3Db%26c%3Dd"</span>));
+<a class="jxr_linenumber" name="L6642" href="#L6642">6642</a> 		<em class="jxr_comment">// No encoding needed - returns as-is</em>
+<a class="jxr_linenumber" name="L6643" href="#L6643">6643</a> 		assertEquals(<span class="jxr_string">"Hello"</span>, urlDecode(<span class="jxr_string">"Hello"</span>));
+<a class="jxr_linenumber" name="L6644" href="#L6644">6644</a> 	}
+<a class="jxr_linenumber" name="L6645" href="#L6645">6645</a> 
+<a class="jxr_linenumber" name="L6646" href="#L6646">6646</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6647" href="#L6647">6647</a> 	<em class="jxr_comment">// urlEncode(String)</em>
+<a class="jxr_linenumber" name="L6648" href="#L6648">6648</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6649" href="#L6649">6649</a> 	@Test
+<a class="jxr_linenumber" name="L6650" href="#L6650">6650</a> 	<strong class="jxr_keyword">void</strong> a228_urlEncode() {
+<a class="jxr_linenumber" name="L6651" href="#L6651">6651</a> 		assertNull(urlEncode(<strong class="jxr_keyword">null</strong>));
+<a class="jxr_linenumber" name="L6652" href="#L6652">6652</a> 		assertEquals(<span class="jxr_string">""</span>, urlEncode(<span class="jxr_string">""</span>));
+<a class="jxr_linenumber" name="L6653" href="#L6653">6653</a> 		assertEquals(<span class="jxr_string">"Hello+World"</span>, urlEncode(<span class="jxr_string">"Hello World"</span>));
+<a class="jxr_linenumber" name="L6654" href="#L6654">6654</a> 		assertEquals(<span class="jxr_string">"test%40example.com"</span>, urlEncode(<span class="jxr_string">"test@example.com"</span>));
+<a class="jxr_linenumber" name="L6655" href="#L6655">6655</a> 		assertEquals(<span class="jxr_string">"a%3Db%26c%3Dd"</span>, urlEncode(<span class="jxr_string">"a=b&amp;c=d"</span>));
+<a class="jxr_linenumber" name="L6656" href="#L6656">6656</a> 		<em class="jxr_comment">// No encoding needed - returns as-is</em>
+<a class="jxr_linenumber" name="L6657" href="#L6657">6657</a> 		assertEquals(<span class="jxr_string">"Hello"</span>, urlEncode(<span class="jxr_string">"Hello"</span>));
+<a class="jxr_linenumber" name="L6658" href="#L6658">6658</a> 		assertEquals(<span class="jxr_string">"test123"</span>, urlEncode(<span class="jxr_string">"test123"</span>));
+<a class="jxr_linenumber" name="L6659" href="#L6659">6659</a> 
+<a class="jxr_linenumber" name="L6660" href="#L6660">6660</a> 		<em class="jxr_comment">// Test</em>
+<a class="jxr_linenumber" name="L6661" href="#L6661">6661</a> 		<strong class="jxr_keyword">var</strong> result1 = urlEncode(<span class="jxr_string">"test@example.com"</span>);
+<a class="jxr_linenumber" name="L6662" href="#L6662">6662</a> 		assertTrue(result1.contains(<span class="jxr_string">"%40"</span>)); <em class="jxr_comment">// @ is encoded</em>
+<a class="jxr_linenumber" name="L6663" href="#L6663">6663</a> 
+<a class="jxr_linenumber" name="L6664" href="#L6664">6664</a> 		<em class="jxr_comment">// Test</em>
+<a class="jxr_linenumber" name="L6665" href="#L6665">6665</a> 		<strong class="jxr_keyword">var</strong> result2 = urlEncode(<span class="jxr_string">"café"</span>);
+<a class="jxr_linenumber" name="L6666" href="#L6666">6666</a> 		assertNotNull(result2);
+<a class="jxr_linenumber" name="L6667" href="#L6667">6667</a> 		assertTrue(result2.contains(<span class="jxr_string">"%"</span>)); <em class="jxr_comment">// Contains encoded characters</em>
+<a class="jxr_linenumber" name="L6668" href="#L6668">6668</a> 
+<a class="jxr_linenumber" name="L6669" href="#L6669">6669</a> 		<strong class="jxr_keyword">var</strong> result3 = urlEncode(<span class="jxr_string">"测试"</span>);
+<a class="jxr_linenumber" name="L6670" href="#L6670">6670</a> 		assertNotNull(result3);
+<a class="jxr_linenumber" name="L6671" href="#L6671">6671</a> 		assertTrue(result3.contains(<span class="jxr_string">"%"</span>)); <em class="jxr_comment">// Contains UTF-8 encoded characters</em>
+<a class="jxr_linenumber" name="L6672" href="#L6672">6672</a> 	}
+<a class="jxr_linenumber" name="L6673" href="#L6673">6673</a> 
+<a class="jxr_linenumber" name="L6674" href="#L6674">6674</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6675" href="#L6675">6675</a> 	<em class="jxr_comment">// urlEncodeLax(String)</em>
+<a class="jxr_linenumber" name="L6676" href="#L6676">6676</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6677" href="#L6677">6677</a> 	@Test
+<a class="jxr_linenumber" name="L6678" href="#L6678">6678</a> 	<strong class="jxr_keyword">void</strong> a229_urlEncodeLax() {
+<a class="jxr_linenumber" name="L6679" href="#L6679">6679</a> 		assertNull(urlEncodeLax(<strong class="jxr_keyword">null</strong>));
+<a class="jxr_linenumber" name="L6680" href="#L6680">6680</a> 		assertEquals(<span class="jxr_string">""</span>, urlEncodeLax(<span class="jxr_string">""</span>));
+<a class="jxr_linenumber" name="L6681" href="#L6681">6681</a> 		<em class="jxr_comment">// Lax encoding - fewer characters are encoded</em>
+<a class="jxr_linenumber" name="L6682" href="#L6682">6682</a> 		assertEquals(<span class="jxr_string">"Hello+World"</span>, urlEncodeLax(<span class="jxr_string">"Hello World"</span>));
+<a class="jxr_linenumber" name="L6683" href="#L6683">6683</a> 		<em class="jxr_comment">// @ might not be encoded in lax mode</em>
+<a class="jxr_linenumber" name="L6684" href="#L6684">6684</a> 		<strong class="jxr_keyword">var</strong> result1 = urlEncodeLax(<span class="jxr_string">"test@example.com"</span>);
+<a class="jxr_linenumber" name="L6685" href="#L6685">6685</a> 		assertNotNull(result1);
+<a class="jxr_linenumber" name="L6686" href="#L6686">6686</a> 		<em class="jxr_comment">// No encoding needed - returns as-is</em>
+<a class="jxr_linenumber" name="L6687" href="#L6687">6687</a> 		assertEquals(<span class="jxr_string">"Hello"</span>, urlEncodeLax(<span class="jxr_string">"Hello"</span>));
+<a class="jxr_linenumber" name="L6688" href="#L6688">6688</a> 		assertEquals(<span class="jxr_string">"test123"</span>, urlEncodeLax(<span class="jxr_string">"test123"</span>));
+<a class="jxr_linenumber" name="L6689" href="#L6689">6689</a> 
+<a class="jxr_linenumber" name="L6690" href="#L6690">6690</a> 		<em class="jxr_comment">// Test that need encoding</em>
+<a class="jxr_linenumber" name="L6691" href="#L6691">6691</a> 		<em class="jxr_comment">// Characters not in URL_UNENCODED_LAX_CHARS and not space</em>
+<a class="jxr_linenumber" name="L6692" href="#L6692">6692</a> 		<strong class="jxr_keyword">var</strong> result2 = urlEncodeLax(<span class="jxr_string">"test#value"</span>);
+<a class="jxr_linenumber" name="L6693" href="#L6693">6693</a> 		assertNotNull(result2);
+<a class="jxr_linenumber" name="L6694" href="#L6694">6694</a> 		assertTrue(result2.contains(<span class="jxr_string">"%23"</span>)); <em class="jxr_comment">// # is encoded as %23</em>
+<a class="jxr_linenumber" name="L6695" href="#L6695">6695</a> 		<strong class="jxr_keyword">var</strong> result3 = urlEncodeLax(<span class="jxr_string">"test%value"</span>);
+<a class="jxr_linenumber" name="L6696" href="#L6696">6696</a> 		assertNotNull(result3);
+<a class="jxr_linenumber" name="L6697" href="#L6697">6697</a> 		assertTrue(result3.contains(<span class="jxr_string">"%25"</span>)); <em class="jxr_comment">// % is encoded as %25</em>
+<a class="jxr_linenumber" name="L6698" href="#L6698">6698</a> 		<strong class="jxr_keyword">var</strong> result4 = urlEncodeLax(<span class="jxr_string">"test&amp;value"</span>);
+<a class="jxr_linenumber" name="L6699" href="#L6699">6699</a> 		assertNotNull(result4);
+<a class="jxr_linenumber" name="L6700" href="#L6700">6700</a> 		assertTrue(result4.contains(<span class="jxr_string">"%26"</span>)); <em class="jxr_comment">// &amp; is encoded as %26</em>
+<a class="jxr_linenumber" name="L6701" href="#L6701">6701</a> 
+<a class="jxr_linenumber" name="L6702" href="#L6702">6702</a> 		<em class="jxr_comment">// Test that need encoding</em>
+<a class="jxr_linenumber" name="L6703" href="#L6703">6703</a> 		<em class="jxr_comment">// Unicode characters are encoded using URLEncoder.encode</em>
+<a class="jxr_linenumber" name="L6704" href="#L6704">6704</a> 		<strong class="jxr_keyword">var</strong> result5 = urlEncodeLax(<span class="jxr_string">"testévalue"</span>);
+<a class="jxr_linenumber" name="L6705" href="#L6705">6705</a> 		assertNotNull(result5);
+<a class="jxr_linenumber" name="L6706" href="#L6706">6706</a> 		assertTrue(result5.contains(<span class="jxr_string">"%"</span>)); <em class="jxr_comment">// é should be encoded</em>
+<a class="jxr_linenumber" name="L6707" href="#L6707">6707</a> 		<strong class="jxr_keyword">var</strong> result6 = urlEncodeLax(<span class="jxr_string">"test中文"</span>);
+<a class="jxr_linenumber" name="L6708" href="#L6708">6708</a> 		assertNotNull(result6);
+<a class="jxr_linenumber" name="L6709" href="#L6709">6709</a> 		assertTrue(result6.contains(<span class="jxr_string">"%"</span>)); <em class="jxr_comment">// Chinese characters should be encoded</em>
+<a class="jxr_linenumber" name="L6710" href="#L6710">6710</a> 		<strong class="jxr_keyword">var</strong> result7 = urlEncodeLax(<span class="jxr_string">"test🎉"</span>);
+<a class="jxr_linenumber" name="L6711" href="#L6711">6711</a> 		assertNotNull(result7);
+<a class="jxr_linenumber" name="L6712" href="#L6712">6712</a> 		assertTrue(result7.contains(<span class="jxr_string">"%"</span>)); <em class="jxr_comment">// Emoji should be encoded</em>
+<a class="jxr_linenumber" name="L6713" href="#L6713">6713</a> 	}
+<a class="jxr_linenumber" name="L6714" href="#L6714">6714</a> 
+<a class="jxr_linenumber" name="L6715" href="#L6715">6715</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6716" href="#L6716">6716</a> 	<em class="jxr_comment">// urlEncodePath(Object)</em>
+<a class="jxr_linenumber" name="L6717" href="#L6717">6717</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6718" href="#L6718">6718</a> 	@Test
+<a class="jxr_linenumber" name="L6719" href="#L6719">6719</a> 	<strong class="jxr_keyword">void</strong> a230_urlEncodePath() {
+<a class="jxr_linenumber" name="L6720" href="#L6720">6720</a> 		<em class="jxr_comment">// Null input</em>
+<a class="jxr_linenumber" name="L6721" href="#L6721">6721</a> 		assertNull(urlEncodePath(<strong class="jxr_keyword">null</strong>));
+<a class="jxr_linenumber" name="L6722" href="#L6722">6722</a> 
+<a class="jxr_linenumber" name="L6723" href="#L6723">6723</a> 		<em class="jxr_comment">// Path encoding - doesn't encode slashes</em>
+<a class="jxr_linenumber" name="L6724" href="#L6724">6724</a> 		<strong class="jxr_keyword">var</strong> result1 = urlEncodePath(<span class="jxr_string">"/path/to/file"</span>);
+<a class="jxr_linenumber" name="L6725" href="#L6725">6725</a> 		assertNotNull(result1);
+<a class="jxr_linenumber" name="L6726" href="#L6726">6726</a> 		assertTrue(result1.contains(<span class="jxr_string">"/"</span>));
+<a class="jxr_linenumber" name="L6727" href="#L6727">6727</a> 
+<a class="jxr_linenumber" name="L6728" href="#L6728">6728</a> 		<em class="jxr_comment">// Spaces are encoded</em>
+<a class="jxr_linenumber" name="L6729" href="#L6729">6729</a> 		<strong class="jxr_keyword">var</strong> result2 = urlEncodePath(<span class="jxr_string">"path with spaces"</span>);
+<a class="jxr_linenumber" name="L6730" href="#L6730">6730</a> 		assertNotNull(result2);
+<a class="jxr_linenumber" name="L6731" href="#L6731">6731</a> 		assertTrue(result2.contains(<span class="jxr_string">"+"</span>) || result2.contains(<span class="jxr_string">"%20"</span>));
+<a class="jxr_linenumber" name="L6732" href="#L6732">6732</a> 
+<a class="jxr_linenumber" name="L6733" href="#L6733">6733</a> 		<em class="jxr_comment">// Special characters are encoded</em>
+<a class="jxr_linenumber" name="L6734" href="#L6734">6734</a> 		<strong class="jxr_keyword">var</strong> result3 = urlEncodePath(<span class="jxr_string">"file@name"</span>);
+<a class="jxr_linenumber" name="L6735" href="#L6735">6735</a> 		assertNotNull(result3);
+<a class="jxr_linenumber" name="L6736" href="#L6736">6736</a> 
+<a class="jxr_linenumber" name="L6737" href="#L6737">6737</a> 		<em class="jxr_comment">// Test code path</em>
+<a class="jxr_linenumber" name="L6738" href="#L6738">6738</a> 		<strong class="jxr_keyword">var</strong> result4 = urlEncodePath(<span class="jxr_string">"simplepath"</span>);
+<a class="jxr_linenumber" name="L6739" href="#L6739">6739</a> 		assertEquals(<span class="jxr_string">"simplepath"</span>, result4); <em class="jxr_comment">// No encoding needed, returns as-is</em>
+<a class="jxr_linenumber" name="L6740" href="#L6740">6740</a> 
+<a class="jxr_linenumber" name="L6741" href="#L6741">6741</a> 		<em class="jxr_comment">// Test</em>
+<a class="jxr_linenumber" name="L6742" href="#L6742">6742</a> 		<em class="jxr_comment">// The surrogate pair handling code is executed when encoding characters that contain surrogate pairs</em>
+<a class="jxr_linenumber" name="L6743" href="#L6743">6743</a> 		<em class="jxr_comment">// Use a string that contains a character needing encoding along with surrogate pairs</em>
+<a class="jxr_linenumber" name="L6744" href="#L6744">6744</a> 		<em class="jxr_comment">// to ensure the encoding path is taken and surrogate pair handling is executed</em>
+<a class="jxr_linenumber" name="L6745" href="#L6745">6745</a> 		<strong class="jxr_keyword">var</strong> emoji = <span class="jxr_string">"🎉"</span>; <em class="jxr_comment">// This contains surrogate pairs</em>
+<a class="jxr_linenumber" name="L6746" href="#L6746">6746</a> 		<strong class="jxr_keyword">var</strong> result5 = urlEncodePath(emoji);
+<a class="jxr_linenumber" name="L6747" href="#L6747">6747</a> 		assertNotNull(result5);
+<a class="jxr_linenumber" name="L6748" href="#L6748">6748</a> 		<em class="jxr_comment">// The surrogate pair code  is executed during encoding</em>
+<a class="jxr_linenumber" name="L6749" href="#L6749">6749</a> 		<em class="jxr_comment">// Check that the result is different from input (encoding occurred) or contains encoded characters</em>
+<a class="jxr_linenumber" name="L6750" href="#L6750">6750</a> 		assertTrue(result5.length() &gt; 0);
+<a class="jxr_linenumber" name="L6751" href="#L6751">6751</a> 		<em class="jxr_comment">// Also test with a string that combines regular characters with surrogate pairs</em>
+<a class="jxr_linenumber" name="L6752" href="#L6752">6752</a> 		<strong class="jxr_keyword">var</strong> result5b = urlEncodePath(<span class="jxr_string">"test🎉file"</span>);
+<a class="jxr_linenumber" name="L6753" href="#L6753">6753</a> 		assertNotNull(result5b);
+<a class="jxr_linenumber" name="L6754" href="#L6754">6754</a> 		assertTrue(result5b.length() &gt; 0);
+<a class="jxr_linenumber" name="L6755" href="#L6755">6755</a> 
+<a class="jxr_linenumber" name="L6756" href="#L6756">6756</a> 		<em class="jxr_comment">// Test - uppercase hex digits (caseDiff applied)</em>
+<a class="jxr_linenumber" name="L6757" href="#L6757">6757</a> 		<em class="jxr_comment">// forDigit returns lowercase 'a'-'f' for hex digits 10-15, which need to be converted to uppercase</em>
+<a class="jxr_linenumber" name="L6758" href="#L6758">6758</a> 		<em class="jxr_comment">// We need characters that produce bytes with hex values containing a-f</em>
+<a class="jxr_linenumber" name="L6759" href="#L6759">6759</a> 		<em class="jxr_comment">// For example, byte 0x0A produces hex "a", byte 0x0B produces "b", etc.</em>
+<a class="jxr_linenumber" name="L6760" href="#L6760">6760</a> 		<em class="jxr_comment">// Use characters that when UTF-8 encoded produce bytes with values 0x0A-0x0F</em>
+<a class="jxr_linenumber" name="L6761" href="#L6761">6761</a> 		<em class="jxr_comment">// Actually, any non-ASCII character will produce multi-byte UTF-8 encoding</em>
+<a class="jxr_linenumber" name="L6762" href="#L6762">6762</a> 		<em class="jxr_comment">// Let's use a character that produces bytes with hex digits a-f</em>
+<a class="jxr_linenumber" name="L6763" href="#L6763">6763</a> 		<strong class="jxr_keyword">var</strong> result6 = urlEncodePath(<span class="jxr_string">"test@file"</span>);
+<a class="jxr_linenumber" name="L6764" href="#L6764">6764</a> 		assertNotNull(result6);
+<a class="jxr_linenumber" name="L6765" href="#L6765">6765</a> 		<em class="jxr_comment">// Check that hex digits are uppercase (A-F, not a-f)</em>
+<a class="jxr_linenumber" name="L6766" href="#L6766">6766</a> 		<em class="jxr_comment">// The encoding should contain %40 for @</em>
+<a class="jxr_linenumber" name="L6767" href="#L6767">6767</a> 		assertTrue(result6.contains(<span class="jxr_string">"%40"</span>) || result6.contains(<span class="jxr_string">"%"</span>));
+<a class="jxr_linenumber" name="L6768" href="#L6768">6768</a> 		<em class="jxr_comment">// Verify all hex sequences are uppercase</em>
+<a class="jxr_linenumber" name="L6769" href="#L6769">6769</a> 		<strong class="jxr_keyword">var</strong> hexPattern = java.util.regex.Pattern.compile(<span class="jxr_string">"%([0-9A-Fa-f]{2})"</span>);
+<a class="jxr_linenumber" name="L6770" href="#L6770">6770</a> 		<strong class="jxr_keyword">var</strong> matcher = hexPattern.matcher(result6);
+<a class="jxr_linenumber" name="L6771" href="#L6771">6771</a> 		<strong class="jxr_keyword">boolean</strong> foundHex = false;
+<a class="jxr_linenumber" name="L6772" href="#L6772">6772</a> 		<strong class="jxr_keyword">while</strong> (matcher.find()) {
+<a class="jxr_linenumber" name="L6773" href="#L6773">6773</a> 			foundHex = <strong class="jxr_keyword">true</strong>;
+<a class="jxr_linenumber" name="L6774" href="#L6774">6774</a> 			<strong class="jxr_keyword">var</strong> hex = matcher.group(1);
+<a class="jxr_linenumber" name="L6775" href="#L6775">6775</a> 			<em class="jxr_comment">// Verify it's uppercase (caseDiff converts lowercase to uppercase)</em>
+<a class="jxr_linenumber" name="L6776" href="#L6776">6776</a> 			assertEquals(hex.toUpperCase(), hex);
+<a class="jxr_linenumber" name="L6777" href="#L6777">6777</a> 		}
+<a class="jxr_linenumber" name="L6778" href="#L6778">6778</a> 		<em class="jxr_comment">// Test with a character that produces bytes with hex digits a-f</em>
+<a class="jxr_linenumber" name="L6779" href="#L6779">6779</a> 		<em class="jxr_comment">// Use a character that when UTF-8 encoded produces bytes with values that result in lowercase hex</em>
+<a class="jxr_linenumber" name="L6780" href="#L6780">6780</a> 		<em class="jxr_comment">// For example, characters that produce bytes 0x0A-0x0F, 0x1A-0x1F, etc.</em>
+<a class="jxr_linenumber" name="L6781" href="#L6781">6781</a> 		<em class="jxr_comment">// Chinese character or other multi-byte UTF-8 character should work</em>
+<a class="jxr_linenumber" name="L6782" href="#L6782">6782</a> 		<strong class="jxr_keyword">var</strong> result7 = urlEncodePath(<span class="jxr_string">"test中文"</span>);
+<a class="jxr_linenumber" name="L6783" href="#L6783">6783</a> 		assertNotNull(result7);
+<a class="jxr_linenumber" name="L6784" href="#L6784">6784</a> 		assertTrue(result7.contains(<span class="jxr_string">"%"</span>));
+<a class="jxr_linenumber" name="L6785" href="#L6785">6785</a> 		<em class="jxr_comment">// Verify hex digits are uppercase</em>
+<a class="jxr_linenumber" name="L6786" href="#L6786">6786</a> 		<strong class="jxr_keyword">var</strong> matcher2 = hexPattern.matcher(result7);
+<a class="jxr_linenumber" name="L6787" href="#L6787">6787</a> 		<strong class="jxr_keyword">while</strong> (matcher2.find()) {
+<a class="jxr_linenumber" name="L6788" href="#L6788">6788</a> 			<strong class="jxr_keyword">var</strong> hex = matcher2.group(1);
+<a class="jxr_linenumber" name="L6789" href="#L6789">6789</a> 			<em class="jxr_comment">// Verify it's uppercase (code path and 7724 convert lowercase to uppercase)</em>
+<a class="jxr_linenumber" name="L6790" href="#L6790">6790</a> 			assertEquals(hex.toUpperCase(), hex);
+<a class="jxr_linenumber" name="L6791" href="#L6791">6791</a> 		}
+<a class="jxr_linenumber" name="L6792" href="#L6792">6792</a> 		<em class="jxr_comment">// If we found hex sequences, verify they're uppercase</em>
+<a class="jxr_linenumber" name="L6793" href="#L6793">6793</a> 		<strong class="jxr_keyword">if</strong> (foundHex) {
+<a class="jxr_linenumber" name="L6794" href="#L6794">6794</a> 			<em class="jxr_comment">// All hex should be uppercase</em>
+<a class="jxr_linenumber" name="L6795" href="#L6795">6795</a> 			assertTrue(result6.equals(result6.toUpperCase()) || result6.matches(<span class="jxr_string">".*%[0-9A-F]{2}.*"</span>));
+<a class="jxr_linenumber" name="L6796" href="#L6796">6796</a> 		}
+<a class="jxr_linenumber" name="L6797" href="#L6797">6797</a> 	}
+<a class="jxr_linenumber" name="L6798" href="#L6798">6798</a> 
+<a class="jxr_linenumber" name="L6799" href="#L6799">6799</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6800" href="#L6800">6800</a> 	<em class="jxr_comment">// wordCount(String)</em>
+<a class="jxr_linenumber" name="L6801" href="#L6801">6801</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6802" href="#L6802">6802</a> 	@Test
+<a class="jxr_linenumber" name="L6803" href="#L6803">6803</a> 	<strong class="jxr_keyword">void</strong> a231_wordCount() {
+<a class="jxr_linenumber" name="L6804" href="#L6804">6804</a> 		assertEquals(0, wordCount(<strong class="jxr_keyword">null</strong>));
+<a class="jxr_linenumber" name="L6805" href="#L6805">6805</a> 		assertEquals(0, wordCount(<span class="jxr_string">""</span>));
+<a class="jxr_linenumber" name="L6806" href="#L6806">6806</a> 		assertEquals(0, wordCount(<span class="jxr_string">"   "</span>));
+<a class="jxr_linenumber" name="L6807" href="#L6807">6807</a> 		assertEquals(1, wordCount(<span class="jxr_string">"hello"</span>));
+<a class="jxr_linenumber" name="L6808" href="#L6808">6808</a> 		assertEquals(2, wordCount(<span class="jxr_string">"Hello world"</span>));
+<a class="jxr_linenumber" name="L6809" href="#L6809">6809</a> 		assertEquals(4, wordCount(<span class="jxr_string">"The quick brown fox"</span>));
+<a class="jxr_linenumber" name="L6810" href="#L6810">6810</a> 		assertEquals(5, wordCount(<span class="jxr_string">"Hello, world! How are you?"</span>));
+<a class="jxr_linenumber" name="L6811" href="#L6811">6811</a> 		assertEquals(3, wordCount(<span class="jxr_string">"one\ttwo\nthree"</span>));
+<a class="jxr_linenumber" name="L6812" href="#L6812">6812</a> 		assertEquals(1, wordCount(<span class="jxr_string">"hello123"</span>));
+<a class="jxr_linenumber" name="L6813" href="#L6813">6813</a> 		<em class="jxr_comment">// Underscores are part of word characters, so "hello_world" is one word</em>
+<a class="jxr_linenumber" name="L6814" href="#L6814">6814</a> 		assertEquals(1, wordCount(<span class="jxr_string">"hello_world"</span>));
+<a class="jxr_linenumber" name="L6815" href="#L6815">6815</a> 		assertEquals(2, wordCount(<span class="jxr_string">"hello world"</span>));
+<a class="jxr_linenumber" name="L6816" href="#L6816">6816</a> 	}
+<a class="jxr_linenumber" name="L6817" href="#L6817">6817</a> 
+<a class="jxr_linenumber" name="L6818" href="#L6818">6818</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6819" href="#L6819">6819</a> 	<em class="jxr_comment">// wrap(String,int) and wrap(String,int,String)</em>
+<a class="jxr_linenumber" name="L6820" href="#L6820">6820</a> 	<em class="jxr_comment">//====================================================================================================</em>
+<a class="jxr_linenumber" name="L6821" href="#L6821">6821</a> 	@Test
+<a class="jxr_linenumber" name="L6822" href="#L6822">6822</a> 	<strong class="jxr_keyword">void</strong> a232_wrap() {
+<a class="jxr_linenumber" name="L6823" href="#L6823">6823</a> 		<em class="jxr_comment">// wrap(String,int) - uses default newline "\n"</em>
+<a class="jxr_linenumber" name="L6824" href="#L6824">6824</a> 		assertNull(wrap(<strong class="jxr_keyword">null</strong>, 10));
+<a class="jxr_linenumber" name="L6825" href="#L6825">6825</a> 		assertEquals(<span class="jxr_string">""</span>, wrap(<span class="jxr_string">""</span>, 10));
+<a class="jxr_linenumber" name="L6826" href="#L6826">6826</a> 		assertEquals(<span class="jxr_string">"hello\nworld"</span>, wrap(<span class="jxr_string">"hello world"</span>, 10));
+<a class="jxr_linenumber" name="L6827" href="#L6827">6827</a> 		assertEquals(<span class="jxr_string">"hello\nworld\ntest"</span>, wrap(<span class="jxr_string">"hello world test"</span>, 10));
+<a class="jxr_linenumber" name="L6828" href="#L6828">6828</a> 		assertEquals(<span class="jxr_string">"hello world"</span>, wrap(<span class="jxr_string">"hello world"</span>, 20));
+<a class="jxr_linenumber" name="L6829" href="#L6829">6829</a> 		assertEquals(<span class="jxr_string">"hello\nworld"</span>, wrap(<span class="jxr_string">"hello world"</span>, 5));
+<a class="jxr_linenumber" name="L6830" href="#L6830">6830</a> 		assertEquals(<span class="jxr_string">"supercalifragilisticexpialidocious"</span>, wrap(<span class="jxr_string">"supercalifragilisticexpialidocious"</span>, 10));
+<a class="jxr_linenumber" name="L6831" href="#L6831">6831</a> 		assertEquals(<span class="jxr_string">"hello\nworld"</span>, wrap(<span class="jxr_string">"hello  world"</span>, 10));
+<a class="jxr_linenumber" name="L6832" href="#L6832">6832</a> 		assertEquals(<span class="jxr_string">"line1\nline2"</span>, wrap(<span class="jxr_string">"line1\nline2"</span>, 10));
+<a class="jxr_linenumber" name="L6833" href="#L6833">6833</a> 		assertEquals(<span class="jxr_string">"a\nb\nc"</span>, wrap(<span class="jxr_string">"a b c"</span>, 1));
+<a class="jxr_linenumber" name="L6834" href="#L6834">6834</a> 		assertThrows(IllegalArgumentException.<strong class="jxr_keyword">class</strong>, () -&gt; wrap(<span class="jxr_string">"test"</span>, 0));
+<a class="jxr_linenumber" name="L6835" href="#L6835">6835</a> 		assertThrows(IllegalArgumentException.<strong class="jxr_keyword">class</strong>, () -&gt; wrap(<span class="jxr_string">"test"</span>, -1));
+<a class="jxr_linenumber" name="L6836" href="#L6836">6836</a> 
+<a class="jxr_linenumber" name="L6837" href="#L6837">6837</a> 		<em class="jxr_comment">// wrap(String,int,String) - with custom newline</em>
+<a class="jxr_linenumber" name="L6838" href="#L6838">6838</a> 		assertNull(wrap(<strong class="jxr_keyword">null</strong>, 10, <span class="jxr_string">"&lt;br&gt;"</span>));
+<a class="jxr_linenumber" name="L6839" href="#L6839">6839</a> 		assertEquals(<span class="jxr_string">""</span>, wrap(<span class="jxr_string">""</span>, 10, <span class="jxr_string">"&lt;br&gt;"</span>));
+<a class="jxr_linenumber" name="L6840" href="#L6840">6840</a> 		assertEquals(<span class="jxr_string">"hello&lt;br&gt;world"</span>, wrap(<span class="jxr_string">"hello world"</span>, 10, <span class="jxr_string">"&lt;br&gt;"</span>));
+<a class="jxr_linenumber" name="L6841" href="#L6841">6841</a> 		assertEquals(<span class="jxr_string">"hello&lt;br&gt;world&lt;br&gt;test"</span>, wrap(<span class="jxr_string">"hello world test"</span>, 10, <span class="jxr_string">"&lt;br&gt;"</span>));
+<a class="jxr_linenumber" name="L6842" href="#L6842">6842</a> 		assertEquals(<span class="jxr_string">"hello world"</span>, wrap(<span class="jxr_string">"hello world"</span>, 20, <span class="jxr_string">"&lt;br&gt;"</span>));
+<a class="jxr_linenumber" name="L6843" href="#L6843">6843</a> 		assertEquals(<span class="jxr_string">"hello&lt;br&gt;world"</span>, wrap(<span class="jxr_string">"hello world"</span>, 5, <span class="jxr_string">"&lt;br&gt;"</span>));
+<a class="jxr_linenumber" name="L6844" href="#L6844">6844</a> 		assertEquals(<span class="jxr_string">"supercalifragilisticexpialidocious"</span>, wrap(<span class="jxr_string">"supercalifragilisticexpialidocious"</span>, 10, <span class="jxr_string">"&lt;br&gt;"</span>));
+<a class="jxr_linenumber" name="L6845" href="#L6845">6845</a> 		assertEquals(<span class="jxr_string">"line1&lt;br&gt;line2"</span>, wrap(<span class="jxr_string">"line1\nline2"</span>, 10, <span class="jxr_string">"&lt;br&gt;"</span>));
+<a class="jxr_linenumber" name="L6846" href="#L6846">6846</a> 		assertEquals(<span class="jxr_string">"a&lt;br&gt;b&lt;br&gt;c"</span>, wrap(<span class="jxr_string">"a b c"</span>, 1, <span class="jxr_string">"&lt;br&gt;"</span>));
+<a class="jxr_linenumber" name="L6847" href="#L6847">6847</a> 		assertThrows(IllegalArgumentException.<strong class="jxr_keyword">class</strong>, () -&gt; wrap(<span class="jxr_string">"test"</span>, 0, <span class="jxr_string">"\n"</span>));
+<a class="jxr_linenumber" name="L6848" href="#L6848">6848</a> 		assertThrows(IllegalArgumentException.<strong class="jxr_keyword">class</strong>, () -&gt; wrap(<span class="jxr_string">"test"</span>, -1, <span class="jxr_string">"\n"</span>));
+<a class="jxr_linenumber" name="L6849" href="#L6849">6849</a> 		assertThrows(IllegalArgumentException.<strong class="jxr_keyword">class</strong>, () -&gt; wrap(<span class="jxr_string">"test"</span>, 10, <strong class="jxr_keyword">null</strong>));
+<a class="jxr_linenumber" name="L6850" href="#L6850">6850</a> 
+<a class="jxr_linenumber" name="L6851" href="#L6851">6851</a> 		<em class="jxr_comment">// Test</em>
+<a class="jxr_linenumber" name="L6852" href="#L6852">6852</a> 		<strong class="jxr_keyword">var</strong> result1 = wrap(<span class="jxr_string">"line1\n\nline2"</span>, 10, <span class="jxr_string">"\n"</span>);
+<a class="jxr_linenumber" name="L6853" href="#L6853">6853</a> 		assertTrue(result1.contains(<span class="jxr_string">"\n\n"</span>)); <em class="jxr_comment">// Empty line preserved</em>
+<a class="jxr_linenumber" name="L6854" href="#L6854">6854</a> 
+<a class="jxr_linenumber" name="L6855" href="#L6855">6855</a> 		<em class="jxr_comment">// Test)</em>
+<a class="jxr_linenumber" name="L6856" href="#L6856">6856</a> 		<em class="jxr_comment">// Multiple spaces create empty words that should be skipped</em>
+<a class="jxr_linenumber" name="L6857" href="#L6857">6857</a> 		<strong class="jxr_keyword">var</strong> result2 = wrap(<span class="jxr_string">"word1  word2"</span>, 10, <span class="jxr_string">"\n"</span>);
+<a class="jxr_linenumber" name="L6858" href="#L6858">6858</a> 		assertTrue(result2.contains(<span class="jxr_string">"word1"</span>));
+<a class="jxr_linenumber" name="L6859" href="#L6859">6859</a> 		assertTrue(result2.contains(<span class="jxr_string">"word2"</span>));
+<a class="jxr_linenumber" name="L6860" href="#L6860">6860</a> 		<em class="jxr_comment">// Test with multiple consecutive spaces</em>
+<a class="jxr_linenumber" name="L6861" href="#L6861">6861</a> 		<strong class="jxr_keyword">var</strong> result2b = wrap(<span class="jxr_string">"a   b   c"</span>, 10, <span class="jxr_string">"\n"</span>);
+<a class="jxr_linenumber" name="L6862" href="#L6862">6862</a> 		assertTrue(result2b.contains(<span class="jxr_string">"a"</span>));
+<a class="jxr_linenumber" name="L6863" href="#L6863">6863</a> 		assertTrue(result2b.contains(<span class="jxr_string">"b"</span>));
+<a class="jxr_linenumber" name="L6864" href="#L6864">6864</a> 		assertTrue(result2b.contains(<span class="jxr_string">"c"</span>));
+<a class="jxr_linenumber" name="L6865" href="#L6865">6865</a> 		<em class="jxr_comment">// Test with leading spaces - split(" +") creates empty string at start</em>
+<a class="jxr_linenumber" name="L6866" href="#L6866">6866</a> 		<strong class="jxr_keyword">var</strong> result2c = wrap(<span class="jxr_string">"  hello world"</span>, 10, <span class="jxr_string">"\n"</span>);
+<a class="jxr_linenumber" name="L6867" href="#L6867">6867</a> 		assertTrue(result2c.contains(<span class="jxr_string">"hello"</span>));
+<a class="jxr_linenumber" name="L6868" href="#L6868">6868</a> 		assertTrue(result2c.contains(<span class="jxr_string">"world"</span>));
+<a class="jxr_linenumber" name="L6869" href="#L6869">6869</a> 		<em class="jxr_comment">// Test with trailing spaces - split(" +") creates empty string at end</em>
+<a class="jxr_linenumber" name="L6870" href="#L6870">6870</a> 		<strong class="jxr_keyword">var</strong> result2d = wrap(<span class="jxr_string">"hello world  "</span>, 10, <span class="jxr_string">"\n"</span>);
+<a class="jxr_linenumber" name="L6871" href="#L6871">6871</a> 		assertTrue(result2d.contains(<span class="jxr_string">"hello"</span>));
+<a class="jxr_linenumber" name="L6872" href="#L6872">6872</a> 		assertTrue(result2d.contains(<span class="jxr_string">"world"</span>));
+<a class="jxr_linenumber" name="L6873" href="#L6873">6873</a> 		<em class="jxr_comment">// Test with both leading and trailing spaces</em>
+<a class="jxr_linenumber" name="L6874" href="#L6874">6874</a> 		<strong class="jxr_keyword">var</strong> result2e = wrap(<span class="jxr_string">"  hello world  "</span>, 10, <span class="jxr_string">"\n"</span>);
+<a class="jxr_linenumber" name="L6875" href="#L6875">6875</a> 		assertTrue(result2e.contains(<span class="jxr_string">"hello"</span>));
+<a class="jxr_linenumber" name="L6876" href="#L6876">6876</a> 		assertTrue(result2e.contains(<span class="jxr_string">"world"</span>));
+<a class="jxr_linenumber" name="L6877" href="#L6877">6877</a> 
+<a class="jxr_linenumber" name="L6878" href="#L6878">6878</a> 		<em class="jxr_comment">// Test</em>
+<a class="jxr_linenumber" name="L6879" href="#L6879">6879</a> 		<em class="jxr_comment">// This tests breaking a long word when it's the first word on a line</em>
+<a class="jxr_linenumber" name="L6880" href="#L6880">6880</a> 		<em class="jxr_comment">// Code path: result.length() &gt; 0 (result already has content)</em>
+<a class="jxr_linenumber" name="L6881" href="#L6881">6881</a> 		<em class="jxr_comment">// Code path: while loop that breaks word into chunks</em>
+<a class="jxr_linenumber" name="L6882" href="#L6882">6882</a> 		<em class="jxr_comment">//   Code path: wordPos &gt; 0 (not first iteration)</em>
+<a class="jxr_linenumber" name="L6883" href="#L6883">6883</a> 		<em class="jxr_comment">//   Code path: remaining &lt;= wrapLength (remaining fits)</em>
+<a class="jxr_linenumber" name="L6884" href="#L6884">6884</a> 		<em class="jxr_comment">//   Code path: append remaining</em>
+<a class="jxr_linenumber" name="L6885" href="#L6885">6885</a> 		<em class="jxr_comment">//   Code path: break</em>
+<a class="jxr_linenumber" name="L6886" href="#L6886">6886</a> 		<em class="jxr_comment">//   Code path: append chunk</em>
+<a class="jxr_linenumber" name="L6887" href="#L6887">6887</a> 		<em class="jxr_comment">//   Code path: advance position</em>
+<a class="jxr_linenumber" name="L6888" href="#L6888">6888</a> 		<strong class="jxr_keyword">var</strong> result3 = wrap(<span class="jxr_string">"short verylongword here"</span>, 5, <span class="jxr_string">"\n"</span>);
+<a class="jxr_linenumber" name="L6889" href="#L6889">6889</a> 		assertFalse(result3.contains(<span class="jxr_string">"verylongword"</span>)); <em class="jxr_comment">// Word should be split into chunks</em>
+<a class="jxr_linenumber" name="L6890" href="#L6890">6890</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> line : result3.split(<span class="jxr_string">"\n"</span>)) {
+<a class="jxr_linenumber" name="L6891" href="#L6891">6891</a> 			<strong class="jxr_keyword">if</strong> (! line.isEmpty())
+<a class="jxr_linenumber" name="L6892" href="#L6892">6892</a> 				assertTrue(line.length() &lt;= 5);
+<a class="jxr_linenumber" name="L6893" href="#L6893">6893</a> 		}
+<a class="jxr_linenumber" name="L6894" href="#L6894">6894</a> 		<em class="jxr_comment">// Test with result already having content  &gt; 0)</em>
+<a class="jxr_linenumber" name="L6895" href="#L6895">6895</a> 		<em class="jxr_comment">// After a previous line, a long word that needs breaking as first word on new line</em>
+<a class="jxr_linenumber" name="L6896" href="#L6896">6896</a> 		<em class="jxr_comment">// This happens when a previous line was completed and we start a new line</em>
+<a class="jxr_linenumber" name="L6897" href="#L6897">6897</a> 		<strong class="jxr_keyword">var</strong> result3b = wrap(<span class="jxr_string">"first\nverylongword here"</span>, 5, <span class="jxr_string">"\n"</span>);
+<a class="jxr_linenumber" name="L6898" href="#L6898">6898</a> 		<em class="jxr_comment">// After "first\n", "verylongword" is the first word on the new line and needs breaking</em>
+<a class="jxr_linenumber" name="L6899" href="#L6899">6899</a> 		assertTrue(result3b.contains(<span class="jxr_string">"first"</span>));
+<a class="jxr_linenumber" name="L6900" href="#L6900">6900</a> 		assertFalse(result3b.contains(<span class="jxr_string">"verylongword"</span>)); <em class="jxr_comment">// Long word should be broken</em>
+<a class="jxr_linenumber" name="L6901" href="#L6901">6901</a> 		<em class="jxr_comment">// Test word that breaks into multiple chunks (covers code path)</em>
+<a class="jxr_linenumber" name="L6902" href="#L6902">6902</a> 		<em class="jxr_comment">// Word length 15, wrapLength 5 -&gt; 3 chunks of 5, 5, 5</em>
+<a class="jxr_linenumber" name="L6903" href="#L6903">6903</a> 		<em class="jxr_comment">// This tests: wordPos &gt; 0 , append chunk , advance position </em>
+<a class="jxr_linenumber" name="L6904" href="#L6904">6904</a> 		<em class="jxr_comment">// And: remaining &lt;= wrapLength , append remaining , break </em>
+<a class="jxr_linenumber" name="L6905" href="#L6905">6905</a> 		<strong class="jxr_keyword">var</strong> result3c = wrap(<span class="jxr_string">"abcdefghijklmno here"</span>, 5, <span class="jxr_string">"\n"</span>);
+<a class="jxr_linenumber" name="L6906" href="#L6906">6906</a> 		assertTrue(result3c.contains(<span class="jxr_string">"abcde"</span>)); <em class="jxr_comment">// First chunk (wordPos == 0, no newline before)</em>
+<a class="jxr_linenumber" name="L6907" href="#L6907">6907</a> 		assertTrue(result3c.contains(<span class="jxr_string">"fghij"</span>)); <em class="jxr_comment">// Second chunk (wordPos &gt; 0, newline before, code path)</em>
+<a class="jxr_linenumber" name="L6908" href="#L6908">6908</a> 		assertTrue(result3c.contains(<span class="jxr_string">"klmno"</span>)); <em class="jxr_comment">// Third chunk (remaining &lt;= wrapLength, code path)</em>
+<a class="jxr_linenumber" name="L6909" href="#L6909">6909</a> 
+<a class="jxr_linenumber" name="L6910" href="#L6910">6910</a> 		<em class="jxr_comment">// Test</em>
+<a class="jxr_linenumber" name="L6911" href="#L6911">6911</a> 		<strong class="jxr_keyword">var</strong> result4 = wrap(<span class="jxr_string">"short word verylongword here"</span>, 10, <span class="jxr_string">"\n"</span>);
+<a class="jxr_linenumber" name="L6912" href="#L6912">6912</a> 		assertFalse(result4.contains(<span class="jxr_string">"verylongword"</span>)); <em class="jxr_comment">// Word should be split into chunks</em>
+<a class="jxr_linenumber" name="L6913" href="#L6913">6913</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> line : result4.split(<span class="jxr_string">"\n"</span>)) {
+<a class="jxr_linenumber" name="L6914" href="#L6914">6914</a> 			<strong class="jxr_keyword">if</strong> (! line.isEmpty())
+<a class="jxr_linenumber" name="L6915" href="#L6915">6915</a> 				assertTrue(line.length() &lt;= 10);
+<a class="jxr_linenumber" name="L6916" href="#L6916">6916</a> 		}
+<a class="jxr_linenumber" name="L6917" href="#L6917">6917</a> 
+<a class="jxr_linenumber" name="L6918" href="#L6918">6918</a> 		<em class="jxr_comment">// Test &gt; 0)</em>
+<a class="jxr_linenumber" name="L6919" href="#L6919">6919</a> 		<strong class="jxr_keyword">var</strong> result5 = wrap(<span class="jxr_string">"short word"</span>, 20, <span class="jxr_string">"\n"</span>);
+<a class="jxr_linenumber" name="L6920" href="#L6920">6920</a> 		assertEquals(<span class="jxr_string">"short word"</span>, result5); <em class="jxr_comment">// Remaining line appended</em>
+<a class="jxr_linenumber" name="L6921" href="#L6921">6921</a> 	}
+<a class="jxr_linenumber" name="L6922" href="#L6922">6922</a> }
 </pre>
 <hr/>
 <div id="footer">© 2016–2025 <a href="https://www.apache.org/">The Apache Software Foundation</a></div>
diff --git a/site/xref/org/apache/juneau/commons/utils/StringUtils.html b/site/xref/org/apache/juneau/commons/utils/StringUtils.html
index c3dcc18c98..c4ea2087bd 100644
--- a/site/xref/org/apache/juneau/commons/utils/StringUtils.html
+++ b/site/xref/org/apache/juneau/commons/utils/StringUtils.html
@@ -7466,917 +7466,914 @@
 <a class="jxr_linenumber" name="L7458" href="#L7458">7458</a> 					<strong class="jxr_keyword">var</strong> c2 = s.charAt(i + 1);
 <a class="jxr_linenumber" name="L7459" href="#L7459">7459</a> 					<strong class="jxr_keyword">if</strong> (escaped.contains(c2)) {
 <a class="jxr_linenumber" name="L7460" href="#L7460">7460</a> 						i++;  <em class="jxr_comment">// NOSONAR - Intentional.</em>
-<a class="jxr_linenumber" name="L7461" href="#L7461">7461</a> 					} <strong class="jxr_keyword">else</strong> <strong class="jxr_keyword">if</strong> (c2 == '&#92;&#92;') {
-<a class="jxr_linenumber" name="L7462" href="#L7462">7462</a> 						sb.append('&#92;&#92;');
-<a class="jxr_linenumber" name="L7463" href="#L7463">7463</a> 						i++;  <em class="jxr_comment">// NOSONAR - Intentional.</em>
-<a class="jxr_linenumber" name="L7464" href="#L7464">7464</a> 					}
-<a class="jxr_linenumber" name="L7465" href="#L7465">7465</a> 				}
-<a class="jxr_linenumber" name="L7466" href="#L7466">7466</a> 			}
-<a class="jxr_linenumber" name="L7467" href="#L7467">7467</a> 			sb.append(s.charAt(i));
-<a class="jxr_linenumber" name="L7468" href="#L7468">7468</a> 		}
-<a class="jxr_linenumber" name="L7469" href="#L7469">7469</a> 		<strong class="jxr_keyword">return</strong> sb.toString();
-<a class="jxr_linenumber" name="L7470" href="#L7470">7470</a> 	}
-<a class="jxr_linenumber" name="L7471" href="#L7471">7471</a> 
-<a class="jxr_linenumber" name="L7472" href="#L7472">7472</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7473" href="#L7473">7473</a> <em class="jxr_javadoccomment">	 * Unescapes HTML entities in a string.</em>
-<a class="jxr_linenumber" name="L7474" href="#L7474">7474</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7475" href="#L7475">7475</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
-<a class="jxr_linenumber" name="L7476" href="#L7476">7476</a> <em class="jxr_javadoccomment">	 * Unescapes the following HTML entities:</em>
-<a class="jxr_linenumber" name="L7477" href="#L7477">7477</a> <em class="jxr_javadoccomment">	 * &lt;ul&gt;</em>
-<a class="jxr_linenumber" name="L7478" href="#L7478">7478</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;amp;"&lt;/js&gt; → &lt;js&gt;'&amp;amp;'&lt;/js&gt;&lt;/li&gt;</em>
-<a class="jxr_linenumber" name="L7479" href="#L7479">7479</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;lt;"&lt;/js&gt; → &lt;js&gt;'&amp;lt;'&lt;/js&gt;&lt;/li&gt;</em>
-<a class="jxr_linenumber" name="L7480" href="#L7480">7480</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;gt;"&lt;/js&gt; → &lt;js&gt;'&amp;gt;'&lt;/js&gt;&lt;/li&gt;</em>
-<a class="jxr_linenumber" name="L7481" href="#L7481">7481</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;quot;"&lt;/js&gt; → &lt;js&gt;'&quot;'&lt;/js&gt;&lt;/li&gt;</em>
-<a class="jxr_linenumber" name="L7482" href="#L7482">7482</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;#39;"&lt;/js&gt; or &lt;js&gt;"&amp;amp;apos;"&lt;/js&gt; → &lt;js&gt;'\''&lt;/js&gt;&lt;/li&gt;</em>
-<a class="jxr_linenumber" name="L7483" href="#L7483">7483</a> <em class="jxr_javadoccomment">	 * &lt;/ul&gt;</em>
-<a class="jxr_linenumber" name="L7484" href="#L7484">7484</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7485" href="#L7485">7485</a> <em class="jxr_javadoccomment">	 * &lt;h5 class='section'&gt;Example:&lt;/h5&gt;</em>
-<a class="jxr_linenumber" name="L7486" href="#L7486">7486</a> <em class="jxr_javadoccomment">	 * &lt;p class='bjava'&gt;</em>
-<a class="jxr_linenumber" name="L7487" href="#L7487">7487</a> <em class="jxr_javadoccomment">	 * 	unescapeHtml(&lt;js&gt;"&amp;amp;lt;script&amp;amp;gt;"&lt;/js&gt;);     &lt;jc&gt;// Returns: "&amp;lt;script&amp;gt;"&lt;/jc&gt;</em>
-<a class="jxr_linenumber" name="L7488" href="#L7488">7488</a> <em class="jxr_javadoccomment">	 * &lt;/p&gt;</em>
-<a class="jxr_linenumber" name="L7489" href="#L7489">7489</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7490" href="#L7490">7490</a> <em class="jxr_javadoccomment">	 * @param str The string to unescape.</em>
-<a class="jxr_linenumber" name="L7491" href="#L7491">7491</a> <em class="jxr_javadoccomment">	 * @return The unescaped string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
-<a class="jxr_linenumber" name="L7492" href="#L7492">7492</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7493" href="#L7493">7493</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String unescapeHtml(String str) {
-<a class="jxr_linenumber" name="L7494" href="#L7494">7494</a> 		<strong class="jxr_keyword">if</strong> (str == <strong class="jxr_keyword">null</strong>)
-<a class="jxr_linenumber" name="L7495" href="#L7495">7495</a> 			<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">null</strong>;
-<a class="jxr_linenumber" name="L7496" href="#L7496">7496</a> 		<em class="jxr_comment">// Must unescape &amp;amp; last to avoid interfering with other entities</em>
-<a class="jxr_linenumber" name="L7497" href="#L7497">7497</a> 		<strong class="jxr_keyword">return</strong> str.replace(<span class="jxr_string">"&amp;lt;"</span>, <span class="jxr_string">"&lt;"</span>).replace(<span class="jxr_string">"&amp;gt;"</span>, <span class="jxr_string">"&gt;"</span>).replace(<span class="jxr_string">"&amp;quot;"</span>, <span class="jxr_string">"\&quot;"</span>).replace(<span class="jxr_string">"&amp;#39;"</span>, <span class="jxr_string">"'"</span>).replace(< [...]
-<a class="jxr_linenumber" name="L7498" href="#L7498">7498</a> 	}
-<a class="jxr_linenumber" name="L7499" href="#L7499">7499</a> 
-<a class="jxr_linenumber" name="L7500" href="#L7500">7500</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7501" href="#L7501">7501</a> <em class="jxr_javadoccomment">	 * Unescapes XML entities in a string.</em>
-<a class="jxr_linenumber" name="L7502" href="#L7502">7502</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7503" href="#L7503">7503</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
-<a class="jxr_linenumber" name="L7504" href="#L7504">7504</a> <em class="jxr_javadoccomment">	 * Unescapes the following XML entities:</em>
-<a class="jxr_linenumber" name="L7505" href="#L7505">7505</a> <em class="jxr_javadoccomment">	 * &lt;ul&gt;</em>
-<a class="jxr_linenumber" name="L7506" href="#L7506">7506</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;amp;"&lt;/js&gt; → &lt;js&gt;'&amp;amp;'&lt;/js&gt;&lt;/li&gt;</em>
-<a class="jxr_linenumber" name="L7507" href="#L7507">7507</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;lt;"&lt;/js&gt; → &lt;js&gt;'&amp;lt;'&lt;/js&gt;&lt;/li&gt;</em>
-<a class="jxr_linenumber" name="L7508" href="#L7508">7508</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;gt;"&lt;/js&gt; → &lt;js&gt;'&amp;gt;'&lt;/js&gt;&lt;/li&gt;</em>
-<a class="jxr_linenumber" name="L7509" href="#L7509">7509</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;quot;"&lt;/js&gt; → &lt;js&gt;'&quot;'&lt;/js&gt;&lt;/li&gt;</em>
-<a class="jxr_linenumber" name="L7510" href="#L7510">7510</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;apos;"&lt;/js&gt; → &lt;js&gt;'\''&lt;/js&gt;&lt;/li&gt;</em>
-<a class="jxr_linenumber" name="L7511" href="#L7511">7511</a> <em class="jxr_javadoccomment">	 * &lt;/ul&gt;</em>
-<a class="jxr_linenumber" name="L7512" href="#L7512">7512</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7513" href="#L7513">7513</a> <em class="jxr_javadoccomment">	 * &lt;h5 class='section'&gt;Example:&lt;/h5&gt;</em>
-<a class="jxr_linenumber" name="L7514" href="#L7514">7514</a> <em class="jxr_javadoccomment">	 * &lt;p class='bjava'&gt;</em>
-<a class="jxr_linenumber" name="L7515" href="#L7515">7515</a> <em class="jxr_javadoccomment">	 * 	unescapeXml(&lt;js&gt;"&amp;amp;lt;tag&amp;amp;gt;"&lt;/js&gt;);     &lt;jc&gt;// Returns: "&amp;lt;tag&amp;gt;"&lt;/jc&gt;</em>
-<a class="jxr_linenumber" name="L7516" href="#L7516">7516</a> <em class="jxr_javadoccomment">	 * &lt;/p&gt;</em>
-<a class="jxr_linenumber" name="L7517" href="#L7517">7517</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7518" href="#L7518">7518</a> <em class="jxr_javadoccomment">	 * @param str The string to unescape.</em>
-<a class="jxr_linenumber" name="L7519" href="#L7519">7519</a> <em class="jxr_javadoccomment">	 * @return The unescaped string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
-<a class="jxr_linenumber" name="L7520" href="#L7520">7520</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7521" href="#L7521">7521</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String unescapeXml(String str) {
-<a class="jxr_linenumber" name="L7522" href="#L7522">7522</a> 		<strong class="jxr_keyword">if</strong> (str == <strong class="jxr_keyword">null</strong>)
-<a class="jxr_linenumber" name="L7523" href="#L7523">7523</a> 			<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">null</strong>;
-<a class="jxr_linenumber" name="L7524" href="#L7524">7524</a> 		<em class="jxr_comment">// Must unescape &amp;amp; last to avoid interfering with other entities</em>
-<a class="jxr_linenumber" name="L7525" href="#L7525">7525</a> 		<strong class="jxr_keyword">return</strong> str.replace(<span class="jxr_string">"&amp;lt;"</span>, <span class="jxr_string">"&lt;"</span>).replace(<span class="jxr_string">"&amp;gt;"</span>, <span class="jxr_string">"&gt;"</span>).replace(<span class="jxr_string">"&amp;quot;"</span>, <span class="jxr_string">"\&quot;"</span>).replace(<span class="jxr_string">"&amp;apos;"</span>, <span class="jxr_string">"'"</span>).replace( [...]
-<a class="jxr_linenumber" name="L7526" href="#L7526">7526</a> 	}
-<a class="jxr_linenumber" name="L7527" href="#L7527">7527</a> 
-<a class="jxr_linenumber" name="L7528" href="#L7528">7528</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7529" href="#L7529">7529</a> <em class="jxr_javadoccomment">	 * Creates an escaped-unicode sequence (e.g. &lt;js&gt;"&#92;&#92;u1234"&lt;/js&gt;) for the specified character.</em>
-<a class="jxr_linenumber" name="L7530" href="#L7530">7530</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7531" href="#L7531">7531</a> <em class="jxr_javadoccomment">	 * @param c The character to create a sequence for.</em>
-<a class="jxr_linenumber" name="L7532" href="#L7532">7532</a> <em class="jxr_javadoccomment">	 * @return An escaped-unicode sequence.</em>
-<a class="jxr_linenumber" name="L7533" href="#L7533">7533</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7534" href="#L7534">7534</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String unicodeSequence(<strong class="jxr_keyword">char</strong> c) {
-<a class="jxr_linenumber" name="L7535" href="#L7535">7535</a> 		<strong class="jxr_keyword">var</strong> sb = <strong class="jxr_keyword">new</strong> StringBuilder(6);
-<a class="jxr_linenumber" name="L7536" href="#L7536">7536</a> 		sb.append('&#92;&#92;').append('u');
-<a class="jxr_linenumber" name="L7537" href="#L7537">7537</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> cc : toHex4(c))
-<a class="jxr_linenumber" name="L7538" href="#L7538">7538</a> 			sb.append(cc);
-<a class="jxr_linenumber" name="L7539" href="#L7539">7539</a> 		<strong class="jxr_keyword">return</strong> sb.toString();
-<a class="jxr_linenumber" name="L7540" href="#L7540">7540</a> 	}
-<a class="jxr_linenumber" name="L7541" href="#L7541">7541</a> 
-<a class="jxr_linenumber" name="L7542" href="#L7542">7542</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7543" href="#L7543">7543</a> <em class="jxr_javadoccomment">	 * Null-safe convenience method for {@link String#toUpperCase()}.</em>
+<a class="jxr_linenumber" name="L7461" href="#L7461">7461</a> 					}
+<a class="jxr_linenumber" name="L7462" href="#L7462">7462</a> 				}
+<a class="jxr_linenumber" name="L7463" href="#L7463">7463</a> 			}
+<a class="jxr_linenumber" name="L7464" href="#L7464">7464</a> 			sb.append(s.charAt(i));
+<a class="jxr_linenumber" name="L7465" href="#L7465">7465</a> 		}
+<a class="jxr_linenumber" name="L7466" href="#L7466">7466</a> 		<strong class="jxr_keyword">return</strong> sb.toString();
+<a class="jxr_linenumber" name="L7467" href="#L7467">7467</a> 	}
+<a class="jxr_linenumber" name="L7468" href="#L7468">7468</a> 
+<a class="jxr_linenumber" name="L7469" href="#L7469">7469</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7470" href="#L7470">7470</a> <em class="jxr_javadoccomment">	 * Unescapes HTML entities in a string.</em>
+<a class="jxr_linenumber" name="L7471" href="#L7471">7471</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7472" href="#L7472">7472</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
+<a class="jxr_linenumber" name="L7473" href="#L7473">7473</a> <em class="jxr_javadoccomment">	 * Unescapes the following HTML entities:</em>
+<a class="jxr_linenumber" name="L7474" href="#L7474">7474</a> <em class="jxr_javadoccomment">	 * &lt;ul&gt;</em>
+<a class="jxr_linenumber" name="L7475" href="#L7475">7475</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;amp;"&lt;/js&gt; → &lt;js&gt;'&amp;amp;'&lt;/js&gt;&lt;/li&gt;</em>
+<a class="jxr_linenumber" name="L7476" href="#L7476">7476</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;lt;"&lt;/js&gt; → &lt;js&gt;'&amp;lt;'&lt;/js&gt;&lt;/li&gt;</em>
+<a class="jxr_linenumber" name="L7477" href="#L7477">7477</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;gt;"&lt;/js&gt; → &lt;js&gt;'&amp;gt;'&lt;/js&gt;&lt;/li&gt;</em>
+<a class="jxr_linenumber" name="L7478" href="#L7478">7478</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;quot;"&lt;/js&gt; → &lt;js&gt;'&quot;'&lt;/js&gt;&lt;/li&gt;</em>
+<a class="jxr_linenumber" name="L7479" href="#L7479">7479</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;#39;"&lt;/js&gt; or &lt;js&gt;"&amp;amp;apos;"&lt;/js&gt; → &lt;js&gt;'\''&lt;/js&gt;&lt;/li&gt;</em>
+<a class="jxr_linenumber" name="L7480" href="#L7480">7480</a> <em class="jxr_javadoccomment">	 * &lt;/ul&gt;</em>
+<a class="jxr_linenumber" name="L7481" href="#L7481">7481</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7482" href="#L7482">7482</a> <em class="jxr_javadoccomment">	 * &lt;h5 class='section'&gt;Example:&lt;/h5&gt;</em>
+<a class="jxr_linenumber" name="L7483" href="#L7483">7483</a> <em class="jxr_javadoccomment">	 * &lt;p class='bjava'&gt;</em>
+<a class="jxr_linenumber" name="L7484" href="#L7484">7484</a> <em class="jxr_javadoccomment">	 * 	unescapeHtml(&lt;js&gt;"&amp;amp;lt;script&amp;amp;gt;"&lt;/js&gt;);     &lt;jc&gt;// Returns: "&amp;lt;script&amp;gt;"&lt;/jc&gt;</em>
+<a class="jxr_linenumber" name="L7485" href="#L7485">7485</a> <em class="jxr_javadoccomment">	 * &lt;/p&gt;</em>
+<a class="jxr_linenumber" name="L7486" href="#L7486">7486</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7487" href="#L7487">7487</a> <em class="jxr_javadoccomment">	 * @param str The string to unescape.</em>
+<a class="jxr_linenumber" name="L7488" href="#L7488">7488</a> <em class="jxr_javadoccomment">	 * @return The unescaped string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
+<a class="jxr_linenumber" name="L7489" href="#L7489">7489</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7490" href="#L7490">7490</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String unescapeHtml(String str) {
+<a class="jxr_linenumber" name="L7491" href="#L7491">7491</a> 		<strong class="jxr_keyword">if</strong> (str == <strong class="jxr_keyword">null</strong>)
+<a class="jxr_linenumber" name="L7492" href="#L7492">7492</a> 			<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">null</strong>;
+<a class="jxr_linenumber" name="L7493" href="#L7493">7493</a> 		<em class="jxr_comment">// Must unescape &amp;amp; last to avoid interfering with other entities</em>
+<a class="jxr_linenumber" name="L7494" href="#L7494">7494</a> 		<strong class="jxr_keyword">return</strong> str.replace(<span class="jxr_string">"&amp;lt;"</span>, <span class="jxr_string">"&lt;"</span>).replace(<span class="jxr_string">"&amp;gt;"</span>, <span class="jxr_string">"&gt;"</span>).replace(<span class="jxr_string">"&amp;quot;"</span>, <span class="jxr_string">"\&quot;"</span>).replace(<span class="jxr_string">"&amp;#39;"</span>, <span class="jxr_string">"'"</span>).replace(< [...]
+<a class="jxr_linenumber" name="L7495" href="#L7495">7495</a> 	}
+<a class="jxr_linenumber" name="L7496" href="#L7496">7496</a> 
+<a class="jxr_linenumber" name="L7497" href="#L7497">7497</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7498" href="#L7498">7498</a> <em class="jxr_javadoccomment">	 * Unescapes XML entities in a string.</em>
+<a class="jxr_linenumber" name="L7499" href="#L7499">7499</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7500" href="#L7500">7500</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
+<a class="jxr_linenumber" name="L7501" href="#L7501">7501</a> <em class="jxr_javadoccomment">	 * Unescapes the following XML entities:</em>
+<a class="jxr_linenumber" name="L7502" href="#L7502">7502</a> <em class="jxr_javadoccomment">	 * &lt;ul&gt;</em>
+<a class="jxr_linenumber" name="L7503" href="#L7503">7503</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;amp;"&lt;/js&gt; → &lt;js&gt;'&amp;amp;'&lt;/js&gt;&lt;/li&gt;</em>
+<a class="jxr_linenumber" name="L7504" href="#L7504">7504</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;lt;"&lt;/js&gt; → &lt;js&gt;'&amp;lt;'&lt;/js&gt;&lt;/li&gt;</em>
+<a class="jxr_linenumber" name="L7505" href="#L7505">7505</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;gt;"&lt;/js&gt; → &lt;js&gt;'&amp;gt;'&lt;/js&gt;&lt;/li&gt;</em>
+<a class="jxr_linenumber" name="L7506" href="#L7506">7506</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;quot;"&lt;/js&gt; → &lt;js&gt;'&quot;'&lt;/js&gt;&lt;/li&gt;</em>
+<a class="jxr_linenumber" name="L7507" href="#L7507">7507</a> <em class="jxr_javadoccomment">	 *   &lt;li&gt;&lt;js&gt;"&amp;amp;apos;"&lt;/js&gt; → &lt;js&gt;'\''&lt;/js&gt;&lt;/li&gt;</em>
+<a class="jxr_linenumber" name="L7508" href="#L7508">7508</a> <em class="jxr_javadoccomment">	 * &lt;/ul&gt;</em>
+<a class="jxr_linenumber" name="L7509" href="#L7509">7509</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7510" href="#L7510">7510</a> <em class="jxr_javadoccomment">	 * &lt;h5 class='section'&gt;Example:&lt;/h5&gt;</em>
+<a class="jxr_linenumber" name="L7511" href="#L7511">7511</a> <em class="jxr_javadoccomment">	 * &lt;p class='bjava'&gt;</em>
+<a class="jxr_linenumber" name="L7512" href="#L7512">7512</a> <em class="jxr_javadoccomment">	 * 	unescapeXml(&lt;js&gt;"&amp;amp;lt;tag&amp;amp;gt;"&lt;/js&gt;);     &lt;jc&gt;// Returns: "&amp;lt;tag&amp;gt;"&lt;/jc&gt;</em>
+<a class="jxr_linenumber" name="L7513" href="#L7513">7513</a> <em class="jxr_javadoccomment">	 * &lt;/p&gt;</em>
+<a class="jxr_linenumber" name="L7514" href="#L7514">7514</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7515" href="#L7515">7515</a> <em class="jxr_javadoccomment">	 * @param str The string to unescape.</em>
+<a class="jxr_linenumber" name="L7516" href="#L7516">7516</a> <em class="jxr_javadoccomment">	 * @return The unescaped string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
+<a class="jxr_linenumber" name="L7517" href="#L7517">7517</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7518" href="#L7518">7518</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String unescapeXml(String str) {
+<a class="jxr_linenumber" name="L7519" href="#L7519">7519</a> 		<strong class="jxr_keyword">if</strong> (str == <strong class="jxr_keyword">null</strong>)
+<a class="jxr_linenumber" name="L7520" href="#L7520">7520</a> 			<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">null</strong>;
+<a class="jxr_linenumber" name="L7521" href="#L7521">7521</a> 		<em class="jxr_comment">// Must unescape &amp;amp; last to avoid interfering with other entities</em>
+<a class="jxr_linenumber" name="L7522" href="#L7522">7522</a> 		<strong class="jxr_keyword">return</strong> str.replace(<span class="jxr_string">"&amp;lt;"</span>, <span class="jxr_string">"&lt;"</span>).replace(<span class="jxr_string">"&amp;gt;"</span>, <span class="jxr_string">"&gt;"</span>).replace(<span class="jxr_string">"&amp;quot;"</span>, <span class="jxr_string">"\&quot;"</span>).replace(<span class="jxr_string">"&amp;apos;"</span>, <span class="jxr_string">"'"</span>).replace( [...]
+<a class="jxr_linenumber" name="L7523" href="#L7523">7523</a> 	}
+<a class="jxr_linenumber" name="L7524" href="#L7524">7524</a> 
+<a class="jxr_linenumber" name="L7525" href="#L7525">7525</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7526" href="#L7526">7526</a> <em class="jxr_javadoccomment">	 * Creates an escaped-unicode sequence (e.g. &lt;js&gt;"&#92;&#92;u1234"&lt;/js&gt;) for the specified character.</em>
+<a class="jxr_linenumber" name="L7527" href="#L7527">7527</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7528" href="#L7528">7528</a> <em class="jxr_javadoccomment">	 * @param c The character to create a sequence for.</em>
+<a class="jxr_linenumber" name="L7529" href="#L7529">7529</a> <em class="jxr_javadoccomment">	 * @return An escaped-unicode sequence.</em>
+<a class="jxr_linenumber" name="L7530" href="#L7530">7530</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7531" href="#L7531">7531</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String unicodeSequence(<strong class="jxr_keyword">char</strong> c) {
+<a class="jxr_linenumber" name="L7532" href="#L7532">7532</a> 		<strong class="jxr_keyword">var</strong> sb = <strong class="jxr_keyword">new</strong> StringBuilder(6);
+<a class="jxr_linenumber" name="L7533" href="#L7533">7533</a> 		sb.append('&#92;&#92;').append('u');
+<a class="jxr_linenumber" name="L7534" href="#L7534">7534</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> cc : toHex4(c))
+<a class="jxr_linenumber" name="L7535" href="#L7535">7535</a> 			sb.append(cc);
+<a class="jxr_linenumber" name="L7536" href="#L7536">7536</a> 		<strong class="jxr_keyword">return</strong> sb.toString();
+<a class="jxr_linenumber" name="L7537" href="#L7537">7537</a> 	}
+<a class="jxr_linenumber" name="L7538" href="#L7538">7538</a> 
+<a class="jxr_linenumber" name="L7539" href="#L7539">7539</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7540" href="#L7540">7540</a> <em class="jxr_javadoccomment">	 * Null-safe convenience method for {@link String#toUpperCase()}.</em>
+<a class="jxr_linenumber" name="L7541" href="#L7541">7541</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7542" href="#L7542">7542</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
+<a class="jxr_linenumber" name="L7543" href="#L7543">7543</a> <em class="jxr_javadoccomment">	 * Converts the string to uppercase if not null.</em>
 <a class="jxr_linenumber" name="L7544" href="#L7544">7544</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7545" href="#L7545">7545</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
-<a class="jxr_linenumber" name="L7546" href="#L7546">7546</a> <em class="jxr_javadoccomment">	 * Converts the string to uppercase if not null.</em>
-<a class="jxr_linenumber" name="L7547" href="#L7547">7547</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7548" href="#L7548">7548</a> <em class="jxr_javadoccomment">	 * @param s The string to convert.</em>
-<a class="jxr_linenumber" name="L7549" href="#L7549">7549</a> <em class="jxr_javadoccomment">	 * @return The uppercase string, or &lt;jk&gt;null&lt;/jk&gt; if the input was &lt;jk&gt;null&lt;/jk&gt;.</em>
-<a class="jxr_linenumber" name="L7550" href="#L7550">7550</a> <em class="jxr_javadoccomment">	 * @see #lowerCase(String)</em>
-<a class="jxr_linenumber" name="L7551" href="#L7551">7551</a> <em class="jxr_javadoccomment">	 * @see Utils#uc(String)</em>
-<a class="jxr_linenumber" name="L7552" href="#L7552">7552</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7553" href="#L7553">7553</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String upperCase(String s) {
-<a class="jxr_linenumber" name="L7554" href="#L7554">7554</a> 		<strong class="jxr_keyword">return</strong> s == <strong class="jxr_keyword">null</strong> ? <strong class="jxr_keyword">null</strong> : s.toUpperCase();
-<a class="jxr_linenumber" name="L7555" href="#L7555">7555</a> 	}
-<a class="jxr_linenumber" name="L7556" href="#L7556">7556</a> 
-<a class="jxr_linenumber" name="L7557" href="#L7557">7557</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7558" href="#L7558">7558</a> <em class="jxr_javadoccomment">	 * Decodes a &lt;c&gt;application/x-www-form-urlencoded&lt;/c&gt; string using &lt;c&gt;UTF-8&lt;/c&gt; encoding scheme.</em>
-<a class="jxr_linenumber" name="L7559" href="#L7559">7559</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7560" href="#L7560">7560</a> <em class="jxr_javadoccomment">	 * @param s The string to decode.</em>
-<a class="jxr_linenumber" name="L7561" href="#L7561">7561</a> <em class="jxr_javadoccomment">	 * @return The decoded string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
-<a class="jxr_linenumber" name="L7562" href="#L7562">7562</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7563" href="#L7563">7563</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String urlDecode(String s) {
+<a class="jxr_linenumber" name="L7545" href="#L7545">7545</a> <em class="jxr_javadoccomment">	 * @param s The string to convert.</em>
+<a class="jxr_linenumber" name="L7546" href="#L7546">7546</a> <em class="jxr_javadoccomment">	 * @return The uppercase string, or &lt;jk&gt;null&lt;/jk&gt; if the input was &lt;jk&gt;null&lt;/jk&gt;.</em>
+<a class="jxr_linenumber" name="L7547" href="#L7547">7547</a> <em class="jxr_javadoccomment">	 * @see #lowerCase(String)</em>
+<a class="jxr_linenumber" name="L7548" href="#L7548">7548</a> <em class="jxr_javadoccomment">	 * @see Utils#uc(String)</em>
+<a class="jxr_linenumber" name="L7549" href="#L7549">7549</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7550" href="#L7550">7550</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String upperCase(String s) {
+<a class="jxr_linenumber" name="L7551" href="#L7551">7551</a> 		<strong class="jxr_keyword">return</strong> s == <strong class="jxr_keyword">null</strong> ? <strong class="jxr_keyword">null</strong> : s.toUpperCase();
+<a class="jxr_linenumber" name="L7552" href="#L7552">7552</a> 	}
+<a class="jxr_linenumber" name="L7553" href="#L7553">7553</a> 
+<a class="jxr_linenumber" name="L7554" href="#L7554">7554</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7555" href="#L7555">7555</a> <em class="jxr_javadoccomment">	 * Decodes a &lt;c&gt;application/x-www-form-urlencoded&lt;/c&gt; string using &lt;c&gt;UTF-8&lt;/c&gt; encoding scheme.</em>
+<a class="jxr_linenumber" name="L7556" href="#L7556">7556</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7557" href="#L7557">7557</a> <em class="jxr_javadoccomment">	 * @param s The string to decode.</em>
+<a class="jxr_linenumber" name="L7558" href="#L7558">7558</a> <em class="jxr_javadoccomment">	 * @return The decoded string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
+<a class="jxr_linenumber" name="L7559" href="#L7559">7559</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7560" href="#L7560">7560</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String urlDecode(String s) {
+<a class="jxr_linenumber" name="L7561" href="#L7561">7561</a> 
+<a class="jxr_linenumber" name="L7562" href="#L7562">7562</a> 		<strong class="jxr_keyword">if</strong> (s == <strong class="jxr_keyword">null</strong>)
+<a class="jxr_linenumber" name="L7563" href="#L7563">7563</a> 			<strong class="jxr_keyword">return</strong> s;
 <a class="jxr_linenumber" name="L7564" href="#L7564">7564</a> 
-<a class="jxr_linenumber" name="L7565" href="#L7565">7565</a> 		<strong class="jxr_keyword">if</strong> (s == <strong class="jxr_keyword">null</strong>)
-<a class="jxr_linenumber" name="L7566" href="#L7566">7566</a> 			<strong class="jxr_keyword">return</strong> s;
-<a class="jxr_linenumber" name="L7567" href="#L7567">7567</a> 
-<a class="jxr_linenumber" name="L7568" href="#L7568">7568</a> 		<strong class="jxr_keyword">var</strong> needsDecode = false;
-<a class="jxr_linenumber" name="L7569" href="#L7569">7569</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; s.length() &amp;&amp; ! needsDecode; i++) {
-<a class="jxr_linenumber" name="L7570" href="#L7570">7570</a> 			<strong class="jxr_keyword">var</strong> c = s.charAt(i);
-<a class="jxr_linenumber" name="L7571" href="#L7571">7571</a> 			<strong class="jxr_keyword">if</strong> (c == '+' || c == '%')
-<a class="jxr_linenumber" name="L7572" href="#L7572">7572</a> 				needsDecode = <strong class="jxr_keyword">true</strong>;
-<a class="jxr_linenumber" name="L7573" href="#L7573">7573</a> 		}
-<a class="jxr_linenumber" name="L7574" href="#L7574">7574</a> 
-<a class="jxr_linenumber" name="L7575" href="#L7575">7575</a> 		<strong class="jxr_keyword">if</strong> (needsDecode) {
-<a class="jxr_linenumber" name="L7576" href="#L7576">7576</a> 			<strong class="jxr_keyword">return</strong> safe(()-&gt;URLDecoder.decode(s, <span class="jxr_string">"UTF-8"</span>));
-<a class="jxr_linenumber" name="L7577" href="#L7577">7577</a> 		}
-<a class="jxr_linenumber" name="L7578" href="#L7578">7578</a> 		<strong class="jxr_keyword">return</strong> s;
-<a class="jxr_linenumber" name="L7579" href="#L7579">7579</a> 	}
-<a class="jxr_linenumber" name="L7580" href="#L7580">7580</a> 
-<a class="jxr_linenumber" name="L7581" href="#L7581">7581</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7582" href="#L7582">7582</a> <em class="jxr_javadoccomment">	 * Encodes a &lt;c&gt;application/x-www-form-urlencoded&lt;/c&gt; string using &lt;c&gt;UTF-8&lt;/c&gt; encoding scheme.</em>
-<a class="jxr_linenumber" name="L7583" href="#L7583">7583</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7584" href="#L7584">7584</a> <em class="jxr_javadoccomment">	 * @param s The string to encode.</em>
-<a class="jxr_linenumber" name="L7585" href="#L7585">7585</a> <em class="jxr_javadoccomment">	 * @return The encoded string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
-<a class="jxr_linenumber" name="L7586" href="#L7586">7586</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7587" href="#L7587">7587</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String urlEncode(String s) {
+<a class="jxr_linenumber" name="L7565" href="#L7565">7565</a> 		<strong class="jxr_keyword">var</strong> needsDecode = false;
+<a class="jxr_linenumber" name="L7566" href="#L7566">7566</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; s.length() &amp;&amp; ! needsDecode; i++) {
+<a class="jxr_linenumber" name="L7567" href="#L7567">7567</a> 			<strong class="jxr_keyword">var</strong> c = s.charAt(i);
+<a class="jxr_linenumber" name="L7568" href="#L7568">7568</a> 			<strong class="jxr_keyword">if</strong> (c == '+' || c == '%')
+<a class="jxr_linenumber" name="L7569" href="#L7569">7569</a> 				needsDecode = <strong class="jxr_keyword">true</strong>;
+<a class="jxr_linenumber" name="L7570" href="#L7570">7570</a> 		}
+<a class="jxr_linenumber" name="L7571" href="#L7571">7571</a> 
+<a class="jxr_linenumber" name="L7572" href="#L7572">7572</a> 		<strong class="jxr_keyword">if</strong> (needsDecode) {
+<a class="jxr_linenumber" name="L7573" href="#L7573">7573</a> 			<strong class="jxr_keyword">return</strong> safe(()-&gt;URLDecoder.decode(s, <span class="jxr_string">"UTF-8"</span>));
+<a class="jxr_linenumber" name="L7574" href="#L7574">7574</a> 		}
+<a class="jxr_linenumber" name="L7575" href="#L7575">7575</a> 		<strong class="jxr_keyword">return</strong> s;
+<a class="jxr_linenumber" name="L7576" href="#L7576">7576</a> 	}
+<a class="jxr_linenumber" name="L7577" href="#L7577">7577</a> 
+<a class="jxr_linenumber" name="L7578" href="#L7578">7578</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7579" href="#L7579">7579</a> <em class="jxr_javadoccomment">	 * Encodes a &lt;c&gt;application/x-www-form-urlencoded&lt;/c&gt; string using &lt;c&gt;UTF-8&lt;/c&gt; encoding scheme.</em>
+<a class="jxr_linenumber" name="L7580" href="#L7580">7580</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7581" href="#L7581">7581</a> <em class="jxr_javadoccomment">	 * @param s The string to encode.</em>
+<a class="jxr_linenumber" name="L7582" href="#L7582">7582</a> <em class="jxr_javadoccomment">	 * @return The encoded string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
+<a class="jxr_linenumber" name="L7583" href="#L7583">7583</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7584" href="#L7584">7584</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String urlEncode(String s) {
+<a class="jxr_linenumber" name="L7585" href="#L7585">7585</a> 
+<a class="jxr_linenumber" name="L7586" href="#L7586">7586</a> 		<strong class="jxr_keyword">if</strong> (s == <strong class="jxr_keyword">null</strong>)
+<a class="jxr_linenumber" name="L7587" href="#L7587">7587</a> 			<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">null</strong>;
 <a class="jxr_linenumber" name="L7588" href="#L7588">7588</a> 
-<a class="jxr_linenumber" name="L7589" href="#L7589">7589</a> 		<strong class="jxr_keyword">if</strong> (s == <strong class="jxr_keyword">null</strong>)
-<a class="jxr_linenumber" name="L7590" href="#L7590">7590</a> 			<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">null</strong>;
-<a class="jxr_linenumber" name="L7591" href="#L7591">7591</a> 
-<a class="jxr_linenumber" name="L7592" href="#L7592">7592</a> 		<strong class="jxr_keyword">var</strong> needsEncode = false;
+<a class="jxr_linenumber" name="L7589" href="#L7589">7589</a> 		<strong class="jxr_keyword">var</strong> needsEncode = false;
+<a class="jxr_linenumber" name="L7590" href="#L7590">7590</a> 
+<a class="jxr_linenumber" name="L7591" href="#L7591">7591</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; s.length() &amp;&amp; ! needsEncode; i++)
+<a class="jxr_linenumber" name="L7592" href="#L7592">7592</a> 			needsEncode |= (! URL_UNENCODED_CHARS.contains(s.charAt(i)));
 <a class="jxr_linenumber" name="L7593" href="#L7593">7593</a> 
-<a class="jxr_linenumber" name="L7594" href="#L7594">7594</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; s.length() &amp;&amp; ! needsEncode; i++)
-<a class="jxr_linenumber" name="L7595" href="#L7595">7595</a> 			needsEncode |= (! URL_UNENCODED_CHARS.contains(s.charAt(i)));
-<a class="jxr_linenumber" name="L7596" href="#L7596">7596</a> 
-<a class="jxr_linenumber" name="L7597" href="#L7597">7597</a> 		<strong class="jxr_keyword">if</strong> (needsEncode) {
-<a class="jxr_linenumber" name="L7598" href="#L7598">7598</a> 			<strong class="jxr_keyword">return</strong> safe(()-&gt;URLEncoder.encode(s, <span class="jxr_string">"UTF-8"</span>));
-<a class="jxr_linenumber" name="L7599" href="#L7599">7599</a> 		}
+<a class="jxr_linenumber" name="L7594" href="#L7594">7594</a> 		<strong class="jxr_keyword">if</strong> (needsEncode) {
+<a class="jxr_linenumber" name="L7595" href="#L7595">7595</a> 			<strong class="jxr_keyword">return</strong> safe(()-&gt;URLEncoder.encode(s, <span class="jxr_string">"UTF-8"</span>));
+<a class="jxr_linenumber" name="L7596" href="#L7596">7596</a> 		}
+<a class="jxr_linenumber" name="L7597" href="#L7597">7597</a> 
+<a class="jxr_linenumber" name="L7598" href="#L7598">7598</a> 		<strong class="jxr_keyword">return</strong> s;
+<a class="jxr_linenumber" name="L7599" href="#L7599">7599</a> 	}
 <a class="jxr_linenumber" name="L7600" href="#L7600">7600</a> 
-<a class="jxr_linenumber" name="L7601" href="#L7601">7601</a> 		<strong class="jxr_keyword">return</strong> s;
-<a class="jxr_linenumber" name="L7602" href="#L7602">7602</a> 	}
-<a class="jxr_linenumber" name="L7603" href="#L7603">7603</a> 
-<a class="jxr_linenumber" name="L7604" href="#L7604">7604</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7605" href="#L7605">7605</a> <em class="jxr_javadoccomment">	 * Same as {@link #urlEncode(String)} except only escapes characters that absolutely need to be escaped.</em>
-<a class="jxr_linenumber" name="L7606" href="#L7606">7606</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7607" href="#L7607">7607</a> <em class="jxr_javadoccomment">	 * @param s The string to escape.</em>
-<a class="jxr_linenumber" name="L7608" href="#L7608">7608</a> <em class="jxr_javadoccomment">	 * @return The encoded string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
-<a class="jxr_linenumber" name="L7609" href="#L7609">7609</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7610" href="#L7610">7610</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String urlEncodeLax(String s) {
-<a class="jxr_linenumber" name="L7611" href="#L7611">7611</a> 		<strong class="jxr_keyword">if</strong> (s == <strong class="jxr_keyword">null</strong>)
-<a class="jxr_linenumber" name="L7612" href="#L7612">7612</a> 			<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">null</strong>;
-<a class="jxr_linenumber" name="L7613" href="#L7613">7613</a> 		<strong class="jxr_keyword">var</strong> needsEncode = false;
-<a class="jxr_linenumber" name="L7614" href="#L7614">7614</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; s.length() &amp;&amp; ! needsEncode; i++)
-<a class="jxr_linenumber" name="L7615" href="#L7615">7615</a> 			needsEncode |= (! URL_UNENCODED_LAX_CHARS.contains(s.charAt(i)));
-<a class="jxr_linenumber" name="L7616" href="#L7616">7616</a> 		<strong class="jxr_keyword">if</strong> (needsEncode) {
-<a class="jxr_linenumber" name="L7617" href="#L7617">7617</a> 			<strong class="jxr_keyword">var</strong> sb = <strong class="jxr_keyword">new</strong> StringBuilder(s.length() * 2);
-<a class="jxr_linenumber" name="L7618" href="#L7618">7618</a> 			<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; s.length(); i++) {
-<a class="jxr_linenumber" name="L7619" href="#L7619">7619</a> 				<strong class="jxr_keyword">var</strong> c = s.charAt(i);
-<a class="jxr_linenumber" name="L7620" href="#L7620">7620</a> 				<strong class="jxr_keyword">if</strong> (URL_UNENCODED_LAX_CHARS.contains(c))
-<a class="jxr_linenumber" name="L7621" href="#L7621">7621</a> 					sb.append(c);
-<a class="jxr_linenumber" name="L7622" href="#L7622">7622</a> 				<strong class="jxr_keyword">else</strong> <strong class="jxr_keyword">if</strong> (c == ' ')
-<a class="jxr_linenumber" name="L7623" href="#L7623">7623</a> 					sb.append(<span class="jxr_string">"+"</span>);
-<a class="jxr_linenumber" name="L7624" href="#L7624">7624</a> 				<strong class="jxr_keyword">else</strong> <strong class="jxr_keyword">if</strong> (c &lt;= 127)
-<a class="jxr_linenumber" name="L7625" href="#L7625">7625</a> 					sb.append('%').append(toHex2(c));
-<a class="jxr_linenumber" name="L7626" href="#L7626">7626</a> 				<strong class="jxr_keyword">else</strong>
-<a class="jxr_linenumber" name="L7627" href="#L7627">7627</a> 					safe(()-&gt;sb.append(URLEncoder.encode(<span class="jxr_string">""</span> + c, <span class="jxr_string">"UTF-8"</span>)));  <em class="jxr_comment">// Yuck.</em>
-<a class="jxr_linenumber" name="L7628" href="#L7628">7628</a> 			}
-<a class="jxr_linenumber" name="L7629" href="#L7629">7629</a> 			s = sb.toString();
-<a class="jxr_linenumber" name="L7630" href="#L7630">7630</a> 		}
-<a class="jxr_linenumber" name="L7631" href="#L7631">7631</a> 		<strong class="jxr_keyword">return</strong> s;
-<a class="jxr_linenumber" name="L7632" href="#L7632">7632</a> 	}
-<a class="jxr_linenumber" name="L7633" href="#L7633">7633</a> 
-<a class="jxr_linenumber" name="L7634" href="#L7634">7634</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7635" href="#L7635">7635</a> <em class="jxr_javadoccomment">	 * Similar to {@link URLEncoder#encode(String, String)} but doesn't encode &lt;js&gt;"/"&lt;/js&gt; characters.</em>
-<a class="jxr_linenumber" name="L7636" href="#L7636">7636</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7637" href="#L7637">7637</a> <em class="jxr_javadoccomment">	 * @param o The object to encode.</em>
-<a class="jxr_linenumber" name="L7638" href="#L7638">7638</a> <em class="jxr_javadoccomment">	 * @return The URL encoded string, or &lt;jk&gt;null&lt;/jk&gt; if the object was null.</em>
-<a class="jxr_linenumber" name="L7639" href="#L7639">7639</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7640" href="#L7640">7640</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String urlEncodePath(Object o) {
+<a class="jxr_linenumber" name="L7601" href="#L7601">7601</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7602" href="#L7602">7602</a> <em class="jxr_javadoccomment">	 * Same as {@link #urlEncode(String)} except only escapes characters that absolutely need to be escaped.</em>
+<a class="jxr_linenumber" name="L7603" href="#L7603">7603</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7604" href="#L7604">7604</a> <em class="jxr_javadoccomment">	 * @param s The string to escape.</em>
+<a class="jxr_linenumber" name="L7605" href="#L7605">7605</a> <em class="jxr_javadoccomment">	 * @return The encoded string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
+<a class="jxr_linenumber" name="L7606" href="#L7606">7606</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7607" href="#L7607">7607</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String urlEncodeLax(String s) {
+<a class="jxr_linenumber" name="L7608" href="#L7608">7608</a> 		<strong class="jxr_keyword">if</strong> (s == <strong class="jxr_keyword">null</strong>)
+<a class="jxr_linenumber" name="L7609" href="#L7609">7609</a> 			<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">null</strong>;
+<a class="jxr_linenumber" name="L7610" href="#L7610">7610</a> 		<strong class="jxr_keyword">var</strong> needsEncode = false;
+<a class="jxr_linenumber" name="L7611" href="#L7611">7611</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; s.length() &amp;&amp; ! needsEncode; i++)
+<a class="jxr_linenumber" name="L7612" href="#L7612">7612</a> 			needsEncode |= (! URL_UNENCODED_LAX_CHARS.contains(s.charAt(i)));
+<a class="jxr_linenumber" name="L7613" href="#L7613">7613</a> 		<strong class="jxr_keyword">if</strong> (needsEncode) {
+<a class="jxr_linenumber" name="L7614" href="#L7614">7614</a> 			<strong class="jxr_keyword">var</strong> sb = <strong class="jxr_keyword">new</strong> StringBuilder(s.length() * 2);
+<a class="jxr_linenumber" name="L7615" href="#L7615">7615</a> 			<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; s.length(); i++) {
+<a class="jxr_linenumber" name="L7616" href="#L7616">7616</a> 				<strong class="jxr_keyword">var</strong> c = s.charAt(i);
+<a class="jxr_linenumber" name="L7617" href="#L7617">7617</a> 				<strong class="jxr_keyword">if</strong> (URL_UNENCODED_LAX_CHARS.contains(c))
+<a class="jxr_linenumber" name="L7618" href="#L7618">7618</a> 					sb.append(c);
+<a class="jxr_linenumber" name="L7619" href="#L7619">7619</a> 				<strong class="jxr_keyword">else</strong> <strong class="jxr_keyword">if</strong> (c == ' ')
+<a class="jxr_linenumber" name="L7620" href="#L7620">7620</a> 					sb.append(<span class="jxr_string">"+"</span>);
+<a class="jxr_linenumber" name="L7621" href="#L7621">7621</a> 				<strong class="jxr_keyword">else</strong> <strong class="jxr_keyword">if</strong> (c &lt;= 127)
+<a class="jxr_linenumber" name="L7622" href="#L7622">7622</a> 					sb.append('%').append(toHex2(c));
+<a class="jxr_linenumber" name="L7623" href="#L7623">7623</a> 				<strong class="jxr_keyword">else</strong>
+<a class="jxr_linenumber" name="L7624" href="#L7624">7624</a> 					safe(()-&gt;sb.append(URLEncoder.encode(<span class="jxr_string">""</span> + c, <span class="jxr_string">"UTF-8"</span>)));  <em class="jxr_comment">// Yuck.</em>
+<a class="jxr_linenumber" name="L7625" href="#L7625">7625</a> 			}
+<a class="jxr_linenumber" name="L7626" href="#L7626">7626</a> 			s = sb.toString();
+<a class="jxr_linenumber" name="L7627" href="#L7627">7627</a> 		}
+<a class="jxr_linenumber" name="L7628" href="#L7628">7628</a> 		<strong class="jxr_keyword">return</strong> s;
+<a class="jxr_linenumber" name="L7629" href="#L7629">7629</a> 	}
+<a class="jxr_linenumber" name="L7630" href="#L7630">7630</a> 
+<a class="jxr_linenumber" name="L7631" href="#L7631">7631</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7632" href="#L7632">7632</a> <em class="jxr_javadoccomment">	 * Similar to {@link URLEncoder#encode(String, String)} but doesn't encode &lt;js&gt;"/"&lt;/js&gt; characters.</em>
+<a class="jxr_linenumber" name="L7633" href="#L7633">7633</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7634" href="#L7634">7634</a> <em class="jxr_javadoccomment">	 * @param o The object to encode.</em>
+<a class="jxr_linenumber" name="L7635" href="#L7635">7635</a> <em class="jxr_javadoccomment">	 * @return The URL encoded string, or &lt;jk&gt;null&lt;/jk&gt; if the object was null.</em>
+<a class="jxr_linenumber" name="L7636" href="#L7636">7636</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7637" href="#L7637">7637</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String urlEncodePath(Object o) {
+<a class="jxr_linenumber" name="L7638" href="#L7638">7638</a> 
+<a class="jxr_linenumber" name="L7639" href="#L7639">7639</a> 		<strong class="jxr_keyword">if</strong> (o == <strong class="jxr_keyword">null</strong>)
+<a class="jxr_linenumber" name="L7640" href="#L7640">7640</a> 			<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">null</strong>;
 <a class="jxr_linenumber" name="L7641" href="#L7641">7641</a> 
-<a class="jxr_linenumber" name="L7642" href="#L7642">7642</a> 		<strong class="jxr_keyword">if</strong> (o == <strong class="jxr_keyword">null</strong>)
-<a class="jxr_linenumber" name="L7643" href="#L7643">7643</a> 			<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">null</strong>;
-<a class="jxr_linenumber" name="L7644" href="#L7644">7644</a> 
-<a class="jxr_linenumber" name="L7645" href="#L7645">7645</a> 		<strong class="jxr_keyword">var</strong> s = s(o);
-<a class="jxr_linenumber" name="L7646" href="#L7646">7646</a> 
-<a class="jxr_linenumber" name="L7647" href="#L7647">7647</a> 		<strong class="jxr_keyword">var</strong> needsEncode = false;
-<a class="jxr_linenumber" name="L7648" href="#L7648">7648</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; s.length() &amp;&amp; ! needsEncode; i++)
-<a class="jxr_linenumber" name="L7649" href="#L7649">7649</a> 			needsEncode = URL_ENCODE_PATHINFO_VALIDCHARS.contains(s.charAt(i));
-<a class="jxr_linenumber" name="L7650" href="#L7650">7650</a> 		<strong class="jxr_keyword">if</strong> (! needsEncode)
-<a class="jxr_linenumber" name="L7651" href="#L7651">7651</a> 			<strong class="jxr_keyword">return</strong> s;
-<a class="jxr_linenumber" name="L7652" href="#L7652">7652</a> 
-<a class="jxr_linenumber" name="L7653" href="#L7653">7653</a> 		<strong class="jxr_keyword">var</strong> sb = <strong class="jxr_keyword">new</strong> StringBuilder();
-<a class="jxr_linenumber" name="L7654" href="#L7654">7654</a> 		<strong class="jxr_keyword">var</strong> caw = <strong class="jxr_keyword">new</strong> CharArrayWriter();
-<a class="jxr_linenumber" name="L7655" href="#L7655">7655</a> 		<strong class="jxr_keyword">var</strong> caseDiff = ('a' - 'A');
-<a class="jxr_linenumber" name="L7656" href="#L7656">7656</a> 
-<a class="jxr_linenumber" name="L7657" href="#L7657">7657</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; s.length();) {
-<a class="jxr_linenumber" name="L7658" href="#L7658">7658</a> 			<strong class="jxr_keyword">var</strong> c = s.charAt(i);
-<a class="jxr_linenumber" name="L7659" href="#L7659">7659</a> 			<strong class="jxr_keyword">if</strong> (URL_ENCODE_PATHINFO_VALIDCHARS.contains(c)) {
-<a class="jxr_linenumber" name="L7660" href="#L7660">7660</a> 				sb.append(c);
-<a class="jxr_linenumber" name="L7661" href="#L7661">7661</a> 				i++;  <em class="jxr_comment">// NOSONAR - Intentional.</em>
-<a class="jxr_linenumber" name="L7662" href="#L7662">7662</a> 			} <strong class="jxr_keyword">else</strong> {
-<a class="jxr_linenumber" name="L7663" href="#L7663">7663</a> 				<strong class="jxr_keyword">if</strong> (c == ' ') {
-<a class="jxr_linenumber" name="L7664" href="#L7664">7664</a> 					sb.append('+');
-<a class="jxr_linenumber" name="L7665" href="#L7665">7665</a> 					i++;  <em class="jxr_comment">// NOSONAR - Intentional.</em>
-<a class="jxr_linenumber" name="L7666" href="#L7666">7666</a> 				} <strong class="jxr_keyword">else</strong> {
-<a class="jxr_linenumber" name="L7667" href="#L7667">7667</a> 					<strong class="jxr_keyword">do</strong> {
-<a class="jxr_linenumber" name="L7668" href="#L7668">7668</a> 						caw.write(c);
-<a class="jxr_linenumber" name="L7669" href="#L7669">7669</a> 						<strong class="jxr_keyword">if</strong> (c &gt;= 0xD800 &amp;&amp; c &lt;= 0xDBFF) {
-<a class="jxr_linenumber" name="L7670" href="#L7670">7670</a> 							<strong class="jxr_keyword">if</strong> ((i + 1) &lt; s.length()) {  <em class="jxr_comment">// NOSONAR - Intentional.</em>
-<a class="jxr_linenumber" name="L7671" href="#L7671">7671</a> 								<strong class="jxr_keyword">int</strong> d = s.charAt(i + 1);
-<a class="jxr_linenumber" name="L7672" href="#L7672">7672</a> 								<strong class="jxr_keyword">if</strong> (d &gt;= 0xDC00 &amp;&amp; d &lt;= 0xDFFF) {
-<a class="jxr_linenumber" name="L7673" href="#L7673">7673</a> 									caw.write(d);
-<a class="jxr_linenumber" name="L7674" href="#L7674">7674</a> 									i++;  <em class="jxr_comment">// NOSONAR - Intentional.</em>
-<a class="jxr_linenumber" name="L7675" href="#L7675">7675</a> 								}
-<a class="jxr_linenumber" name="L7676" href="#L7676">7676</a> 							}
-<a class="jxr_linenumber" name="L7677" href="#L7677">7677</a> 						}
-<a class="jxr_linenumber" name="L7678" href="#L7678">7678</a> 						i++;  <em class="jxr_comment">// NOSONAR - Intentional.</em>
-<a class="jxr_linenumber" name="L7679" href="#L7679">7679</a> 					} <strong class="jxr_keyword">while</strong> (i &lt; s.length() &amp;&amp; ! URL_ENCODE_PATHINFO_VALIDCHARS.contains((c = s.charAt(i))));   <em class="jxr_comment">// NOSONAR - Intentional.</em>
-<a class="jxr_linenumber" name="L7680" href="#L7680">7680</a> 
-<a class="jxr_linenumber" name="L7681" href="#L7681">7681</a> 					caw.flush();
-<a class="jxr_linenumber" name="L7682" href="#L7682">7682</a> 					<strong class="jxr_keyword">var</strong> s2 = <strong class="jxr_keyword">new</strong> String(caw.toCharArray());
-<a class="jxr_linenumber" name="L7683" href="#L7683">7683</a> 					<strong class="jxr_keyword">var</strong> ba = s2.getBytes(UTF8);
-<a class="jxr_linenumber" name="L7684" href="#L7684">7684</a> 					<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> element : ba) {
-<a class="jxr_linenumber" name="L7685" href="#L7685">7685</a> 						sb.append('%');
-<a class="jxr_linenumber" name="L7686" href="#L7686">7686</a> 						<strong class="jxr_keyword">var</strong> ch = forDigit((element &gt;&gt; 4) &amp; 0xF, 16);
-<a class="jxr_linenumber" name="L7687" href="#L7687">7687</a> 						<strong class="jxr_keyword">if</strong> (isLetter(ch)) {
-<a class="jxr_linenumber" name="L7688" href="#L7688">7688</a> 							ch -= caseDiff;
-<a class="jxr_linenumber" name="L7689" href="#L7689">7689</a> 						}
-<a class="jxr_linenumber" name="L7690" href="#L7690">7690</a> 						sb.append(ch);
-<a class="jxr_linenumber" name="L7691" href="#L7691">7691</a> 						ch = forDigit(element &amp; 0xF, 16);
-<a class="jxr_linenumber" name="L7692" href="#L7692">7692</a> 						<strong class="jxr_keyword">if</strong> (isLetter(ch)) {
-<a class="jxr_linenumber" name="L7693" href="#L7693">7693</a> 							ch -= caseDiff;
-<a class="jxr_linenumber" name="L7694" href="#L7694">7694</a> 						}
-<a class="jxr_linenumber" name="L7695" href="#L7695">7695</a> 						sb.append(ch);
-<a class="jxr_linenumber" name="L7696" href="#L7696">7696</a> 					}
-<a class="jxr_linenumber" name="L7697" href="#L7697">7697</a> 					caw.reset();
-<a class="jxr_linenumber" name="L7698" href="#L7698">7698</a> 				}
-<a class="jxr_linenumber" name="L7699" href="#L7699">7699</a> 			}
-<a class="jxr_linenumber" name="L7700" href="#L7700">7700</a> 		}
-<a class="jxr_linenumber" name="L7701" href="#L7701">7701</a> 		<strong class="jxr_keyword">return</strong> sb.toString();
-<a class="jxr_linenumber" name="L7702" href="#L7702">7702</a> 	}
-<a class="jxr_linenumber" name="L7703" href="#L7703">7703</a> 
-<a class="jxr_linenumber" name="L7704" href="#L7704">7704</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7705" href="#L7705">7705</a> <em class="jxr_javadoccomment">	 * Counts the number of words in a string.</em>
-<a class="jxr_linenumber" name="L7706" href="#L7706">7706</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7707" href="#L7707">7707</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
-<a class="jxr_linenumber" name="L7708" href="#L7708">7708</a> <em class="jxr_javadoccomment">	 * A word is defined as a sequence of one or more word characters (letters, digits, underscores)</em>
-<a class="jxr_linenumber" name="L7709" href="#L7709">7709</a> <em class="jxr_javadoccomment">	 * separated by non-word characters.</em>
-<a class="jxr_linenumber" name="L7710" href="#L7710">7710</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7711" href="#L7711">7711</a> <em class="jxr_javadoccomment">	 * &lt;h5 class='section'&gt;Example:&lt;/h5&gt;</em>
-<a class="jxr_linenumber" name="L7712" href="#L7712">7712</a> <em class="jxr_javadoccomment">	 * &lt;p class='bjava'&gt;</em>
-<a class="jxr_linenumber" name="L7713" href="#L7713">7713</a> <em class="jxr_javadoccomment">	 * 	wordCount(&lt;js&gt;"Hello world"&lt;/js&gt;);              &lt;jc&gt;// 2&lt;/jc&gt;</em>
-<a class="jxr_linenumber" name="L7714" href="#L7714">7714</a> <em class="jxr_javadoccomment">	 * 	wordCount(&lt;js&gt;"The quick brown fox"&lt;/js&gt;);      &lt;jc&gt;// 4&lt;/jc&gt;</em>
-<a class="jxr_linenumber" name="L7715" href="#L7715">7715</a> <em class="jxr_javadoccomment">	 * 	wordCount(&lt;js&gt;"Hello, world! How are you?"&lt;/js&gt;); &lt;jc&gt;// 5&lt;/jc&gt;</em>
-<a class="jxr_linenumber" name="L7716" href="#L7716">7716</a> <em class="jxr_javadoccomment">	 * &lt;/p&gt;</em>
-<a class="jxr_linenumber" name="L7717" href="#L7717">7717</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7718" href="#L7718">7718</a> <em class="jxr_javadoccomment">	 * @param str The string to count words in. Can be &lt;jk&gt;null&lt;/jk&gt;.</em>
-<a class="jxr_linenumber" name="L7719" href="#L7719">7719</a> <em class="jxr_javadoccomment">	 * @return The number of words, or &lt;c&gt;0&lt;/c&gt; if the string is &lt;jk&gt;null&lt;/jk&gt; or empty.</em>
-<a class="jxr_linenumber" name="L7720" href="#L7720">7720</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7721" href="#L7721">7721</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">int</strong> wordCount(String str) {
-<a class="jxr_linenumber" name="L7722" href="#L7722">7722</a> 		<strong class="jxr_keyword">if</strong> (isEmpty(str))
-<a class="jxr_linenumber" name="L7723" href="#L7723">7723</a> 			<strong class="jxr_keyword">return</strong> 0;
+<a class="jxr_linenumber" name="L7642" href="#L7642">7642</a> 		<strong class="jxr_keyword">var</strong> s = s(o);
+<a class="jxr_linenumber" name="L7643" href="#L7643">7643</a> 
+<a class="jxr_linenumber" name="L7644" href="#L7644">7644</a> 		<strong class="jxr_keyword">var</strong> needsEncode = false;
+<a class="jxr_linenumber" name="L7645" href="#L7645">7645</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; s.length() &amp;&amp; ! needsEncode; i++)
+<a class="jxr_linenumber" name="L7646" href="#L7646">7646</a> 			needsEncode = URL_ENCODE_PATHINFO_VALIDCHARS.contains(s.charAt(i));
+<a class="jxr_linenumber" name="L7647" href="#L7647">7647</a> 		<strong class="jxr_keyword">if</strong> (! needsEncode)
+<a class="jxr_linenumber" name="L7648" href="#L7648">7648</a> 			<strong class="jxr_keyword">return</strong> s;
+<a class="jxr_linenumber" name="L7649" href="#L7649">7649</a> 
+<a class="jxr_linenumber" name="L7650" href="#L7650">7650</a> 		<strong class="jxr_keyword">var</strong> sb = <strong class="jxr_keyword">new</strong> StringBuilder();
+<a class="jxr_linenumber" name="L7651" href="#L7651">7651</a> 		<strong class="jxr_keyword">var</strong> caw = <strong class="jxr_keyword">new</strong> CharArrayWriter();
+<a class="jxr_linenumber" name="L7652" href="#L7652">7652</a> 		<strong class="jxr_keyword">var</strong> caseDiff = ('a' - 'A');
+<a class="jxr_linenumber" name="L7653" href="#L7653">7653</a> 
+<a class="jxr_linenumber" name="L7654" href="#L7654">7654</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; s.length();) {
+<a class="jxr_linenumber" name="L7655" href="#L7655">7655</a> 			<strong class="jxr_keyword">var</strong> c = s.charAt(i);
+<a class="jxr_linenumber" name="L7656" href="#L7656">7656</a> 			<strong class="jxr_keyword">if</strong> (URL_ENCODE_PATHINFO_VALIDCHARS.contains(c)) {
+<a class="jxr_linenumber" name="L7657" href="#L7657">7657</a> 				sb.append(c);
+<a class="jxr_linenumber" name="L7658" href="#L7658">7658</a> 				i++;  <em class="jxr_comment">// NOSONAR - Intentional.</em>
+<a class="jxr_linenumber" name="L7659" href="#L7659">7659</a> 			} <strong class="jxr_keyword">else</strong> {
+<a class="jxr_linenumber" name="L7660" href="#L7660">7660</a> 				<strong class="jxr_keyword">if</strong> (c == ' ') {
+<a class="jxr_linenumber" name="L7661" href="#L7661">7661</a> 					sb.append('+');
+<a class="jxr_linenumber" name="L7662" href="#L7662">7662</a> 					i++;  <em class="jxr_comment">// NOSONAR - Intentional.</em>
+<a class="jxr_linenumber" name="L7663" href="#L7663">7663</a> 				} <strong class="jxr_keyword">else</strong> {
+<a class="jxr_linenumber" name="L7664" href="#L7664">7664</a> 					<strong class="jxr_keyword">do</strong> {
+<a class="jxr_linenumber" name="L7665" href="#L7665">7665</a> 						caw.write(c);
+<a class="jxr_linenumber" name="L7666" href="#L7666">7666</a> 						<strong class="jxr_keyword">if</strong> (c &gt;= 0xD800 &amp;&amp; c &lt;= 0xDBFF) {
+<a class="jxr_linenumber" name="L7667" href="#L7667">7667</a> 							<strong class="jxr_keyword">if</strong> ((i + 1) &lt; s.length()) {  <em class="jxr_comment">// NOSONAR - Intentional.</em>
+<a class="jxr_linenumber" name="L7668" href="#L7668">7668</a> 								<strong class="jxr_keyword">int</strong> d = s.charAt(i + 1);
+<a class="jxr_linenumber" name="L7669" href="#L7669">7669</a> 								<strong class="jxr_keyword">if</strong> (d &gt;= 0xDC00 &amp;&amp; d &lt;= 0xDFFF) {
+<a class="jxr_linenumber" name="L7670" href="#L7670">7670</a> 									caw.write(d);
+<a class="jxr_linenumber" name="L7671" href="#L7671">7671</a> 									i++;  <em class="jxr_comment">// NOSONAR - Intentional.</em>
+<a class="jxr_linenumber" name="L7672" href="#L7672">7672</a> 								}
+<a class="jxr_linenumber" name="L7673" href="#L7673">7673</a> 							}
+<a class="jxr_linenumber" name="L7674" href="#L7674">7674</a> 						}
+<a class="jxr_linenumber" name="L7675" href="#L7675">7675</a> 						i++;  <em class="jxr_comment">// NOSONAR - Intentional.</em>
+<a class="jxr_linenumber" name="L7676" href="#L7676">7676</a> 					} <strong class="jxr_keyword">while</strong> (i &lt; s.length() &amp;&amp; ! URL_ENCODE_PATHINFO_VALIDCHARS.contains((c = s.charAt(i))));   <em class="jxr_comment">// NOSONAR - Intentional.</em>
+<a class="jxr_linenumber" name="L7677" href="#L7677">7677</a> 
+<a class="jxr_linenumber" name="L7678" href="#L7678">7678</a> 					caw.flush();
+<a class="jxr_linenumber" name="L7679" href="#L7679">7679</a> 					<strong class="jxr_keyword">var</strong> s2 = <strong class="jxr_keyword">new</strong> String(caw.toCharArray());
+<a class="jxr_linenumber" name="L7680" href="#L7680">7680</a> 					<strong class="jxr_keyword">var</strong> ba = s2.getBytes(UTF8);
+<a class="jxr_linenumber" name="L7681" href="#L7681">7681</a> 					<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> element : ba) {
+<a class="jxr_linenumber" name="L7682" href="#L7682">7682</a> 						sb.append('%');
+<a class="jxr_linenumber" name="L7683" href="#L7683">7683</a> 						<strong class="jxr_keyword">var</strong> ch = forDigit((element &gt;&gt; 4) &amp; 0xF, 16);
+<a class="jxr_linenumber" name="L7684" href="#L7684">7684</a> 						<strong class="jxr_keyword">if</strong> (isLetter(ch)) {
+<a class="jxr_linenumber" name="L7685" href="#L7685">7685</a> 							ch -= caseDiff;
+<a class="jxr_linenumber" name="L7686" href="#L7686">7686</a> 						}
+<a class="jxr_linenumber" name="L7687" href="#L7687">7687</a> 						sb.append(ch);
+<a class="jxr_linenumber" name="L7688" href="#L7688">7688</a> 						ch = forDigit(element &amp; 0xF, 16);
+<a class="jxr_linenumber" name="L7689" href="#L7689">7689</a> 						<strong class="jxr_keyword">if</strong> (isLetter(ch)) {
+<a class="jxr_linenumber" name="L7690" href="#L7690">7690</a> 							ch -= caseDiff;
+<a class="jxr_linenumber" name="L7691" href="#L7691">7691</a> 						}
+<a class="jxr_linenumber" name="L7692" href="#L7692">7692</a> 						sb.append(ch);
+<a class="jxr_linenumber" name="L7693" href="#L7693">7693</a> 					}
+<a class="jxr_linenumber" name="L7694" href="#L7694">7694</a> 					caw.reset();
+<a class="jxr_linenumber" name="L7695" href="#L7695">7695</a> 				}
+<a class="jxr_linenumber" name="L7696" href="#L7696">7696</a> 			}
+<a class="jxr_linenumber" name="L7697" href="#L7697">7697</a> 		}
+<a class="jxr_linenumber" name="L7698" href="#L7698">7698</a> 		<strong class="jxr_keyword">return</strong> sb.toString();
+<a class="jxr_linenumber" name="L7699" href="#L7699">7699</a> 	}
+<a class="jxr_linenumber" name="L7700" href="#L7700">7700</a> 
+<a class="jxr_linenumber" name="L7701" href="#L7701">7701</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7702" href="#L7702">7702</a> <em class="jxr_javadoccomment">	 * Counts the number of words in a string.</em>
+<a class="jxr_linenumber" name="L7703" href="#L7703">7703</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7704" href="#L7704">7704</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
+<a class="jxr_linenumber" name="L7705" href="#L7705">7705</a> <em class="jxr_javadoccomment">	 * A word is defined as a sequence of one or more word characters (letters, digits, underscores)</em>
+<a class="jxr_linenumber" name="L7706" href="#L7706">7706</a> <em class="jxr_javadoccomment">	 * separated by non-word characters.</em>
+<a class="jxr_linenumber" name="L7707" href="#L7707">7707</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7708" href="#L7708">7708</a> <em class="jxr_javadoccomment">	 * &lt;h5 class='section'&gt;Example:&lt;/h5&gt;</em>
+<a class="jxr_linenumber" name="L7709" href="#L7709">7709</a> <em class="jxr_javadoccomment">	 * &lt;p class='bjava'&gt;</em>
+<a class="jxr_linenumber" name="L7710" href="#L7710">7710</a> <em class="jxr_javadoccomment">	 * 	wordCount(&lt;js&gt;"Hello world"&lt;/js&gt;);              &lt;jc&gt;// 2&lt;/jc&gt;</em>
+<a class="jxr_linenumber" name="L7711" href="#L7711">7711</a> <em class="jxr_javadoccomment">	 * 	wordCount(&lt;js&gt;"The quick brown fox"&lt;/js&gt;);      &lt;jc&gt;// 4&lt;/jc&gt;</em>
+<a class="jxr_linenumber" name="L7712" href="#L7712">7712</a> <em class="jxr_javadoccomment">	 * 	wordCount(&lt;js&gt;"Hello, world! How are you?"&lt;/js&gt;); &lt;jc&gt;// 5&lt;/jc&gt;</em>
+<a class="jxr_linenumber" name="L7713" href="#L7713">7713</a> <em class="jxr_javadoccomment">	 * &lt;/p&gt;</em>
+<a class="jxr_linenumber" name="L7714" href="#L7714">7714</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7715" href="#L7715">7715</a> <em class="jxr_javadoccomment">	 * @param str The string to count words in. Can be &lt;jk&gt;null&lt;/jk&gt;.</em>
+<a class="jxr_linenumber" name="L7716" href="#L7716">7716</a> <em class="jxr_javadoccomment">	 * @return The number of words, or &lt;c&gt;0&lt;/c&gt; if the string is &lt;jk&gt;null&lt;/jk&gt; or empty.</em>
+<a class="jxr_linenumber" name="L7717" href="#L7717">7717</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7718" href="#L7718">7718</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">int</strong> wordCount(String str) {
+<a class="jxr_linenumber" name="L7719" href="#L7719">7719</a> 		<strong class="jxr_keyword">if</strong> (isEmpty(str))
+<a class="jxr_linenumber" name="L7720" href="#L7720">7720</a> 			<strong class="jxr_keyword">return</strong> 0;
+<a class="jxr_linenumber" name="L7721" href="#L7721">7721</a> 
+<a class="jxr_linenumber" name="L7722" href="#L7722">7722</a> 		<strong class="jxr_keyword">var</strong> count = 0;
+<a class="jxr_linenumber" name="L7723" href="#L7723">7723</a> 		<strong class="jxr_keyword">var</strong> inWord = false;
 <a class="jxr_linenumber" name="L7724" href="#L7724">7724</a> 
-<a class="jxr_linenumber" name="L7725" href="#L7725">7725</a> 		<strong class="jxr_keyword">var</strong> count = 0;
-<a class="jxr_linenumber" name="L7726" href="#L7726">7726</a> 		<strong class="jxr_keyword">var</strong> inWord = false;
-<a class="jxr_linenumber" name="L7727" href="#L7727">7727</a> 
-<a class="jxr_linenumber" name="L7728" href="#L7728">7728</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; str.length(); i++) {
-<a class="jxr_linenumber" name="L7729" href="#L7729">7729</a> 			<strong class="jxr_keyword">var</strong> c = str.charAt(i);
-<a class="jxr_linenumber" name="L7730" href="#L7730">7730</a> 			<strong class="jxr_keyword">if</strong> ((LETTER.contains(c) || DIGIT.contains(c)) || c == '_') {
-<a class="jxr_linenumber" name="L7731" href="#L7731">7731</a> 				<strong class="jxr_keyword">if</strong> (! inWord) {
-<a class="jxr_linenumber" name="L7732" href="#L7732">7732</a> 					count++;
-<a class="jxr_linenumber" name="L7733" href="#L7733">7733</a> 					inWord = <strong class="jxr_keyword">true</strong>;
-<a class="jxr_linenumber" name="L7734" href="#L7734">7734</a> 				}
-<a class="jxr_linenumber" name="L7735" href="#L7735">7735</a> 			} <strong class="jxr_keyword">else</strong> {
-<a class="jxr_linenumber" name="L7736" href="#L7736">7736</a> 				inWord = false;
-<a class="jxr_linenumber" name="L7737" href="#L7737">7737</a> 			}
-<a class="jxr_linenumber" name="L7738" href="#L7738">7738</a> 		}
+<a class="jxr_linenumber" name="L7725" href="#L7725">7725</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; str.length(); i++) {
+<a class="jxr_linenumber" name="L7726" href="#L7726">7726</a> 			<strong class="jxr_keyword">var</strong> c = str.charAt(i);
+<a class="jxr_linenumber" name="L7727" href="#L7727">7727</a> 			<strong class="jxr_keyword">if</strong> ((LETTER.contains(c) || DIGIT.contains(c)) || c == '_') {
+<a class="jxr_linenumber" name="L7728" href="#L7728">7728</a> 				<strong class="jxr_keyword">if</strong> (! inWord) {
+<a class="jxr_linenumber" name="L7729" href="#L7729">7729</a> 					count++;
+<a class="jxr_linenumber" name="L7730" href="#L7730">7730</a> 					inWord = <strong class="jxr_keyword">true</strong>;
+<a class="jxr_linenumber" name="L7731" href="#L7731">7731</a> 				}
+<a class="jxr_linenumber" name="L7732" href="#L7732">7732</a> 			} <strong class="jxr_keyword">else</strong> {
+<a class="jxr_linenumber" name="L7733" href="#L7733">7733</a> 				inWord = false;
+<a class="jxr_linenumber" name="L7734" href="#L7734">7734</a> 			}
+<a class="jxr_linenumber" name="L7735" href="#L7735">7735</a> 		}
+<a class="jxr_linenumber" name="L7736" href="#L7736">7736</a> 
+<a class="jxr_linenumber" name="L7737" href="#L7737">7737</a> 		<strong class="jxr_keyword">return</strong> count;
+<a class="jxr_linenumber" name="L7738" href="#L7738">7738</a> 	}
 <a class="jxr_linenumber" name="L7739" href="#L7739">7739</a> 
-<a class="jxr_linenumber" name="L7740" href="#L7740">7740</a> 		<strong class="jxr_keyword">return</strong> count;
-<a class="jxr_linenumber" name="L7741" href="#L7741">7741</a> 	}
-<a class="jxr_linenumber" name="L7742" href="#L7742">7742</a> 
-<a class="jxr_linenumber" name="L7743" href="#L7743">7743</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7744" href="#L7744">7744</a> <em class="jxr_javadoccomment">	 * Wraps text to a specified line length.</em>
-<a class="jxr_linenumber" name="L7745" href="#L7745">7745</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7746" href="#L7746">7746</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
-<a class="jxr_linenumber" name="L7747" href="#L7747">7747</a> <em class="jxr_javadoccomment">	 * Wraps text by breaking at word boundaries (spaces). Words longer than the wrap length</em>
-<a class="jxr_linenumber" name="L7748" href="#L7748">7748</a> <em class="jxr_javadoccomment">	 * will be broken at the wrap length. Existing newlines are preserved.</em>
-<a class="jxr_linenumber" name="L7749" href="#L7749">7749</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7750" href="#L7750">7750</a> <em class="jxr_javadoccomment">	 * &lt;h5 class='section'&gt;Example:&lt;/h5&gt;</em>
-<a class="jxr_linenumber" name="L7751" href="#L7751">7751</a> <em class="jxr_javadoccomment">	 * &lt;p class='bjava'&gt;</em>
-<a class="jxr_linenumber" name="L7752" href="#L7752">7752</a> <em class="jxr_javadoccomment">	 * 	wrap(&lt;js&gt;"hello world test"&lt;/js&gt;, 10);  &lt;jc&gt;// "hello world\ntest"&lt;/jc&gt;</em>
-<a class="jxr_linenumber" name="L7753" href="#L7753">7753</a> <em class="jxr_javadoccomment">	 * 	wrap(&lt;jk&gt;null&lt;/jk&gt;, 10);                &lt;jc&gt;// null&lt;/jc&gt;</em>
-<a class="jxr_linenumber" name="L7754" href="#L7754">7754</a> <em class="jxr_javadoccomment">	 * &lt;/p&gt;</em>
-<a class="jxr_linenumber" name="L7755" href="#L7755">7755</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7756" href="#L7756">7756</a> <em class="jxr_javadoccomment">	 * @param str The string to wrap.</em>
-<a class="jxr_linenumber" name="L7757" href="#L7757">7757</a> <em class="jxr_javadoccomment">	 * @param wrapLength The maximum line length (must be &amp;gt; 0).</em>
-<a class="jxr_linenumber" name="L7758" href="#L7758">7758</a> <em class="jxr_javadoccomment">	 * @return The wrapped string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
-<a class="jxr_linenumber" name="L7759" href="#L7759">7759</a> <em class="jxr_javadoccomment">	 * @throws IllegalArgumentException if wrapLength is &amp;lt;= 0.</em>
-<a class="jxr_linenumber" name="L7760" href="#L7760">7760</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7761" href="#L7761">7761</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String wrap(String str, <strong class="jxr_keyword">int</strong> wrapLength) {
-<a class="jxr_linenumber" name="L7762" href="#L7762">7762</a> 		<strong class="jxr_keyword">return</strong> wrap(str, wrapLength, <span class="jxr_string">"\n"</span>);
-<a class="jxr_linenumber" name="L7763" href="#L7763">7763</a> 	}
-<a class="jxr_linenumber" name="L7764" href="#L7764">7764</a> 
-<a class="jxr_linenumber" name="L7765" href="#L7765">7765</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7766" href="#L7766">7766</a> <em class="jxr_javadoccomment">	 * Wraps text to a specified line length with a custom newline string.</em>
-<a class="jxr_linenumber" name="L7767" href="#L7767">7767</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7768" href="#L7768">7768</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
-<a class="jxr_linenumber" name="L7769" href="#L7769">7769</a> <em class="jxr_javadoccomment">	 * Wraps text by breaking at word boundaries (spaces). Words longer than the wrap length</em>
-<a class="jxr_linenumber" name="L7770" href="#L7770">7770</a> <em class="jxr_javadoccomment">	 * will be broken at the wrap length. Existing newlines are preserved.</em>
-<a class="jxr_linenumber" name="L7771" href="#L7771">7771</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7772" href="#L7772">7772</a> <em class="jxr_javadoccomment">	 * &lt;h5 class='section'&gt;Example:&lt;/h5&gt;</em>
-<a class="jxr_linenumber" name="L7773" href="#L7773">7773</a> <em class="jxr_javadoccomment">	 * &lt;p class='bjava'&gt;</em>
-<a class="jxr_linenumber" name="L7774" href="#L7774">7774</a> <em class="jxr_javadoccomment">	 * 	wrap(&lt;js&gt;"hello world test"&lt;/js&gt;, 10, &lt;js&gt;"&lt;br&gt;"&lt;/js&gt;);  &lt;jc&gt;// "hello world&lt;br&gt;test"&lt;/jc&gt;</em>
-<a class="jxr_linenumber" name="L7775" href="#L7775">7775</a> <em class="jxr_javadoccomment">	 * 	wrap(&lt;jk&gt;null&lt;/jk&gt;, 10, &lt;js&gt;"\n"&lt;/js&gt;);                  &lt;jc&gt;// null&lt;/jc&gt;</em>
-<a class="jxr_linenumber" name="L7776" href="#L7776">7776</a> <em class="jxr_javadoccomment">	 * &lt;/p&gt;</em>
-<a class="jxr_linenumber" name="L7777" href="#L7777">7777</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7778" href="#L7778">7778</a> <em class="jxr_javadoccomment">	 * @param str The string to wrap.</em>
-<a class="jxr_linenumber" name="L7779" href="#L7779">7779</a> <em class="jxr_javadoccomment">	 * @param wrapLength The maximum line length (must be &amp;gt; 0).</em>
-<a class="jxr_linenumber" name="L7780" href="#L7780">7780</a> <em class="jxr_javadoccomment">	 * @param newline The string to use as line separator.</em>
-<a class="jxr_linenumber" name="L7781" href="#L7781">7781</a> <em class="jxr_javadoccomment">	 * @return The wrapped string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
-<a class="jxr_linenumber" name="L7782" href="#L7782">7782</a> <em class="jxr_javadoccomment">	 * @throws IllegalArgumentException if wrapLength is &amp;lt;= 0 or newline is &lt;jk&gt;null&lt;/jk&gt;.</em>
-<a class="jxr_linenumber" name="L7783" href="#L7783">7783</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7784" href="#L7784">7784</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String wrap(String str, <strong class="jxr_keyword">int</strong> wrapLength, String newline) {
-<a class="jxr_linenumber" name="L7785" href="#L7785">7785</a> 		<strong class="jxr_keyword">if</strong> (str == <strong class="jxr_keyword">null</strong>)
-<a class="jxr_linenumber" name="L7786" href="#L7786">7786</a> 			<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">null</strong>;
-<a class="jxr_linenumber" name="L7787" href="#L7787">7787</a> 		<strong class="jxr_keyword">if</strong> (isEmpty(str))
-<a class="jxr_linenumber" name="L7788" href="#L7788">7788</a> 			<strong class="jxr_keyword">return</strong> str;
-<a class="jxr_linenumber" name="L7789" href="#L7789">7789</a> 		<strong class="jxr_keyword">if</strong> (wrapLength &lt;= 0)
-<a class="jxr_linenumber" name="L7790" href="#L7790">7790</a> 			<strong class="jxr_keyword">throw</strong> illegalArg(<span class="jxr_string">"wrapLength must be &gt; 0: {0}"</span>, wrapLength);
-<a class="jxr_linenumber" name="L7791" href="#L7791">7791</a> 		<strong class="jxr_keyword">if</strong> (newline == <strong class="jxr_keyword">null</strong>)
-<a class="jxr_linenumber" name="L7792" href="#L7792">7792</a> 			<strong class="jxr_keyword">throw</strong> illegalArg(<span class="jxr_string">"newline cannot be null"</span>);
+<a class="jxr_linenumber" name="L7740" href="#L7740">7740</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7741" href="#L7741">7741</a> <em class="jxr_javadoccomment">	 * Wraps text to a specified line length.</em>
+<a class="jxr_linenumber" name="L7742" href="#L7742">7742</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7743" href="#L7743">7743</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
+<a class="jxr_linenumber" name="L7744" href="#L7744">7744</a> <em class="jxr_javadoccomment">	 * Wraps text by breaking at word boundaries (spaces). Words longer than the wrap length</em>
+<a class="jxr_linenumber" name="L7745" href="#L7745">7745</a> <em class="jxr_javadoccomment">	 * will be broken at the wrap length. Existing newlines are preserved.</em>
+<a class="jxr_linenumber" name="L7746" href="#L7746">7746</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7747" href="#L7747">7747</a> <em class="jxr_javadoccomment">	 * &lt;h5 class='section'&gt;Example:&lt;/h5&gt;</em>
+<a class="jxr_linenumber" name="L7748" href="#L7748">7748</a> <em class="jxr_javadoccomment">	 * &lt;p class='bjava'&gt;</em>
+<a class="jxr_linenumber" name="L7749" href="#L7749">7749</a> <em class="jxr_javadoccomment">	 * 	wrap(&lt;js&gt;"hello world test"&lt;/js&gt;, 10);  &lt;jc&gt;// "hello world\ntest"&lt;/jc&gt;</em>
+<a class="jxr_linenumber" name="L7750" href="#L7750">7750</a> <em class="jxr_javadoccomment">	 * 	wrap(&lt;jk&gt;null&lt;/jk&gt;, 10);                &lt;jc&gt;// null&lt;/jc&gt;</em>
+<a class="jxr_linenumber" name="L7751" href="#L7751">7751</a> <em class="jxr_javadoccomment">	 * &lt;/p&gt;</em>
+<a class="jxr_linenumber" name="L7752" href="#L7752">7752</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7753" href="#L7753">7753</a> <em class="jxr_javadoccomment">	 * @param str The string to wrap.</em>
+<a class="jxr_linenumber" name="L7754" href="#L7754">7754</a> <em class="jxr_javadoccomment">	 * @param wrapLength The maximum line length (must be &amp;gt; 0).</em>
+<a class="jxr_linenumber" name="L7755" href="#L7755">7755</a> <em class="jxr_javadoccomment">	 * @return The wrapped string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
+<a class="jxr_linenumber" name="L7756" href="#L7756">7756</a> <em class="jxr_javadoccomment">	 * @throws IllegalArgumentException if wrapLength is &amp;lt;= 0.</em>
+<a class="jxr_linenumber" name="L7757" href="#L7757">7757</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7758" href="#L7758">7758</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String wrap(String str, <strong class="jxr_keyword">int</strong> wrapLength) {
+<a class="jxr_linenumber" name="L7759" href="#L7759">7759</a> 		<strong class="jxr_keyword">return</strong> wrap(str, wrapLength, <span class="jxr_string">"\n"</span>);
+<a class="jxr_linenumber" name="L7760" href="#L7760">7760</a> 	}
+<a class="jxr_linenumber" name="L7761" href="#L7761">7761</a> 
+<a class="jxr_linenumber" name="L7762" href="#L7762">7762</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7763" href="#L7763">7763</a> <em class="jxr_javadoccomment">	 * Wraps text to a specified line length with a custom newline string.</em>
+<a class="jxr_linenumber" name="L7764" href="#L7764">7764</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7765" href="#L7765">7765</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
+<a class="jxr_linenumber" name="L7766" href="#L7766">7766</a> <em class="jxr_javadoccomment">	 * Wraps text by breaking at word boundaries (spaces). Words longer than the wrap length</em>
+<a class="jxr_linenumber" name="L7767" href="#L7767">7767</a> <em class="jxr_javadoccomment">	 * will be broken at the wrap length. Existing newlines are preserved.</em>
+<a class="jxr_linenumber" name="L7768" href="#L7768">7768</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7769" href="#L7769">7769</a> <em class="jxr_javadoccomment">	 * &lt;h5 class='section'&gt;Example:&lt;/h5&gt;</em>
+<a class="jxr_linenumber" name="L7770" href="#L7770">7770</a> <em class="jxr_javadoccomment">	 * &lt;p class='bjava'&gt;</em>
+<a class="jxr_linenumber" name="L7771" href="#L7771">7771</a> <em class="jxr_javadoccomment">	 * 	wrap(&lt;js&gt;"hello world test"&lt;/js&gt;, 10, &lt;js&gt;"&lt;br&gt;"&lt;/js&gt;);  &lt;jc&gt;// "hello world&lt;br&gt;test"&lt;/jc&gt;</em>
+<a class="jxr_linenumber" name="L7772" href="#L7772">7772</a> <em class="jxr_javadoccomment">	 * 	wrap(&lt;jk&gt;null&lt;/jk&gt;, 10, &lt;js&gt;"\n"&lt;/js&gt;);                  &lt;jc&gt;// null&lt;/jc&gt;</em>
+<a class="jxr_linenumber" name="L7773" href="#L7773">7773</a> <em class="jxr_javadoccomment">	 * &lt;/p&gt;</em>
+<a class="jxr_linenumber" name="L7774" href="#L7774">7774</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7775" href="#L7775">7775</a> <em class="jxr_javadoccomment">	 * @param str The string to wrap.</em>
+<a class="jxr_linenumber" name="L7776" href="#L7776">7776</a> <em class="jxr_javadoccomment">	 * @param wrapLength The maximum line length (must be &amp;gt; 0).</em>
+<a class="jxr_linenumber" name="L7777" href="#L7777">7777</a> <em class="jxr_javadoccomment">	 * @param newline The string to use as line separator.</em>
+<a class="jxr_linenumber" name="L7778" href="#L7778">7778</a> <em class="jxr_javadoccomment">	 * @return The wrapped string, or &lt;jk&gt;null&lt;/jk&gt; if input is &lt;jk&gt;null&lt;/jk&gt;.</em>
+<a class="jxr_linenumber" name="L7779" href="#L7779">7779</a> <em class="jxr_javadoccomment">	 * @throws IllegalArgumentException if wrapLength is &amp;lt;= 0 or newline is &lt;jk&gt;null&lt;/jk&gt;.</em>
+<a class="jxr_linenumber" name="L7780" href="#L7780">7780</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7781" href="#L7781">7781</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> String wrap(String str, <strong class="jxr_keyword">int</strong> wrapLength, String newline) {
+<a class="jxr_linenumber" name="L7782" href="#L7782">7782</a> 		<strong class="jxr_keyword">if</strong> (str == <strong class="jxr_keyword">null</strong>)
+<a class="jxr_linenumber" name="L7783" href="#L7783">7783</a> 			<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">null</strong>;
+<a class="jxr_linenumber" name="L7784" href="#L7784">7784</a> 		<strong class="jxr_keyword">if</strong> (isEmpty(str))
+<a class="jxr_linenumber" name="L7785" href="#L7785">7785</a> 			<strong class="jxr_keyword">return</strong> str;
+<a class="jxr_linenumber" name="L7786" href="#L7786">7786</a> 		<strong class="jxr_keyword">if</strong> (wrapLength &lt;= 0)
+<a class="jxr_linenumber" name="L7787" href="#L7787">7787</a> 			<strong class="jxr_keyword">throw</strong> illegalArg(<span class="jxr_string">"wrapLength must be &gt; 0: {0}"</span>, wrapLength);
+<a class="jxr_linenumber" name="L7788" href="#L7788">7788</a> 		<strong class="jxr_keyword">if</strong> (newline == <strong class="jxr_keyword">null</strong>)
+<a class="jxr_linenumber" name="L7789" href="#L7789">7789</a> 			<strong class="jxr_keyword">throw</strong> illegalArg(<span class="jxr_string">"newline cannot be null"</span>);
+<a class="jxr_linenumber" name="L7790" href="#L7790">7790</a> 
+<a class="jxr_linenumber" name="L7791" href="#L7791">7791</a> 		<strong class="jxr_keyword">var</strong> result = <strong class="jxr_keyword">new</strong> StringBuilder();
+<a class="jxr_linenumber" name="L7792" href="#L7792">7792</a> 		<strong class="jxr_keyword">var</strong> lines = str.split(<span class="jxr_string">"\r?\n"</span>, -1);  <em class="jxr_comment">// Preserve empty lines</em>
 <a class="jxr_linenumber" name="L7793" href="#L7793">7793</a> 
-<a class="jxr_linenumber" name="L7794" href="#L7794">7794</a> 		<strong class="jxr_keyword">var</strong> result = <strong class="jxr_keyword">new</strong> StringBuilder();
-<a class="jxr_linenumber" name="L7795" href="#L7795">7795</a> 		<strong class="jxr_keyword">var</strong> lines = str.split(<span class="jxr_string">"\r?\n"</span>, -1);  <em class="jxr_comment">// Preserve empty lines</em>
-<a class="jxr_linenumber" name="L7796" href="#L7796">7796</a> 
-<a class="jxr_linenumber" name="L7797" href="#L7797">7797</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> lineIdx = 0; lineIdx &lt; lines.length; lineIdx++) {
-<a class="jxr_linenumber" name="L7798" href="#L7798">7798</a> 			<strong class="jxr_keyword">var</strong> line = lines[lineIdx];
-<a class="jxr_linenumber" name="L7799" href="#L7799">7799</a> 			<strong class="jxr_keyword">if</strong> (line.isEmpty()) {
-<a class="jxr_linenumber" name="L7800" href="#L7800">7800</a> 				<strong class="jxr_keyword">if</strong> (lineIdx &lt; lines.length - 1)
-<a class="jxr_linenumber" name="L7801" href="#L7801">7801</a> 					result.append(newline);
-<a class="jxr_linenumber" name="L7802" href="#L7802">7802</a> 				<strong class="jxr_keyword">continue</strong>;
-<a class="jxr_linenumber" name="L7803" href="#L7803">7803</a> 			}
-<a class="jxr_linenumber" name="L7804" href="#L7804">7804</a> 
-<a class="jxr_linenumber" name="L7805" href="#L7805">7805</a> 			<em class="jxr_comment">// Split into words first, then combine words that fit</em>
-<a class="jxr_linenumber" name="L7806" href="#L7806">7806</a> 			<strong class="jxr_keyword">var</strong> words = line.split(<span class="jxr_string">" +"</span>);  <em class="jxr_comment">// Split on one or more spaces</em>
-<a class="jxr_linenumber" name="L7807" href="#L7807">7807</a> 			<strong class="jxr_keyword">var</strong> currentLine = <strong class="jxr_keyword">new</strong> StringBuilder();
-<a class="jxr_linenumber" name="L7808" href="#L7808">7808</a> 
-<a class="jxr_linenumber" name="L7809" href="#L7809">7809</a> 			<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> word : words) {
-<a class="jxr_linenumber" name="L7810" href="#L7810">7810</a> 				<strong class="jxr_keyword">if</strong> (word.isEmpty())
-<a class="jxr_linenumber" name="L7811" href="#L7811">7811</a> 					<strong class="jxr_keyword">continue</strong>;
+<a class="jxr_linenumber" name="L7794" href="#L7794">7794</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> lineIdx = 0; lineIdx &lt; lines.length; lineIdx++) {
+<a class="jxr_linenumber" name="L7795" href="#L7795">7795</a> 			<strong class="jxr_keyword">var</strong> line = lines[lineIdx];
+<a class="jxr_linenumber" name="L7796" href="#L7796">7796</a> 			<strong class="jxr_keyword">if</strong> (line.isEmpty()) {
+<a class="jxr_linenumber" name="L7797" href="#L7797">7797</a> 				<strong class="jxr_keyword">if</strong> (lineIdx &lt; lines.length - 1)
+<a class="jxr_linenumber" name="L7798" href="#L7798">7798</a> 					result.append(newline);
+<a class="jxr_linenumber" name="L7799" href="#L7799">7799</a> 				<strong class="jxr_keyword">continue</strong>;
+<a class="jxr_linenumber" name="L7800" href="#L7800">7800</a> 			}
+<a class="jxr_linenumber" name="L7801" href="#L7801">7801</a> 
+<a class="jxr_linenumber" name="L7802" href="#L7802">7802</a> 			<em class="jxr_comment">// Split into words first, then combine words that fit</em>
+<a class="jxr_linenumber" name="L7803" href="#L7803">7803</a> 			<strong class="jxr_keyword">var</strong> words = line.split(<span class="jxr_string">" +"</span>);  <em class="jxr_comment">// Split on one or more spaces</em>
+<a class="jxr_linenumber" name="L7804" href="#L7804">7804</a> 			<strong class="jxr_keyword">var</strong> currentLine = <strong class="jxr_keyword">new</strong> StringBuilder();
+<a class="jxr_linenumber" name="L7805" href="#L7805">7805</a> 
+<a class="jxr_linenumber" name="L7806" href="#L7806">7806</a> 			<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> word : words) {
+<a class="jxr_linenumber" name="L7807" href="#L7807">7807</a> 				<strong class="jxr_keyword">if</strong> (word.isEmpty())
+<a class="jxr_linenumber" name="L7808" href="#L7808">7808</a> 					<strong class="jxr_keyword">continue</strong>;
+<a class="jxr_linenumber" name="L7809" href="#L7809">7809</a> 
+<a class="jxr_linenumber" name="L7810" href="#L7810">7810</a> 				<strong class="jxr_keyword">var</strong> wordLength = word.length();
+<a class="jxr_linenumber" name="L7811" href="#L7811">7811</a> 				<strong class="jxr_keyword">var</strong> currentLength = currentLine.length();
 <a class="jxr_linenumber" name="L7812" href="#L7812">7812</a> 
-<a class="jxr_linenumber" name="L7813" href="#L7813">7813</a> 				<strong class="jxr_keyword">var</strong> wordLength = word.length();
-<a class="jxr_linenumber" name="L7814" href="#L7814">7814</a> 				<strong class="jxr_keyword">var</strong> currentLength = currentLine.length();
-<a class="jxr_linenumber" name="L7815" href="#L7815">7815</a> 
-<a class="jxr_linenumber" name="L7816" href="#L7816">7816</a> 				<strong class="jxr_keyword">if</strong> (currentLength == 0) {
-<a class="jxr_linenumber" name="L7817" href="#L7817">7817</a> 					<em class="jxr_comment">// First word on line</em>
-<a class="jxr_linenumber" name="L7818" href="#L7818">7818</a> 					<em class="jxr_comment">// Only break single words if there are multiple words in the input</em>
-<a class="jxr_linenumber" name="L7819" href="#L7819">7819</a> 					<em class="jxr_comment">// (single long words should not be broken for readability)</em>
-<a class="jxr_linenumber" name="L7820" href="#L7820">7820</a> 					<strong class="jxr_keyword">if</strong> (wordLength &gt; wrapLength &amp;&amp; words.length &gt; 1) {
-<a class="jxr_linenumber" name="L7821" href="#L7821">7821</a> 						<em class="jxr_comment">// Word is too long and there are other words, break it</em>
-<a class="jxr_linenumber" name="L7822" href="#L7822">7822</a> 						<strong class="jxr_keyword">if</strong> (result.length() &gt; 0)
-<a class="jxr_linenumber" name="L7823" href="#L7823">7823</a> 							result.append(newline);
-<a class="jxr_linenumber" name="L7824" href="#L7824">7824</a> 						<strong class="jxr_keyword">var</strong> wordPos = 0;
-<a class="jxr_linenumber" name="L7825" href="#L7825">7825</a> 						<strong class="jxr_keyword">while</strong> (wordPos &lt; wordLength) {
-<a class="jxr_linenumber" name="L7826" href="#L7826">7826</a> 							<strong class="jxr_keyword">if</strong> (wordPos &gt; 0)
-<a class="jxr_linenumber" name="L7827" href="#L7827">7827</a> 								result.append(newline);
-<a class="jxr_linenumber" name="L7828" href="#L7828">7828</a> 							<strong class="jxr_keyword">var</strong> remaining = wordLength - wordPos;
-<a class="jxr_linenumber" name="L7829" href="#L7829">7829</a> 							<strong class="jxr_keyword">if</strong> (remaining &lt;= wrapLength) {
-<a class="jxr_linenumber" name="L7830" href="#L7830">7830</a> 								result.append(word.substring(wordPos));
-<a class="jxr_linenumber" name="L7831" href="#L7831">7831</a> 								<strong class="jxr_keyword">break</strong>;
-<a class="jxr_linenumber" name="L7832" href="#L7832">7832</a> 							}
-<a class="jxr_linenumber" name="L7833" href="#L7833">7833</a> 							result.append(word.substring(wordPos, wordPos + wrapLength));
-<a class="jxr_linenumber" name="L7834" href="#L7834">7834</a> 							wordPos += wrapLength;
-<a class="jxr_linenumber" name="L7835" href="#L7835">7835</a> 						}
-<a class="jxr_linenumber" name="L7836" href="#L7836">7836</a> 					} <strong class="jxr_keyword">else</strong> {
-<a class="jxr_linenumber" name="L7837" href="#L7837">7837</a> 						currentLine.append(word);
-<a class="jxr_linenumber" name="L7838" href="#L7838">7838</a> 					}
-<a class="jxr_linenumber" name="L7839" href="#L7839">7839</a> 				} <strong class="jxr_keyword">else</strong> {
-<a class="jxr_linenumber" name="L7840" href="#L7840">7840</a> 					<em class="jxr_comment">// Check if we can add this word to current line</em>
-<a class="jxr_linenumber" name="L7841" href="#L7841">7841</a> 					<strong class="jxr_keyword">var</strong> neededLength = currentLength + 1 + wordLength;  <em class="jxr_comment">// current + space + word</em>
-<a class="jxr_linenumber" name="L7842" href="#L7842">7842</a> 					<em class="jxr_comment">// Break if it would fit exactly or exceed - prefer breaking for readability</em>
-<a class="jxr_linenumber" name="L7843" href="#L7843">7843</a> 					<strong class="jxr_keyword">if</strong> (neededLength &lt; wrapLength) {
-<a class="jxr_linenumber" name="L7844" href="#L7844">7844</a> 						<em class="jxr_comment">// Fits with room to spare</em>
-<a class="jxr_linenumber" name="L7845" href="#L7845">7845</a> 						currentLine.append(' ').append(word);
-<a class="jxr_linenumber" name="L7846" href="#L7846">7846</a> 					} <strong class="jxr_keyword">else</strong> {
-<a class="jxr_linenumber" name="L7847" href="#L7847">7847</a> 						<em class="jxr_comment">// Doesn't fit or fits exactly - start new line</em>
-<a class="jxr_linenumber" name="L7848" href="#L7848">7848</a> 						<strong class="jxr_keyword">if</strong> (result.length() &gt; 0)
-<a class="jxr_linenumber" name="L7849" href="#L7849">7849</a> 							result.append(newline);
-<a class="jxr_linenumber" name="L7850" href="#L7850">7850</a> 						result.append(currentLine);
-<a class="jxr_linenumber" name="L7851" href="#L7851">7851</a> 						currentLine.setLength(0);
-<a class="jxr_linenumber" name="L7852" href="#L7852">7852</a> 						<strong class="jxr_keyword">if</strong> (wordLength &gt; wrapLength &amp;&amp; words.length &gt; 1) {
-<a class="jxr_linenumber" name="L7853" href="#L7853">7853</a> 							<em class="jxr_comment">// Word is too long and there are other words, break it</em>
-<a class="jxr_linenumber" name="L7854" href="#L7854">7854</a> 							result.append(newline);
-<a class="jxr_linenumber" name="L7855" href="#L7855">7855</a> 							<strong class="jxr_keyword">var</strong> wordPos = 0;
-<a class="jxr_linenumber" name="L7856" href="#L7856">7856</a> 							<strong class="jxr_keyword">while</strong> (wordPos &lt; wordLength) {
-<a class="jxr_linenumber" name="L7857" href="#L7857">7857</a> 								<strong class="jxr_keyword">if</strong> (wordPos &gt; 0)
-<a class="jxr_linenumber" name="L7858" href="#L7858">7858</a> 									result.append(newline);
-<a class="jxr_linenumber" name="L7859" href="#L7859">7859</a> 								<strong class="jxr_keyword">var</strong> remaining = wordLength - wordPos;
-<a class="jxr_linenumber" name="L7860" href="#L7860">7860</a> 								<strong class="jxr_keyword">if</strong> (remaining &lt;= wrapLength) {
-<a class="jxr_linenumber" name="L7861" href="#L7861">7861</a> 									result.append(word.substring(wordPos));
-<a class="jxr_linenumber" name="L7862" href="#L7862">7862</a> 									<strong class="jxr_keyword">break</strong>;
-<a class="jxr_linenumber" name="L7863" href="#L7863">7863</a> 								}
-<a class="jxr_linenumber" name="L7864" href="#L7864">7864</a> 								result.append(word.substring(wordPos, wordPos + wrapLength));
-<a class="jxr_linenumber" name="L7865" href="#L7865">7865</a> 								wordPos += wrapLength;
-<a class="jxr_linenumber" name="L7866" href="#L7866">7866</a> 							}
-<a class="jxr_linenumber" name="L7867" href="#L7867">7867</a> 						} <strong class="jxr_keyword">else</strong> {
-<a class="jxr_linenumber" name="L7868" href="#L7868">7868</a> 							currentLine.append(word);
-<a class="jxr_linenumber" name="L7869" href="#L7869">7869</a> 						}
-<a class="jxr_linenumber" name="L7870" href="#L7870">7870</a> 					}
-<a class="jxr_linenumber" name="L7871" href="#L7871">7871</a> 				}
-<a class="jxr_linenumber" name="L7872" href="#L7872">7872</a> 			}
-<a class="jxr_linenumber" name="L7873" href="#L7873">7873</a> 
-<a class="jxr_linenumber" name="L7874" href="#L7874">7874</a> 			<em class="jxr_comment">// Append any remaining line</em>
-<a class="jxr_linenumber" name="L7875" href="#L7875">7875</a> 			<strong class="jxr_keyword">if</strong> (currentLine.length() &gt; 0) {
-<a class="jxr_linenumber" name="L7876" href="#L7876">7876</a> 				<strong class="jxr_keyword">if</strong> (result.length() &gt; 0)
-<a class="jxr_linenumber" name="L7877" href="#L7877">7877</a> 					result.append(newline);
-<a class="jxr_linenumber" name="L7878" href="#L7878">7878</a> 				result.append(currentLine);
-<a class="jxr_linenumber" name="L7879" href="#L7879">7879</a> 			}
-<a class="jxr_linenumber" name="L7880" href="#L7880">7880</a> 		}
+<a class="jxr_linenumber" name="L7813" href="#L7813">7813</a> 				<strong class="jxr_keyword">if</strong> (currentLength == 0) {
+<a class="jxr_linenumber" name="L7814" href="#L7814">7814</a> 					<em class="jxr_comment">// First word on line</em>
+<a class="jxr_linenumber" name="L7815" href="#L7815">7815</a> 					<em class="jxr_comment">// Only break single words if there are multiple words in the input</em>
+<a class="jxr_linenumber" name="L7816" href="#L7816">7816</a> 					<em class="jxr_comment">// (single long words should not be broken for readability)</em>
+<a class="jxr_linenumber" name="L7817" href="#L7817">7817</a> 					<strong class="jxr_keyword">if</strong> (wordLength &gt; wrapLength &amp;&amp; words.length &gt; 1) {
+<a class="jxr_linenumber" name="L7818" href="#L7818">7818</a> 						<em class="jxr_comment">// Word is too long and there are other words, break it</em>
+<a class="jxr_linenumber" name="L7819" href="#L7819">7819</a> 						<strong class="jxr_keyword">if</strong> (result.length() &gt; 0)
+<a class="jxr_linenumber" name="L7820" href="#L7820">7820</a> 							result.append(newline);
+<a class="jxr_linenumber" name="L7821" href="#L7821">7821</a> 						<strong class="jxr_keyword">var</strong> wordPos = 0;
+<a class="jxr_linenumber" name="L7822" href="#L7822">7822</a> 						<strong class="jxr_keyword">while</strong> (wordPos &lt; wordLength) {
+<a class="jxr_linenumber" name="L7823" href="#L7823">7823</a> 							<strong class="jxr_keyword">if</strong> (wordPos &gt; 0)
+<a class="jxr_linenumber" name="L7824" href="#L7824">7824</a> 								result.append(newline);
+<a class="jxr_linenumber" name="L7825" href="#L7825">7825</a> 							<strong class="jxr_keyword">var</strong> remaining = wordLength - wordPos;
+<a class="jxr_linenumber" name="L7826" href="#L7826">7826</a> 							<strong class="jxr_keyword">if</strong> (remaining &lt;= wrapLength) {
+<a class="jxr_linenumber" name="L7827" href="#L7827">7827</a> 								result.append(word.substring(wordPos));
+<a class="jxr_linenumber" name="L7828" href="#L7828">7828</a> 								<strong class="jxr_keyword">break</strong>;
+<a class="jxr_linenumber" name="L7829" href="#L7829">7829</a> 							}
+<a class="jxr_linenumber" name="L7830" href="#L7830">7830</a> 							result.append(word.substring(wordPos, wordPos + wrapLength));
+<a class="jxr_linenumber" name="L7831" href="#L7831">7831</a> 							wordPos += wrapLength;
+<a class="jxr_linenumber" name="L7832" href="#L7832">7832</a> 						}
+<a class="jxr_linenumber" name="L7833" href="#L7833">7833</a> 					} <strong class="jxr_keyword">else</strong> {
+<a class="jxr_linenumber" name="L7834" href="#L7834">7834</a> 						currentLine.append(word);
+<a class="jxr_linenumber" name="L7835" href="#L7835">7835</a> 					}
+<a class="jxr_linenumber" name="L7836" href="#L7836">7836</a> 				} <strong class="jxr_keyword">else</strong> {
+<a class="jxr_linenumber" name="L7837" href="#L7837">7837</a> 					<em class="jxr_comment">// Check if we can add this word to current line</em>
+<a class="jxr_linenumber" name="L7838" href="#L7838">7838</a> 					<strong class="jxr_keyword">var</strong> neededLength = currentLength + 1 + wordLength;  <em class="jxr_comment">// current + space + word</em>
+<a class="jxr_linenumber" name="L7839" href="#L7839">7839</a> 					<em class="jxr_comment">// Break if it would fit exactly or exceed - prefer breaking for readability</em>
+<a class="jxr_linenumber" name="L7840" href="#L7840">7840</a> 					<strong class="jxr_keyword">if</strong> (neededLength &lt; wrapLength) {
+<a class="jxr_linenumber" name="L7841" href="#L7841">7841</a> 						<em class="jxr_comment">// Fits with room to spare</em>
+<a class="jxr_linenumber" name="L7842" href="#L7842">7842</a> 						currentLine.append(' ').append(word);
+<a class="jxr_linenumber" name="L7843" href="#L7843">7843</a> 					} <strong class="jxr_keyword">else</strong> {
+<a class="jxr_linenumber" name="L7844" href="#L7844">7844</a> 						<em class="jxr_comment">// Doesn't fit or fits exactly - start new line</em>
+<a class="jxr_linenumber" name="L7845" href="#L7845">7845</a> 						<strong class="jxr_keyword">if</strong> (result.length() &gt; 0)
+<a class="jxr_linenumber" name="L7846" href="#L7846">7846</a> 							result.append(newline);
+<a class="jxr_linenumber" name="L7847" href="#L7847">7847</a> 						result.append(currentLine);
+<a class="jxr_linenumber" name="L7848" href="#L7848">7848</a> 						currentLine.setLength(0);
+<a class="jxr_linenumber" name="L7849" href="#L7849">7849</a> 						<strong class="jxr_keyword">if</strong> (wordLength &gt; wrapLength &amp;&amp; words.length &gt; 1) {
+<a class="jxr_linenumber" name="L7850" href="#L7850">7850</a> 							<em class="jxr_comment">// Word is too long and there are other words, break it</em>
+<a class="jxr_linenumber" name="L7851" href="#L7851">7851</a> 							result.append(newline);
+<a class="jxr_linenumber" name="L7852" href="#L7852">7852</a> 							<strong class="jxr_keyword">var</strong> wordPos = 0;
+<a class="jxr_linenumber" name="L7853" href="#L7853">7853</a> 							<strong class="jxr_keyword">while</strong> (wordPos &lt; wordLength) {
+<a class="jxr_linenumber" name="L7854" href="#L7854">7854</a> 								<strong class="jxr_keyword">if</strong> (wordPos &gt; 0)
+<a class="jxr_linenumber" name="L7855" href="#L7855">7855</a> 									result.append(newline);
+<a class="jxr_linenumber" name="L7856" href="#L7856">7856</a> 								<strong class="jxr_keyword">var</strong> remaining = wordLength - wordPos;
+<a class="jxr_linenumber" name="L7857" href="#L7857">7857</a> 								<strong class="jxr_keyword">if</strong> (remaining &lt;= wrapLength) {
+<a class="jxr_linenumber" name="L7858" href="#L7858">7858</a> 									result.append(word.substring(wordPos));
+<a class="jxr_linenumber" name="L7859" href="#L7859">7859</a> 									<strong class="jxr_keyword">break</strong>;
+<a class="jxr_linenumber" name="L7860" href="#L7860">7860</a> 								}
+<a class="jxr_linenumber" name="L7861" href="#L7861">7861</a> 								result.append(word.substring(wordPos, wordPos + wrapLength));
+<a class="jxr_linenumber" name="L7862" href="#L7862">7862</a> 								wordPos += wrapLength;
+<a class="jxr_linenumber" name="L7863" href="#L7863">7863</a> 							}
+<a class="jxr_linenumber" name="L7864" href="#L7864">7864</a> 						} <strong class="jxr_keyword">else</strong> {
+<a class="jxr_linenumber" name="L7865" href="#L7865">7865</a> 							currentLine.append(word);
+<a class="jxr_linenumber" name="L7866" href="#L7866">7866</a> 						}
+<a class="jxr_linenumber" name="L7867" href="#L7867">7867</a> 					}
+<a class="jxr_linenumber" name="L7868" href="#L7868">7868</a> 				}
+<a class="jxr_linenumber" name="L7869" href="#L7869">7869</a> 			}
+<a class="jxr_linenumber" name="L7870" href="#L7870">7870</a> 
+<a class="jxr_linenumber" name="L7871" href="#L7871">7871</a> 			<em class="jxr_comment">// Append any remaining line</em>
+<a class="jxr_linenumber" name="L7872" href="#L7872">7872</a> 			<strong class="jxr_keyword">if</strong> (currentLine.length() &gt; 0) {
+<a class="jxr_linenumber" name="L7873" href="#L7873">7873</a> 				<strong class="jxr_keyword">if</strong> (result.length() &gt; 0)
+<a class="jxr_linenumber" name="L7874" href="#L7874">7874</a> 					result.append(newline);
+<a class="jxr_linenumber" name="L7875" href="#L7875">7875</a> 				result.append(currentLine);
+<a class="jxr_linenumber" name="L7876" href="#L7876">7876</a> 			}
+<a class="jxr_linenumber" name="L7877" href="#L7877">7877</a> 		}
+<a class="jxr_linenumber" name="L7878" href="#L7878">7878</a> 
+<a class="jxr_linenumber" name="L7879" href="#L7879">7879</a> 		<strong class="jxr_keyword">return</strong> result.toString();
+<a class="jxr_linenumber" name="L7880" href="#L7880">7880</a> 	}
 <a class="jxr_linenumber" name="L7881" href="#L7881">7881</a> 
-<a class="jxr_linenumber" name="L7882" href="#L7882">7882</a> 		<strong class="jxr_keyword">return</strong> result.toString();
-<a class="jxr_linenumber" name="L7883" href="#L7883">7883</a> 	}
-<a class="jxr_linenumber" name="L7884" href="#L7884">7884</a> 
-<a class="jxr_linenumber" name="L7885" href="#L7885">7885</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7886" href="#L7886">7886</a> <em class="jxr_javadoccomment">	 * Helper method to estimate the number of syllables in a word.</em>
-<a class="jxr_linenumber" name="L7887" href="#L7887">7887</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7888" href="#L7888">7888</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">int</strong> estimateSyllables(String word) {
-<a class="jxr_linenumber" name="L7889" href="#L7889">7889</a> 
-<a class="jxr_linenumber" name="L7890" href="#L7890">7890</a> 		<strong class="jxr_keyword">var</strong> lower = word.toLowerCase();
-<a class="jxr_linenumber" name="L7891" href="#L7891">7891</a> 		<strong class="jxr_keyword">var</strong> count = 0;
-<a class="jxr_linenumber" name="L7892" href="#L7892">7892</a> 		<strong class="jxr_keyword">var</strong> prevWasVowel = false;
-<a class="jxr_linenumber" name="L7893" href="#L7893">7893</a> 
-<a class="jxr_linenumber" name="L7894" href="#L7894">7894</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; lower.length(); i++) {
-<a class="jxr_linenumber" name="L7895" href="#L7895">7895</a> 			<strong class="jxr_keyword">var</strong> c = lower.charAt(i);
-<a class="jxr_linenumber" name="L7896" href="#L7896">7896</a> 			<strong class="jxr_keyword">var</strong> isVowel = (VOWEL.contains(c) || c == 'y');
-<a class="jxr_linenumber" name="L7897" href="#L7897">7897</a> 
-<a class="jxr_linenumber" name="L7898" href="#L7898">7898</a> 			<strong class="jxr_keyword">if</strong> (isVowel &amp;&amp; ! prevWasVowel) {
-<a class="jxr_linenumber" name="L7899" href="#L7899">7899</a> 				count++;
-<a class="jxr_linenumber" name="L7900" href="#L7900">7900</a> 			}
-<a class="jxr_linenumber" name="L7901" href="#L7901">7901</a> 			prevWasVowel = isVowel;
-<a class="jxr_linenumber" name="L7902" href="#L7902">7902</a> 		}
-<a class="jxr_linenumber" name="L7903" href="#L7903">7903</a> 
-<a class="jxr_linenumber" name="L7904" href="#L7904">7904</a> 		<em class="jxr_comment">// Handle silent 'e' at the end</em>
-<a class="jxr_linenumber" name="L7905" href="#L7905">7905</a> 		<strong class="jxr_keyword">if</strong> (lower.endsWith(<span class="jxr_string">"e"</span>) &amp;&amp; count &gt; 1) {
-<a class="jxr_linenumber" name="L7906" href="#L7906">7906</a> 			count--;
-<a class="jxr_linenumber" name="L7907" href="#L7907">7907</a> 		}
-<a class="jxr_linenumber" name="L7908" href="#L7908">7908</a> 
-<a class="jxr_linenumber" name="L7909" href="#L7909">7909</a> 		<em class="jxr_comment">// At least one syllable</em>
-<a class="jxr_linenumber" name="L7910" href="#L7910">7910</a> 		<strong class="jxr_keyword">return</strong> Math.max(1, count);
-<a class="jxr_linenumber" name="L7911" href="#L7911">7911</a> 	}
-<a class="jxr_linenumber" name="L7912" href="#L7912">7912</a> 
-<a class="jxr_linenumber" name="L7913" href="#L7913">7913</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7914" href="#L7914">7914</a> <em class="jxr_javadoccomment">	 * Finds the first non-whitespace, non-comment character in a string.</em>
-<a class="jxr_linenumber" name="L7915" href="#L7915">7915</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7916" href="#L7916">7916</a> <em class="jxr_javadoccomment">	 * @param s The string to analyze.</em>
-<a class="jxr_linenumber" name="L7917" href="#L7917">7917</a> <em class="jxr_javadoccomment">	 * @return The first real character, or &lt;c&gt;-1&lt;/c&gt; if none found.</em>
-<a class="jxr_linenumber" name="L7918" href="#L7918">7918</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7919" href="#L7919">7919</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">int</strong> firstRealCharacter(String s) {
-<a class="jxr_linenumber" name="L7920" href="#L7920">7920</a> 		<strong class="jxr_keyword">return</strong> safe(()-&gt; {
-<a class="jxr_linenumber" name="L7921" href="#L7921">7921</a> 			<strong class="jxr_keyword">var</strong> r = <strong class="jxr_keyword">new</strong> StringReader(s);
-<a class="jxr_linenumber" name="L7922" href="#L7922">7922</a> 			<strong class="jxr_keyword">var</strong> c = 0;
-<a class="jxr_linenumber" name="L7923" href="#L7923">7923</a> 			<strong class="jxr_keyword">while</strong> ((c = r.read()) != -1) {
-<a class="jxr_linenumber" name="L7924" href="#L7924">7924</a> 				<strong class="jxr_keyword">if</strong> (! isWhitespace(c)) {
-<a class="jxr_linenumber" name="L7925" href="#L7925">7925</a> 					<strong class="jxr_keyword">if</strong> (c == '/') {
-<a class="jxr_linenumber" name="L7926" href="#L7926">7926</a> 						skipComments(r);
-<a class="jxr_linenumber" name="L7927" href="#L7927">7927</a> 					} <strong class="jxr_keyword">else</strong> {
-<a class="jxr_linenumber" name="L7928" href="#L7928">7928</a> 						<strong class="jxr_keyword">return</strong> c;
-<a class="jxr_linenumber" name="L7929" href="#L7929">7929</a> 					}
-<a class="jxr_linenumber" name="L7930" href="#L7930">7930</a> 				}
-<a class="jxr_linenumber" name="L7931" href="#L7931">7931</a> 			}
-<a class="jxr_linenumber" name="L7932" href="#L7932">7932</a> 			<strong class="jxr_keyword">return</strong> -1;
-<a class="jxr_linenumber" name="L7933" href="#L7933">7933</a> 		});
-<a class="jxr_linenumber" name="L7934" href="#L7934">7934</a> 	}
-<a class="jxr_linenumber" name="L7935" href="#L7935">7935</a> 
-<a class="jxr_linenumber" name="L7936" href="#L7936">7936</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7937" href="#L7937">7937</a> <em class="jxr_javadoccomment">	 * Helper method to get Soundex code for a character.</em>
-<a class="jxr_linenumber" name="L7938" href="#L7938">7938</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7939" href="#L7939">7939</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">char</strong> getSoundexCode(<strong class="jxr_keyword">char</strong> c) {
-<a class="jxr_linenumber" name="L7940" href="#L7940">7940</a> 		<strong class="jxr_keyword">if</strong> (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' || c == 'H' || c == 'W' || c == 'Y')
-<a class="jxr_linenumber" name="L7941" href="#L7941">7941</a> 			<strong class="jxr_keyword">return</strong> '0';
-<a class="jxr_linenumber" name="L7942" href="#L7942">7942</a> 		<strong class="jxr_keyword">if</strong> (c == 'B' || c == 'F' || c == 'P' || c == 'V')
-<a class="jxr_linenumber" name="L7943" href="#L7943">7943</a> 			<strong class="jxr_keyword">return</strong> '1';
-<a class="jxr_linenumber" name="L7944" href="#L7944">7944</a> 		<strong class="jxr_keyword">if</strong> (c == 'C' || c == 'G' || c == 'J' || c == 'K' || c == 'Q' || c == 'S' || c == 'X' || c == 'Z')
-<a class="jxr_linenumber" name="L7945" href="#L7945">7945</a> 			<strong class="jxr_keyword">return</strong> '2';
-<a class="jxr_linenumber" name="L7946" href="#L7946">7946</a> 		<strong class="jxr_keyword">if</strong> (c == 'D' || c == 'T')
-<a class="jxr_linenumber" name="L7947" href="#L7947">7947</a> 			<strong class="jxr_keyword">return</strong> '3';
-<a class="jxr_linenumber" name="L7948" href="#L7948">7948</a> 		<strong class="jxr_keyword">if</strong> (c == 'L')
-<a class="jxr_linenumber" name="L7949" href="#L7949">7949</a> 			<strong class="jxr_keyword">return</strong> '4';
-<a class="jxr_linenumber" name="L7950" href="#L7950">7950</a> 		<strong class="jxr_keyword">if</strong> (c == 'M' || c == 'N')
-<a class="jxr_linenumber" name="L7951" href="#L7951">7951</a> 			<strong class="jxr_keyword">return</strong> '5';
-<a class="jxr_linenumber" name="L7952" href="#L7952">7952</a> 		<strong class="jxr_keyword">if</strong> (c == 'R')
-<a class="jxr_linenumber" name="L7953" href="#L7953">7953</a> 			<strong class="jxr_keyword">return</strong> '6';
-<a class="jxr_linenumber" name="L7954" href="#L7954">7954</a> 		<strong class="jxr_keyword">return</strong> '0'; <em class="jxr_comment">// Non-letter characters</em>
-<a class="jxr_linenumber" name="L7955" href="#L7955">7955</a> 	}
-<a class="jxr_linenumber" name="L7956" href="#L7956">7956</a> 
-<a class="jxr_linenumber" name="L7957" href="#L7957">7957</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L7958" href="#L7958">7958</a> <em class="jxr_javadoccomment">	 * Validates if a string is a valid IPv6 address format (without network operations).</em>
-<a class="jxr_linenumber" name="L7959" href="#L7959">7959</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7960" href="#L7960">7960</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
-<a class="jxr_linenumber" name="L7961" href="#L7961">7961</a> <em class="jxr_javadoccomment">	 * This method performs pure string-based validation and does not perform any DNS lookups</em>
-<a class="jxr_linenumber" name="L7962" href="#L7962">7962</a> <em class="jxr_javadoccomment">	 * or network operations, making it fast and suitable for validation purposes.</em>
-<a class="jxr_linenumber" name="L7963" href="#L7963">7963</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L7964" href="#L7964">7964</a> <em class="jxr_javadoccomment">	 * @param ip The IPv6 address string to validate.</em>
-<a class="jxr_linenumber" name="L7965" href="#L7965">7965</a> <em class="jxr_javadoccomment">	 * @return &lt;jk&gt;true&lt;/jk&gt; if the string is a valid IPv6 address format, &lt;jk&gt;false&lt;/jk&gt; otherwise.</em>
-<a class="jxr_linenumber" name="L7966" href="#L7966">7966</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L7967" href="#L7967">7967</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">boolean</strong> isValidIPv6Address(String ip) {
-<a class="jxr_linenumber" name="L7968" href="#L7968">7968</a> 		<strong class="jxr_keyword">if</strong> (ip == <strong class="jxr_keyword">null</strong> || ip.isEmpty())
-<a class="jxr_linenumber" name="L7969" href="#L7969">7969</a> 			<strong class="jxr_keyword">return</strong> false;
-<a class="jxr_linenumber" name="L7970" href="#L7970">7970</a> 
-<a class="jxr_linenumber" name="L7971" href="#L7971">7971</a> 		<em class="jxr_comment">// IPv6 addresses can be:</em>
-<a class="jxr_linenumber" name="L7972" href="#L7972">7972</a> 		<em class="jxr_comment">// 1. Full format: 2001:0db8:85a3:0000:0000:8a2e:0370:7334 (8 groups of 4 hex digits)</em>
-<a class="jxr_linenumber" name="L7973" href="#L7973">7973</a> 		<em class="jxr_comment">// 2. Compressed format: 2001:db8::1 (uses :: to represent consecutive zeros)</em>
-<a class="jxr_linenumber" name="L7974" href="#L7974">7974</a> 		<em class="jxr_comment">// 3. IPv4-mapped: ::ffff:192.168.1.1 (last 32 bits as IPv4)</em>
-<a class="jxr_linenumber" name="L7975" href="#L7975">7975</a> 		<em class="jxr_comment">// 4. Loopback: ::1</em>
-<a class="jxr_linenumber" name="L7976" href="#L7976">7976</a> 		<em class="jxr_comment">// 5. Unspecified: ::</em>
-<a class="jxr_linenumber" name="L7977" href="#L7977">7977</a> 
-<a class="jxr_linenumber" name="L7978" href="#L7978">7978</a> 		<em class="jxr_comment">// Cannot start or end with a single colon (except ::)</em>
-<a class="jxr_linenumber" name="L7979" href="#L7979">7979</a> 		<strong class="jxr_keyword">if</strong> (ip.startsWith(<span class="jxr_string">":"</span>) &amp;&amp; !ip.startsWith(<span class="jxr_string">"::"</span>))
-<a class="jxr_linenumber" name="L7980" href="#L7980">7980</a> 			<strong class="jxr_keyword">return</strong> false;
-<a class="jxr_linenumber" name="L7981" href="#L7981">7981</a> 		<strong class="jxr_keyword">if</strong> (ip.endsWith(<span class="jxr_string">":"</span>) &amp;&amp; !ip.endsWith(<span class="jxr_string">"::"</span>))
-<a class="jxr_linenumber" name="L7982" href="#L7982">7982</a> 			<strong class="jxr_keyword">return</strong> false;
-<a class="jxr_linenumber" name="L7983" href="#L7983">7983</a> 
-<a class="jxr_linenumber" name="L7984" href="#L7984">7984</a> 		<em class="jxr_comment">// Check for IPv4-mapped format (contains both : and .)</em>
-<a class="jxr_linenumber" name="L7985" href="#L7985">7985</a> 		<strong class="jxr_keyword">if</strong> (ip.contains(<span class="jxr_string">"."</span>)) {
-<a class="jxr_linenumber" name="L7986" href="#L7986">7986</a> 			<em class="jxr_comment">// Must be in format ::ffff:x.x.x.x or similar</em>
-<a class="jxr_linenumber" name="L7987" href="#L7987">7987</a> 			<strong class="jxr_keyword">var</strong> lastColon = ip.lastIndexOf(<span class="jxr_string">":"</span>);
-<a class="jxr_linenumber" name="L7988" href="#L7988">7988</a> 			<strong class="jxr_keyword">if</strong> (lastColon &lt; 0)
-<a class="jxr_linenumber" name="L7989" href="#L7989">7989</a> 				<strong class="jxr_keyword">return</strong> false;
-<a class="jxr_linenumber" name="L7990" href="#L7990">7990</a> 			<strong class="jxr_keyword">var</strong> ipv4Part = ip.substring(lastColon + 1);
-<a class="jxr_linenumber" name="L7991" href="#L7991">7991</a> 			<em class="jxr_comment">// Validate IPv4 part</em>
-<a class="jxr_linenumber" name="L7992" href="#L7992">7992</a> 			<strong class="jxr_keyword">var</strong> ipv4Parts = ipv4Part.split(<span class="jxr_string">"&#92;&#92;."</span>);
-<a class="jxr_linenumber" name="L7993" href="#L7993">7993</a> 			<strong class="jxr_keyword">if</strong> (ipv4Parts.length != 4)
-<a class="jxr_linenumber" name="L7994" href="#L7994">7994</a> 				<strong class="jxr_keyword">return</strong> false;
-<a class="jxr_linenumber" name="L7995" href="#L7995">7995</a> 			<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> part : ipv4Parts) {
-<a class="jxr_linenumber" name="L7996" href="#L7996">7996</a> 				<strong class="jxr_keyword">try</strong> {
-<a class="jxr_linenumber" name="L7997" href="#L7997">7997</a> 					<strong class="jxr_keyword">var</strong> num = Integer.parseInt(part);
-<a class="jxr_linenumber" name="L7998" href="#L7998">7998</a> 					<strong class="jxr_keyword">if</strong> (num &lt; 0 || num &gt; 255)
-<a class="jxr_linenumber" name="L7999" href="#L7999">7999</a> 						<strong class="jxr_keyword">return</strong> false;
-<a class="jxr_linenumber" name="L8000" href="#L8000">8000</a> 				} <strong class="jxr_keyword">catch</strong> (@SuppressWarnings(<span class="jxr_string">"unused"</span>) NumberFormatException e) {
-<a class="jxr_linenumber" name="L8001" href="#L8001">8001</a> 					<strong class="jxr_keyword">return</strong> false;
-<a class="jxr_linenumber" name="L8002" href="#L8002">8002</a> 				}
-<a class="jxr_linenumber" name="L8003" href="#L8003">8003</a> 			}
-<a class="jxr_linenumber" name="L8004" href="#L8004">8004</a> 			<em class="jxr_comment">// Validate IPv6 part before the IPv4</em>
-<a class="jxr_linenumber" name="L8005" href="#L8005">8005</a> 			<strong class="jxr_keyword">var</strong> ipv6Part = ip.substring(0, lastColon);
-<a class="jxr_linenumber" name="L8006" href="#L8006">8006</a> 			<em class="jxr_comment">// Accept empty, ::, ::ffff, ::FFFF, or : (when string starts with ::)</em>
-<a class="jxr_linenumber" name="L8007" href="#L8007">8007</a> 			<strong class="jxr_keyword">if</strong> (ipv6Part.isEmpty() || ipv6Part.equals(<span class="jxr_string">"::"</span>) || ipv6Part.equals(<span class="jxr_string">"::ffff"</span>) || ipv6Part.equals(<span class="jxr_string">"::FFFF"</span>) || (ipv6Part.equals(<span class="jxr_string">":"</span>) &amp;&amp; ip.startsWith(<span class="jxr_string">"::"</span>)))
-<a class="jxr_linenumber" name="L8008" href="#L8008">8008</a> 				<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">true</strong>;
-<a class="jxr_linenumber" name="L8009" href="#L8009">8009</a> 			<em class="jxr_comment">// More complex validation would be needed for other IPv4-mapped formats</em>
-<a class="jxr_linenumber" name="L8010" href="#L8010">8010</a> 			<em class="jxr_comment">// For now, accept common formats</em>
-<a class="jxr_linenumber" name="L8011" href="#L8011">8011</a> 		}
-<a class="jxr_linenumber" name="L8012" href="#L8012">8012</a> 
-<a class="jxr_linenumber" name="L8013" href="#L8013">8013</a> 		<em class="jxr_comment">// Check for :: (compression) - only one allowed</em>
-<a class="jxr_linenumber" name="L8014" href="#L8014">8014</a> 		<strong class="jxr_keyword">var</strong> doubleColonCount = 0;
-<a class="jxr_linenumber" name="L8015" href="#L8015">8015</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 1; i &lt; ip.length(); i++) {
-<a class="jxr_linenumber" name="L8016" href="#L8016">8016</a> 			<strong class="jxr_keyword">if</strong> (ip.charAt(i) == ':' &amp;&amp; ip.charAt(i - 1) == ':') {
-<a class="jxr_linenumber" name="L8017" href="#L8017">8017</a> 				doubleColonCount++;
-<a class="jxr_linenumber" name="L8018" href="#L8018">8018</a> 				<strong class="jxr_keyword">if</strong> (doubleColonCount &gt; 1)
-<a class="jxr_linenumber" name="L8019" href="#L8019">8019</a> 					<strong class="jxr_keyword">return</strong> false; <em class="jxr_comment">// Only one :: allowed</em>
-<a class="jxr_linenumber" name="L8020" href="#L8020">8020</a> 			}
-<a class="jxr_linenumber" name="L8021" href="#L8021">8021</a> 		}
+<a class="jxr_linenumber" name="L7882" href="#L7882">7882</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7883" href="#L7883">7883</a> <em class="jxr_javadoccomment">	 * Helper method to estimate the number of syllables in a word.</em>
+<a class="jxr_linenumber" name="L7884" href="#L7884">7884</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7885" href="#L7885">7885</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">int</strong> estimateSyllables(String word) {
+<a class="jxr_linenumber" name="L7886" href="#L7886">7886</a> 
+<a class="jxr_linenumber" name="L7887" href="#L7887">7887</a> 		<strong class="jxr_keyword">var</strong> lower = word.toLowerCase();
+<a class="jxr_linenumber" name="L7888" href="#L7888">7888</a> 		<strong class="jxr_keyword">var</strong> count = 0;
+<a class="jxr_linenumber" name="L7889" href="#L7889">7889</a> 		<strong class="jxr_keyword">var</strong> prevWasVowel = false;
+<a class="jxr_linenumber" name="L7890" href="#L7890">7890</a> 
+<a class="jxr_linenumber" name="L7891" href="#L7891">7891</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; lower.length(); i++) {
+<a class="jxr_linenumber" name="L7892" href="#L7892">7892</a> 			<strong class="jxr_keyword">var</strong> c = lower.charAt(i);
+<a class="jxr_linenumber" name="L7893" href="#L7893">7893</a> 			<strong class="jxr_keyword">var</strong> isVowel = (VOWEL.contains(c) || c == 'y');
+<a class="jxr_linenumber" name="L7894" href="#L7894">7894</a> 
+<a class="jxr_linenumber" name="L7895" href="#L7895">7895</a> 			<strong class="jxr_keyword">if</strong> (isVowel &amp;&amp; ! prevWasVowel) {
+<a class="jxr_linenumber" name="L7896" href="#L7896">7896</a> 				count++;
+<a class="jxr_linenumber" name="L7897" href="#L7897">7897</a> 			}
+<a class="jxr_linenumber" name="L7898" href="#L7898">7898</a> 			prevWasVowel = isVowel;
+<a class="jxr_linenumber" name="L7899" href="#L7899">7899</a> 		}
+<a class="jxr_linenumber" name="L7900" href="#L7900">7900</a> 
+<a class="jxr_linenumber" name="L7901" href="#L7901">7901</a> 		<em class="jxr_comment">// Handle silent 'e' at the end</em>
+<a class="jxr_linenumber" name="L7902" href="#L7902">7902</a> 		<strong class="jxr_keyword">if</strong> (lower.endsWith(<span class="jxr_string">"e"</span>) &amp;&amp; count &gt; 1) {
+<a class="jxr_linenumber" name="L7903" href="#L7903">7903</a> 			count--;
+<a class="jxr_linenumber" name="L7904" href="#L7904">7904</a> 		}
+<a class="jxr_linenumber" name="L7905" href="#L7905">7905</a> 
+<a class="jxr_linenumber" name="L7906" href="#L7906">7906</a> 		<em class="jxr_comment">// At least one syllable</em>
+<a class="jxr_linenumber" name="L7907" href="#L7907">7907</a> 		<strong class="jxr_keyword">return</strong> Math.max(1, count);
+<a class="jxr_linenumber" name="L7908" href="#L7908">7908</a> 	}
+<a class="jxr_linenumber" name="L7909" href="#L7909">7909</a> 
+<a class="jxr_linenumber" name="L7910" href="#L7910">7910</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7911" href="#L7911">7911</a> <em class="jxr_javadoccomment">	 * Finds the first non-whitespace, non-comment character in a string.</em>
+<a class="jxr_linenumber" name="L7912" href="#L7912">7912</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7913" href="#L7913">7913</a> <em class="jxr_javadoccomment">	 * @param s The string to analyze.</em>
+<a class="jxr_linenumber" name="L7914" href="#L7914">7914</a> <em class="jxr_javadoccomment">	 * @return The first real character, or &lt;c&gt;-1&lt;/c&gt; if none found.</em>
+<a class="jxr_linenumber" name="L7915" href="#L7915">7915</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7916" href="#L7916">7916</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">int</strong> firstRealCharacter(String s) {
+<a class="jxr_linenumber" name="L7917" href="#L7917">7917</a> 		<strong class="jxr_keyword">return</strong> safe(()-&gt; {
+<a class="jxr_linenumber" name="L7918" href="#L7918">7918</a> 			<strong class="jxr_keyword">var</strong> r = <strong class="jxr_keyword">new</strong> StringReader(s);
+<a class="jxr_linenumber" name="L7919" href="#L7919">7919</a> 			<strong class="jxr_keyword">var</strong> c = 0;
+<a class="jxr_linenumber" name="L7920" href="#L7920">7920</a> 			<strong class="jxr_keyword">while</strong> ((c = r.read()) != -1) {
+<a class="jxr_linenumber" name="L7921" href="#L7921">7921</a> 				<strong class="jxr_keyword">if</strong> (! isWhitespace(c)) {
+<a class="jxr_linenumber" name="L7922" href="#L7922">7922</a> 					<strong class="jxr_keyword">if</strong> (c == '/') {
+<a class="jxr_linenumber" name="L7923" href="#L7923">7923</a> 						skipComments(r);
+<a class="jxr_linenumber" name="L7924" href="#L7924">7924</a> 					} <strong class="jxr_keyword">else</strong> {
+<a class="jxr_linenumber" name="L7925" href="#L7925">7925</a> 						<strong class="jxr_keyword">return</strong> c;
+<a class="jxr_linenumber" name="L7926" href="#L7926">7926</a> 					}
+<a class="jxr_linenumber" name="L7927" href="#L7927">7927</a> 				}
+<a class="jxr_linenumber" name="L7928" href="#L7928">7928</a> 			}
+<a class="jxr_linenumber" name="L7929" href="#L7929">7929</a> 			<strong class="jxr_keyword">return</strong> -1;
+<a class="jxr_linenumber" name="L7930" href="#L7930">7930</a> 		});
+<a class="jxr_linenumber" name="L7931" href="#L7931">7931</a> 	}
+<a class="jxr_linenumber" name="L7932" href="#L7932">7932</a> 
+<a class="jxr_linenumber" name="L7933" href="#L7933">7933</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7934" href="#L7934">7934</a> <em class="jxr_javadoccomment">	 * Helper method to get Soundex code for a character.</em>
+<a class="jxr_linenumber" name="L7935" href="#L7935">7935</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7936" href="#L7936">7936</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">char</strong> getSoundexCode(<strong class="jxr_keyword">char</strong> c) {
+<a class="jxr_linenumber" name="L7937" href="#L7937">7937</a> 		<strong class="jxr_keyword">if</strong> (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' || c == 'H' || c == 'W' || c == 'Y')
+<a class="jxr_linenumber" name="L7938" href="#L7938">7938</a> 			<strong class="jxr_keyword">return</strong> '0';
+<a class="jxr_linenumber" name="L7939" href="#L7939">7939</a> 		<strong class="jxr_keyword">if</strong> (c == 'B' || c == 'F' || c == 'P' || c == 'V')
+<a class="jxr_linenumber" name="L7940" href="#L7940">7940</a> 			<strong class="jxr_keyword">return</strong> '1';
+<a class="jxr_linenumber" name="L7941" href="#L7941">7941</a> 		<strong class="jxr_keyword">if</strong> (c == 'C' || c == 'G' || c == 'J' || c == 'K' || c == 'Q' || c == 'S' || c == 'X' || c == 'Z')
+<a class="jxr_linenumber" name="L7942" href="#L7942">7942</a> 			<strong class="jxr_keyword">return</strong> '2';
+<a class="jxr_linenumber" name="L7943" href="#L7943">7943</a> 		<strong class="jxr_keyword">if</strong> (c == 'D' || c == 'T')
+<a class="jxr_linenumber" name="L7944" href="#L7944">7944</a> 			<strong class="jxr_keyword">return</strong> '3';
+<a class="jxr_linenumber" name="L7945" href="#L7945">7945</a> 		<strong class="jxr_keyword">if</strong> (c == 'L')
+<a class="jxr_linenumber" name="L7946" href="#L7946">7946</a> 			<strong class="jxr_keyword">return</strong> '4';
+<a class="jxr_linenumber" name="L7947" href="#L7947">7947</a> 		<strong class="jxr_keyword">if</strong> (c == 'M' || c == 'N')
+<a class="jxr_linenumber" name="L7948" href="#L7948">7948</a> 			<strong class="jxr_keyword">return</strong> '5';
+<a class="jxr_linenumber" name="L7949" href="#L7949">7949</a> 		<strong class="jxr_keyword">if</strong> (c == 'R')
+<a class="jxr_linenumber" name="L7950" href="#L7950">7950</a> 			<strong class="jxr_keyword">return</strong> '6';
+<a class="jxr_linenumber" name="L7951" href="#L7951">7951</a> 		<strong class="jxr_keyword">return</strong> '0'; <em class="jxr_comment">// Non-letter characters</em>
+<a class="jxr_linenumber" name="L7952" href="#L7952">7952</a> 	}
+<a class="jxr_linenumber" name="L7953" href="#L7953">7953</a> 
+<a class="jxr_linenumber" name="L7954" href="#L7954">7954</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L7955" href="#L7955">7955</a> <em class="jxr_javadoccomment">	 * Validates if a string is a valid IPv6 address format (without network operations).</em>
+<a class="jxr_linenumber" name="L7956" href="#L7956">7956</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7957" href="#L7957">7957</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
+<a class="jxr_linenumber" name="L7958" href="#L7958">7958</a> <em class="jxr_javadoccomment">	 * This method performs pure string-based validation and does not perform any DNS lookups</em>
+<a class="jxr_linenumber" name="L7959" href="#L7959">7959</a> <em class="jxr_javadoccomment">	 * or network operations, making it fast and suitable for validation purposes.</em>
+<a class="jxr_linenumber" name="L7960" href="#L7960">7960</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L7961" href="#L7961">7961</a> <em class="jxr_javadoccomment">	 * @param ip The IPv6 address string to validate.</em>
+<a class="jxr_linenumber" name="L7962" href="#L7962">7962</a> <em class="jxr_javadoccomment">	 * @return &lt;jk&gt;true&lt;/jk&gt; if the string is a valid IPv6 address format, &lt;jk&gt;false&lt;/jk&gt; otherwise.</em>
+<a class="jxr_linenumber" name="L7963" href="#L7963">7963</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L7964" href="#L7964">7964</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">boolean</strong> isValidIPv6Address(String ip) {
+<a class="jxr_linenumber" name="L7965" href="#L7965">7965</a> 		<strong class="jxr_keyword">if</strong> (ip == <strong class="jxr_keyword">null</strong> || ip.isEmpty())
+<a class="jxr_linenumber" name="L7966" href="#L7966">7966</a> 			<strong class="jxr_keyword">return</strong> false;
+<a class="jxr_linenumber" name="L7967" href="#L7967">7967</a> 
+<a class="jxr_linenumber" name="L7968" href="#L7968">7968</a> 		<em class="jxr_comment">// IPv6 addresses can be:</em>
+<a class="jxr_linenumber" name="L7969" href="#L7969">7969</a> 		<em class="jxr_comment">// 1. Full format: 2001:0db8:85a3:0000:0000:8a2e:0370:7334 (8 groups of 4 hex digits)</em>
+<a class="jxr_linenumber" name="L7970" href="#L7970">7970</a> 		<em class="jxr_comment">// 2. Compressed format: 2001:db8::1 (uses :: to represent consecutive zeros)</em>
+<a class="jxr_linenumber" name="L7971" href="#L7971">7971</a> 		<em class="jxr_comment">// 3. IPv4-mapped: ::ffff:192.168.1.1 (last 32 bits as IPv4)</em>
+<a class="jxr_linenumber" name="L7972" href="#L7972">7972</a> 		<em class="jxr_comment">// 4. Loopback: ::1</em>
+<a class="jxr_linenumber" name="L7973" href="#L7973">7973</a> 		<em class="jxr_comment">// 5. Unspecified: ::</em>
+<a class="jxr_linenumber" name="L7974" href="#L7974">7974</a> 
+<a class="jxr_linenumber" name="L7975" href="#L7975">7975</a> 		<em class="jxr_comment">// Cannot start or end with a single colon (except ::)</em>
+<a class="jxr_linenumber" name="L7976" href="#L7976">7976</a> 		<strong class="jxr_keyword">if</strong> (ip.startsWith(<span class="jxr_string">":"</span>) &amp;&amp; !ip.startsWith(<span class="jxr_string">"::"</span>))
+<a class="jxr_linenumber" name="L7977" href="#L7977">7977</a> 			<strong class="jxr_keyword">return</strong> false;
+<a class="jxr_linenumber" name="L7978" href="#L7978">7978</a> 		<strong class="jxr_keyword">if</strong> (ip.endsWith(<span class="jxr_string">":"</span>) &amp;&amp; !ip.endsWith(<span class="jxr_string">"::"</span>))
+<a class="jxr_linenumber" name="L7979" href="#L7979">7979</a> 			<strong class="jxr_keyword">return</strong> false;
+<a class="jxr_linenumber" name="L7980" href="#L7980">7980</a> 
+<a class="jxr_linenumber" name="L7981" href="#L7981">7981</a> 		<em class="jxr_comment">// Check for IPv4-mapped format (contains both : and .)</em>
+<a class="jxr_linenumber" name="L7982" href="#L7982">7982</a> 		<strong class="jxr_keyword">if</strong> (ip.contains(<span class="jxr_string">"."</span>)) {
+<a class="jxr_linenumber" name="L7983" href="#L7983">7983</a> 			<em class="jxr_comment">// Must be in format ::ffff:x.x.x.x or similar</em>
+<a class="jxr_linenumber" name="L7984" href="#L7984">7984</a> 			<strong class="jxr_keyword">var</strong> lastColon = ip.lastIndexOf(<span class="jxr_string">":"</span>);
+<a class="jxr_linenumber" name="L7985" href="#L7985">7985</a> 			<strong class="jxr_keyword">if</strong> (lastColon &lt; 0)
+<a class="jxr_linenumber" name="L7986" href="#L7986">7986</a> 				<strong class="jxr_keyword">return</strong> false;
+<a class="jxr_linenumber" name="L7987" href="#L7987">7987</a> 			<strong class="jxr_keyword">var</strong> ipv4Part = ip.substring(lastColon + 1);
+<a class="jxr_linenumber" name="L7988" href="#L7988">7988</a> 			<em class="jxr_comment">// Validate IPv4 part</em>
+<a class="jxr_linenumber" name="L7989" href="#L7989">7989</a> 			<strong class="jxr_keyword">var</strong> ipv4Parts = ipv4Part.split(<span class="jxr_string">"&#92;&#92;."</span>);
+<a class="jxr_linenumber" name="L7990" href="#L7990">7990</a> 			<strong class="jxr_keyword">if</strong> (ipv4Parts.length != 4)
+<a class="jxr_linenumber" name="L7991" href="#L7991">7991</a> 				<strong class="jxr_keyword">return</strong> false;
+<a class="jxr_linenumber" name="L7992" href="#L7992">7992</a> 			<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> part : ipv4Parts) {
+<a class="jxr_linenumber" name="L7993" href="#L7993">7993</a> 				<strong class="jxr_keyword">try</strong> {
+<a class="jxr_linenumber" name="L7994" href="#L7994">7994</a> 					<strong class="jxr_keyword">var</strong> num = Integer.parseInt(part);
+<a class="jxr_linenumber" name="L7995" href="#L7995">7995</a> 					<strong class="jxr_keyword">if</strong> (num &lt; 0 || num &gt; 255)
+<a class="jxr_linenumber" name="L7996" href="#L7996">7996</a> 						<strong class="jxr_keyword">return</strong> false;
+<a class="jxr_linenumber" name="L7997" href="#L7997">7997</a> 				} <strong class="jxr_keyword">catch</strong> (@SuppressWarnings(<span class="jxr_string">"unused"</span>) NumberFormatException e) {
+<a class="jxr_linenumber" name="L7998" href="#L7998">7998</a> 					<strong class="jxr_keyword">return</strong> false;
+<a class="jxr_linenumber" name="L7999" href="#L7999">7999</a> 				}
+<a class="jxr_linenumber" name="L8000" href="#L8000">8000</a> 			}
+<a class="jxr_linenumber" name="L8001" href="#L8001">8001</a> 			<em class="jxr_comment">// Validate IPv6 part before the IPv4</em>
+<a class="jxr_linenumber" name="L8002" href="#L8002">8002</a> 			<strong class="jxr_keyword">var</strong> ipv6Part = ip.substring(0, lastColon);
+<a class="jxr_linenumber" name="L8003" href="#L8003">8003</a> 			<em class="jxr_comment">// Accept empty, ::, ::ffff, ::FFFF, or : (when string starts with ::)</em>
+<a class="jxr_linenumber" name="L8004" href="#L8004">8004</a> 			<strong class="jxr_keyword">if</strong> (ipv6Part.isEmpty() || ipv6Part.equals(<span class="jxr_string">"::"</span>) || ipv6Part.equals(<span class="jxr_string">"::ffff"</span>) || ipv6Part.equals(<span class="jxr_string">"::FFFF"</span>) || (ipv6Part.equals(<span class="jxr_string">":"</span>) &amp;&amp; ip.startsWith(<span class="jxr_string">"::"</span>)))
+<a class="jxr_linenumber" name="L8005" href="#L8005">8005</a> 				<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">true</strong>;
+<a class="jxr_linenumber" name="L8006" href="#L8006">8006</a> 			<em class="jxr_comment">// More complex validation would be needed for other IPv4-mapped formats</em>
+<a class="jxr_linenumber" name="L8007" href="#L8007">8007</a> 			<em class="jxr_comment">// For now, accept common formats</em>
+<a class="jxr_linenumber" name="L8008" href="#L8008">8008</a> 		}
+<a class="jxr_linenumber" name="L8009" href="#L8009">8009</a> 
+<a class="jxr_linenumber" name="L8010" href="#L8010">8010</a> 		<em class="jxr_comment">// Check for :: (compression) - only one allowed</em>
+<a class="jxr_linenumber" name="L8011" href="#L8011">8011</a> 		<strong class="jxr_keyword">var</strong> doubleColonCount = 0;
+<a class="jxr_linenumber" name="L8012" href="#L8012">8012</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 1; i &lt; ip.length(); i++) {
+<a class="jxr_linenumber" name="L8013" href="#L8013">8013</a> 			<strong class="jxr_keyword">if</strong> (ip.charAt(i) == ':' &amp;&amp; ip.charAt(i - 1) == ':') {
+<a class="jxr_linenumber" name="L8014" href="#L8014">8014</a> 				doubleColonCount++;
+<a class="jxr_linenumber" name="L8015" href="#L8015">8015</a> 				<strong class="jxr_keyword">if</strong> (doubleColonCount &gt; 1)
+<a class="jxr_linenumber" name="L8016" href="#L8016">8016</a> 					<strong class="jxr_keyword">return</strong> false; <em class="jxr_comment">// Only one :: allowed</em>
+<a class="jxr_linenumber" name="L8017" href="#L8017">8017</a> 			}
+<a class="jxr_linenumber" name="L8018" href="#L8018">8018</a> 		}
+<a class="jxr_linenumber" name="L8019" href="#L8019">8019</a> 
+<a class="jxr_linenumber" name="L8020" href="#L8020">8020</a> 		<em class="jxr_comment">// Split by ::</em>
+<a class="jxr_linenumber" name="L8021" href="#L8021">8021</a> 		<strong class="jxr_keyword">var</strong> parts = ip.split(<span class="jxr_string">"::"</span>, -1);
 <a class="jxr_linenumber" name="L8022" href="#L8022">8022</a> 
-<a class="jxr_linenumber" name="L8023" href="#L8023">8023</a> 		<em class="jxr_comment">// Split by ::</em>
-<a class="jxr_linenumber" name="L8024" href="#L8024">8024</a> 		<strong class="jxr_keyword">var</strong> parts = ip.split(<span class="jxr_string">"::"</span>, -1);
-<a class="jxr_linenumber" name="L8025" href="#L8025">8025</a> 
-<a class="jxr_linenumber" name="L8026" href="#L8026">8026</a> 		<strong class="jxr_keyword">if</strong> (parts.length == 2) {
-<a class="jxr_linenumber" name="L8027" href="#L8027">8027</a> 			<em class="jxr_comment">// Compressed format</em>
-<a class="jxr_linenumber" name="L8028" href="#L8028">8028</a> 			<strong class="jxr_keyword">var</strong> leftParts = parts[0].isEmpty() ? <strong class="jxr_keyword">new</strong> String[0] : parts[0].split(<span class="jxr_string">":"</span>);
-<a class="jxr_linenumber" name="L8029" href="#L8029">8029</a> 			<strong class="jxr_keyword">var</strong> rightParts = parts[1].isEmpty() ? <strong class="jxr_keyword">new</strong> String[0] : parts[1].split(<span class="jxr_string">":"</span>);
-<a class="jxr_linenumber" name="L8030" href="#L8030">8030</a> 			<strong class="jxr_keyword">var</strong> totalParts = leftParts.length + rightParts.length;
-<a class="jxr_linenumber" name="L8031" href="#L8031">8031</a> 			<strong class="jxr_keyword">if</strong> (totalParts &gt; 7)
-<a class="jxr_linenumber" name="L8032" href="#L8032">8032</a> 				<strong class="jxr_keyword">return</strong> false; <em class="jxr_comment">// Too many groups (max 8, but :: counts as one or more)</em>
-<a class="jxr_linenumber" name="L8033" href="#L8033">8033</a> 		} <strong class="jxr_keyword">else</strong> {
-<a class="jxr_linenumber" name="L8034" href="#L8034">8034</a> 			<em class="jxr_comment">// Full format (no compression)</em>
-<a class="jxr_linenumber" name="L8035" href="#L8035">8035</a> 			<strong class="jxr_keyword">var</strong> groups = ip.split(<span class="jxr_string">":"</span>);
-<a class="jxr_linenumber" name="L8036" href="#L8036">8036</a> 			<strong class="jxr_keyword">if</strong> (groups.length != 8)
-<a class="jxr_linenumber" name="L8037" href="#L8037">8037</a> 				<strong class="jxr_keyword">return</strong> false;
-<a class="jxr_linenumber" name="L8038" href="#L8038">8038</a> 		}
-<a class="jxr_linenumber" name="L8039" href="#L8039">8039</a> 
-<a class="jxr_linenumber" name="L8040" href="#L8040">8040</a> 		<em class="jxr_comment">// Validate each hex group</em>
-<a class="jxr_linenumber" name="L8041" href="#L8041">8041</a> 		<strong class="jxr_keyword">var</strong> groups = ip.split(<span class="jxr_string">"::"</span>);
-<a class="jxr_linenumber" name="L8042" href="#L8042">8042</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> groupSection : groups) {
-<a class="jxr_linenumber" name="L8043" href="#L8043">8043</a> 			<strong class="jxr_keyword">if</strong> (groupSection.isEmpty())
-<a class="jxr_linenumber" name="L8044" href="#L8044">8044</a> 				<strong class="jxr_keyword">continue</strong>; <em class="jxr_comment">// Skip empty section from ::</em>
-<a class="jxr_linenumber" name="L8045" href="#L8045">8045</a> 			<strong class="jxr_keyword">var</strong> groupParts = groupSection.split(<span class="jxr_string">":"</span>);
-<a class="jxr_linenumber" name="L8046" href="#L8046">8046</a> 			<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> group : groupParts) {
-<a class="jxr_linenumber" name="L8047" href="#L8047">8047</a> 				<strong class="jxr_keyword">if</strong> (group.length() &gt; 4)
-<a class="jxr_linenumber" name="L8048" href="#L8048">8048</a> 					<strong class="jxr_keyword">return</strong> false; <em class="jxr_comment">// Each group is max 4 hex digits</em>
-<a class="jxr_linenumber" name="L8049" href="#L8049">8049</a> 				<em class="jxr_comment">// Validate hex digits</em>
-<a class="jxr_linenumber" name="L8050" href="#L8050">8050</a> 				<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; group.length(); i++) {
-<a class="jxr_linenumber" name="L8051" href="#L8051">8051</a> 					<strong class="jxr_keyword">var</strong> c = group.charAt(i);
-<a class="jxr_linenumber" name="L8052" href="#L8052">8052</a> 					<strong class="jxr_keyword">if</strong> (! HEXADECIMAL_CHARS.contains(c))
-<a class="jxr_linenumber" name="L8053" href="#L8053">8053</a> 						<strong class="jxr_keyword">return</strong> false;
-<a class="jxr_linenumber" name="L8054" href="#L8054">8054</a> 				}
-<a class="jxr_linenumber" name="L8055" href="#L8055">8055</a> 			}
-<a class="jxr_linenumber" name="L8056" href="#L8056">8056</a> 		}
+<a class="jxr_linenumber" name="L8023" href="#L8023">8023</a> 		<strong class="jxr_keyword">if</strong> (parts.length == 2) {
+<a class="jxr_linenumber" name="L8024" href="#L8024">8024</a> 			<em class="jxr_comment">// Compressed format</em>
+<a class="jxr_linenumber" name="L8025" href="#L8025">8025</a> 			<strong class="jxr_keyword">var</strong> leftParts = parts[0].isEmpty() ? <strong class="jxr_keyword">new</strong> String[0] : parts[0].split(<span class="jxr_string">":"</span>);
+<a class="jxr_linenumber" name="L8026" href="#L8026">8026</a> 			<strong class="jxr_keyword">var</strong> rightParts = parts[1].isEmpty() ? <strong class="jxr_keyword">new</strong> String[0] : parts[1].split(<span class="jxr_string">":"</span>);
+<a class="jxr_linenumber" name="L8027" href="#L8027">8027</a> 			<strong class="jxr_keyword">var</strong> totalParts = leftParts.length + rightParts.length;
+<a class="jxr_linenumber" name="L8028" href="#L8028">8028</a> 			<strong class="jxr_keyword">if</strong> (totalParts &gt; 7)
+<a class="jxr_linenumber" name="L8029" href="#L8029">8029</a> 				<strong class="jxr_keyword">return</strong> false; <em class="jxr_comment">// Too many groups (max 8, but :: counts as one or more)</em>
+<a class="jxr_linenumber" name="L8030" href="#L8030">8030</a> 		} <strong class="jxr_keyword">else</strong> {
+<a class="jxr_linenumber" name="L8031" href="#L8031">8031</a> 			<em class="jxr_comment">// Full format (no compression)</em>
+<a class="jxr_linenumber" name="L8032" href="#L8032">8032</a> 			<strong class="jxr_keyword">var</strong> groups = ip.split(<span class="jxr_string">":"</span>);
+<a class="jxr_linenumber" name="L8033" href="#L8033">8033</a> 			<strong class="jxr_keyword">if</strong> (groups.length != 8)
+<a class="jxr_linenumber" name="L8034" href="#L8034">8034</a> 				<strong class="jxr_keyword">return</strong> false;
+<a class="jxr_linenumber" name="L8035" href="#L8035">8035</a> 		}
+<a class="jxr_linenumber" name="L8036" href="#L8036">8036</a> 
+<a class="jxr_linenumber" name="L8037" href="#L8037">8037</a> 		<em class="jxr_comment">// Validate each hex group</em>
+<a class="jxr_linenumber" name="L8038" href="#L8038">8038</a> 		<strong class="jxr_keyword">var</strong> groups = ip.split(<span class="jxr_string">"::"</span>);
+<a class="jxr_linenumber" name="L8039" href="#L8039">8039</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> groupSection : groups) {
+<a class="jxr_linenumber" name="L8040" href="#L8040">8040</a> 			<strong class="jxr_keyword">if</strong> (groupSection.isEmpty())
+<a class="jxr_linenumber" name="L8041" href="#L8041">8041</a> 				<strong class="jxr_keyword">continue</strong>; <em class="jxr_comment">// Skip empty section from ::</em>
+<a class="jxr_linenumber" name="L8042" href="#L8042">8042</a> 			<strong class="jxr_keyword">var</strong> groupParts = groupSection.split(<span class="jxr_string">":"</span>);
+<a class="jxr_linenumber" name="L8043" href="#L8043">8043</a> 			<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> group : groupParts) {
+<a class="jxr_linenumber" name="L8044" href="#L8044">8044</a> 				<strong class="jxr_keyword">if</strong> (group.length() &gt; 4)
+<a class="jxr_linenumber" name="L8045" href="#L8045">8045</a> 					<strong class="jxr_keyword">return</strong> false; <em class="jxr_comment">// Each group is max 4 hex digits</em>
+<a class="jxr_linenumber" name="L8046" href="#L8046">8046</a> 				<em class="jxr_comment">// Validate hex digits</em>
+<a class="jxr_linenumber" name="L8047" href="#L8047">8047</a> 				<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; group.length(); i++) {
+<a class="jxr_linenumber" name="L8048" href="#L8048">8048</a> 					<strong class="jxr_keyword">var</strong> c = group.charAt(i);
+<a class="jxr_linenumber" name="L8049" href="#L8049">8049</a> 					<strong class="jxr_keyword">if</strong> (! HEXADECIMAL_CHARS.contains(c))
+<a class="jxr_linenumber" name="L8050" href="#L8050">8050</a> 						<strong class="jxr_keyword">return</strong> false;
+<a class="jxr_linenumber" name="L8051" href="#L8051">8051</a> 				}
+<a class="jxr_linenumber" name="L8052" href="#L8052">8052</a> 			}
+<a class="jxr_linenumber" name="L8053" href="#L8053">8053</a> 		}
+<a class="jxr_linenumber" name="L8054" href="#L8054">8054</a> 
+<a class="jxr_linenumber" name="L8055" href="#L8055">8055</a> 		<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">true</strong>;
+<a class="jxr_linenumber" name="L8056" href="#L8056">8056</a> 	}
 <a class="jxr_linenumber" name="L8057" href="#L8057">8057</a> 
-<a class="jxr_linenumber" name="L8058" href="#L8058">8058</a> 		<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">true</strong>;
-<a class="jxr_linenumber" name="L8059" href="#L8059">8059</a> 	}
-<a class="jxr_linenumber" name="L8060" href="#L8060">8060</a> 
-<a class="jxr_linenumber" name="L8061" href="#L8061">8061</a> 
-<a class="jxr_linenumber" name="L8062" href="#L8062">8062</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">class</strong> Readifier {
-<a class="jxr_linenumber" name="L8063" href="#L8063">8063</a> 		<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">final</strong> Class&lt;?&gt; type;
-<a class="jxr_linenumber" name="L8064" href="#L8064">8064</a> 		<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">final</strong> Function&lt;Object,String&gt; bridge;
-<a class="jxr_linenumber" name="L8065" href="#L8065">8065</a> 
-<a class="jxr_linenumber" name="L8066" href="#L8066">8066</a> 		<strong class="jxr_keyword">private</strong> &lt;T&gt; Readifier(Class&lt;T&gt; type, Function&lt;? <strong class="jxr_keyword">super</strong> T,String&gt; converter) {
-<a class="jxr_linenumber" name="L8067" href="#L8067">8067</a> 			<strong class="jxr_keyword">this</strong>.type = type;
-<a class="jxr_linenumber" name="L8068" href="#L8068">8068</a> 			<strong class="jxr_keyword">this</strong>.bridge = o -&gt; converter.apply(type.<strong class="jxr_keyword">cast</strong>(o));
-<a class="jxr_linenumber" name="L8069" href="#L8069">8069</a> 		}
-<a class="jxr_linenumber" name="L8070" href="#L8070">8070</a> 
-<a class="jxr_linenumber" name="L8071" href="#L8071">8071</a> 		Class&lt;?&gt; forClass() {
-<a class="jxr_linenumber" name="L8072" href="#L8072">8072</a> 			<strong class="jxr_keyword">return</strong> type;
-<a class="jxr_linenumber" name="L8073" href="#L8073">8073</a> 		}
-<a class="jxr_linenumber" name="L8074" href="#L8074">8074</a> 
-<a class="jxr_linenumber" name="L8075" href="#L8075">8075</a> 		Function&lt;Object,String&gt; toFunction() {
-<a class="jxr_linenumber" name="L8076" href="#L8076">8076</a> 			<strong class="jxr_keyword">return</strong> bridge;
-<a class="jxr_linenumber" name="L8077" href="#L8077">8077</a> 		}
-<a class="jxr_linenumber" name="L8078" href="#L8078">8078</a> 	}
-<a class="jxr_linenumber" name="L8079" href="#L8079">8079</a> 
-<a class="jxr_linenumber" name="L8080" href="#L8080">8080</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> &lt;T&gt; Readifier readifier(Class&lt;T&gt; type, Function&lt;? <strong class="jxr_keyword">super</strong> T,String&gt; converter) {
-<a class="jxr_linenumber" name="L8081" href="#L8081">8081</a> 		<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">new</strong> Readifier(type, converter);
-<a class="jxr_linenumber" name="L8082" href="#L8082">8082</a> 	}
+<a class="jxr_linenumber" name="L8058" href="#L8058">8058</a> 
+<a class="jxr_linenumber" name="L8059" href="#L8059">8059</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">class</strong> Readifier {
+<a class="jxr_linenumber" name="L8060" href="#L8060">8060</a> 		<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">final</strong> Class&lt;?&gt; type;
+<a class="jxr_linenumber" name="L8061" href="#L8061">8061</a> 		<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">final</strong> Function&lt;Object,String&gt; bridge;
+<a class="jxr_linenumber" name="L8062" href="#L8062">8062</a> 
+<a class="jxr_linenumber" name="L8063" href="#L8063">8063</a> 		<strong class="jxr_keyword">private</strong> &lt;T&gt; Readifier(Class&lt;T&gt; type, Function&lt;? <strong class="jxr_keyword">super</strong> T,String&gt; converter) {
+<a class="jxr_linenumber" name="L8064" href="#L8064">8064</a> 			<strong class="jxr_keyword">this</strong>.type = type;
+<a class="jxr_linenumber" name="L8065" href="#L8065">8065</a> 			<strong class="jxr_keyword">this</strong>.bridge = o -&gt; converter.apply(type.<strong class="jxr_keyword">cast</strong>(o));
+<a class="jxr_linenumber" name="L8066" href="#L8066">8066</a> 		}
+<a class="jxr_linenumber" name="L8067" href="#L8067">8067</a> 
+<a class="jxr_linenumber" name="L8068" href="#L8068">8068</a> 		Class&lt;?&gt; forClass() {
+<a class="jxr_linenumber" name="L8069" href="#L8069">8069</a> 			<strong class="jxr_keyword">return</strong> type;
+<a class="jxr_linenumber" name="L8070" href="#L8070">8070</a> 		}
+<a class="jxr_linenumber" name="L8071" href="#L8071">8071</a> 
+<a class="jxr_linenumber" name="L8072" href="#L8072">8072</a> 		Function&lt;Object,String&gt; toFunction() {
+<a class="jxr_linenumber" name="L8073" href="#L8073">8073</a> 			<strong class="jxr_keyword">return</strong> bridge;
+<a class="jxr_linenumber" name="L8074" href="#L8074">8074</a> 		}
+<a class="jxr_linenumber" name="L8075" href="#L8075">8075</a> 	}
+<a class="jxr_linenumber" name="L8076" href="#L8076">8076</a> 
+<a class="jxr_linenumber" name="L8077" href="#L8077">8077</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> &lt;T&gt; Readifier readifier(Class&lt;T&gt; type, Function&lt;? <strong class="jxr_keyword">super</strong> T,String&gt; converter) {
+<a class="jxr_linenumber" name="L8078" href="#L8078">8078</a> 		<strong class="jxr_keyword">return</strong> <strong class="jxr_keyword">new</strong> Readifier(type, converter);
+<a class="jxr_linenumber" name="L8079" href="#L8079">8079</a> 	}
+<a class="jxr_linenumber" name="L8080" href="#L8080">8080</a> 
+<a class="jxr_linenumber" name="L8081" href="#L8081">8081</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> List&lt;Readifier&gt; loadReadifiers() {
+<a class="jxr_linenumber" name="L8082" href="#L8082">8082</a> 		<strong class="jxr_keyword">var</strong> list = <strong class="jxr_keyword">new</strong> ArrayList&lt;Readifier&gt;();
 <a class="jxr_linenumber" name="L8083" href="#L8083">8083</a> 
-<a class="jxr_linenumber" name="L8084" href="#L8084">8084</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> List&lt;Readifier&gt; loadReadifiers() {
-<a class="jxr_linenumber" name="L8085" href="#L8085">8085</a> 		<strong class="jxr_keyword">var</strong> list = <strong class="jxr_keyword">new</strong> ArrayList&lt;Readifier&gt;();
-<a class="jxr_linenumber" name="L8086" href="#L8086">8086</a> 
-<a class="jxr_linenumber" name="L8087" href="#L8087">8087</a> 		<em class="jxr_comment">// More specific types first - order matters!</em>
-<a class="jxr_linenumber" name="L8088" href="#L8088">8088</a> 		list.add(readifier(Map.Entry.<strong class="jxr_keyword">class</strong>, x -&gt; readable(x.getKey()) + '=' + readable(x.getValue())));
-<a class="jxr_linenumber" name="L8089" href="#L8089">8089</a> 		list.add(readifier(Collection.<strong class="jxr_keyword">class</strong>, x -&gt; ((Collection&lt;?&gt;)x).stream().map(StringUtils::readable).collect(joining(<span class="jxr_string">","</span>, <span class="jxr_string">"["</span>, <span class="jxr_string">"]"</span>))));
-<a class="jxr_linenumber" name="L8090" href="#L8090">8090</a> 		list.add(readifier(Map.<strong class="jxr_keyword">class</strong>, x -&gt; ((Map&lt;?,?&gt;)x).entrySet().stream().map(StringUtils::readable).collect(joining(<span class="jxr_string">","</span>, <span class="jxr_string">"{"</span>, <span class="jxr_string">"}"</span>))));
-<a class="jxr_linenumber" name="L8091" href="#L8091">8091</a> 		list.add(readifier(Iterable.<strong class="jxr_keyword">class</strong>, x -&gt; readable(toList(x))));
-<a class="jxr_linenumber" name="L8092" href="#L8092">8092</a> 		list.add(readifier(Iterator.<strong class="jxr_keyword">class</strong>, x -&gt; readable(toList(x))));
-<a class="jxr_linenumber" name="L8093" href="#L8093">8093</a> 		list.add(readifier(Enumeration.<strong class="jxr_keyword">class</strong>, x -&gt; readable(toList(x))));
-<a class="jxr_linenumber" name="L8094" href="#L8094">8094</a> 		list.add(readifier(Optional.<strong class="jxr_keyword">class</strong>, x -&gt; readable(((Optional&lt;?&gt;)x).orElse(<strong class="jxr_keyword">null</strong>))));
-<a class="jxr_linenumber" name="L8095" href="#L8095">8095</a> 		list.add(readifier(GregorianCalendar.<strong class="jxr_keyword">class</strong>, x -&gt; x.toZonedDateTime().format(DateTimeFormatter.ISO_INSTANT)));
-<a class="jxr_linenumber" name="L8096" href="#L8096">8096</a> 		list.add(readifier(Date.<strong class="jxr_keyword">class</strong>, x -&gt; x.toInstant().toString()));
-<a class="jxr_linenumber" name="L8097" href="#L8097">8097</a> 		list.add(readifier(InputStream.<strong class="jxr_keyword">class</strong>, x -&gt; toHex(x)));
-<a class="jxr_linenumber" name="L8098" href="#L8098">8098</a> 		list.add(readifier(Reader.<strong class="jxr_keyword">class</strong>, (Reader x) -&gt; safe(() -&gt; read(x))));
-<a class="jxr_linenumber" name="L8099" href="#L8099">8099</a> 		list.add(readifier(File.<strong class="jxr_keyword">class</strong>, (File x) -&gt; safe(() -&gt; read(x))));
-<a class="jxr_linenumber" name="L8100" href="#L8100">8100</a> 		list.add(readifier(byte[].<strong class="jxr_keyword">class</strong>, x -&gt; toHex(x)));
-<a class="jxr_linenumber" name="L8101" href="#L8101">8101</a> 		list.add(readifier(Enum.<strong class="jxr_keyword">class</strong>, x -&gt; ((Enum&lt;?&gt;)x).name()));
-<a class="jxr_linenumber" name="L8102" href="#L8102">8102</a> 		list.add(readifier(Class.<strong class="jxr_keyword">class</strong>, x -&gt; cns(x)));
-<a class="jxr_linenumber" name="L8103" href="#L8103">8103</a> 		list.add(readifier(Constructor.<strong class="jxr_keyword">class</strong>, x -&gt; ConstructorInfo.of(x).getFullName()));
-<a class="jxr_linenumber" name="L8104" href="#L8104">8104</a> 		list.add(readifier(Method.<strong class="jxr_keyword">class</strong>, x -&gt; MethodInfo.of(x).getFullName()));
-<a class="jxr_linenumber" name="L8105" href="#L8105">8105</a> 		list.add(readifier(Field.<strong class="jxr_keyword">class</strong>, x -&gt; FieldInfo.of(x).toString()));
-<a class="jxr_linenumber" name="L8106" href="#L8106">8106</a> 		list.add(readifier(Parameter.<strong class="jxr_keyword">class</strong>, x -&gt; ParameterInfo.of(x).toString()));
-<a class="jxr_linenumber" name="L8107" href="#L8107">8107</a> 		list.add(readifier(ClassInfo.<strong class="jxr_keyword">class</strong>, ClassInfo::toString));
-<a class="jxr_linenumber" name="L8108" href="#L8108">8108</a> 		list.add(readifier(MethodInfo.<strong class="jxr_keyword">class</strong>, MethodInfo::toString));
-<a class="jxr_linenumber" name="L8109" href="#L8109">8109</a> 		list.add(readifier(ConstructorInfo.<strong class="jxr_keyword">class</strong>, ConstructorInfo::toString));
-<a class="jxr_linenumber" name="L8110" href="#L8110">8110</a> 		list.add(readifier(FieldInfo.<strong class="jxr_keyword">class</strong>, FieldInfo::toString));
-<a class="jxr_linenumber" name="L8111" href="#L8111">8111</a> 		list.add(readifier(ParameterInfo.<strong class="jxr_keyword">class</strong>, ParameterInfo::toString));
+<a class="jxr_linenumber" name="L8084" href="#L8084">8084</a> 		<em class="jxr_comment">// More specific types first - order matters!</em>
+<a class="jxr_linenumber" name="L8085" href="#L8085">8085</a> 		list.add(readifier(Map.Entry.<strong class="jxr_keyword">class</strong>, x -&gt; readable(x.getKey()) + '=' + readable(x.getValue())));
+<a class="jxr_linenumber" name="L8086" href="#L8086">8086</a> 		list.add(readifier(Collection.<strong class="jxr_keyword">class</strong>, x -&gt; ((Collection&lt;?&gt;)x).stream().map(StringUtils::readable).collect(joining(<span class="jxr_string">","</span>, <span class="jxr_string">"["</span>, <span class="jxr_string">"]"</span>))));
+<a class="jxr_linenumber" name="L8087" href="#L8087">8087</a> 		list.add(readifier(Map.<strong class="jxr_keyword">class</strong>, x -&gt; ((Map&lt;?,?&gt;)x).entrySet().stream().map(StringUtils::readable).collect(joining(<span class="jxr_string">","</span>, <span class="jxr_string">"{"</span>, <span class="jxr_string">"}"</span>))));
+<a class="jxr_linenumber" name="L8088" href="#L8088">8088</a> 		list.add(readifier(Iterable.<strong class="jxr_keyword">class</strong>, x -&gt; readable(toList(x))));
+<a class="jxr_linenumber" name="L8089" href="#L8089">8089</a> 		list.add(readifier(Iterator.<strong class="jxr_keyword">class</strong>, x -&gt; readable(toList(x))));
+<a class="jxr_linenumber" name="L8090" href="#L8090">8090</a> 		list.add(readifier(Enumeration.<strong class="jxr_keyword">class</strong>, x -&gt; readable(toList(x))));
+<a class="jxr_linenumber" name="L8091" href="#L8091">8091</a> 		list.add(readifier(Optional.<strong class="jxr_keyword">class</strong>, x -&gt; readable(((Optional&lt;?&gt;)x).orElse(<strong class="jxr_keyword">null</strong>))));
+<a class="jxr_linenumber" name="L8092" href="#L8092">8092</a> 		list.add(readifier(GregorianCalendar.<strong class="jxr_keyword">class</strong>, x -&gt; x.toZonedDateTime().format(DateTimeFormatter.ISO_INSTANT)));
+<a class="jxr_linenumber" name="L8093" href="#L8093">8093</a> 		list.add(readifier(Date.<strong class="jxr_keyword">class</strong>, x -&gt; x.toInstant().toString()));
+<a class="jxr_linenumber" name="L8094" href="#L8094">8094</a> 		list.add(readifier(InputStream.<strong class="jxr_keyword">class</strong>, x -&gt; toHex(x)));
+<a class="jxr_linenumber" name="L8095" href="#L8095">8095</a> 		list.add(readifier(Reader.<strong class="jxr_keyword">class</strong>, (Reader x) -&gt; safe(() -&gt; read(x))));
+<a class="jxr_linenumber" name="L8096" href="#L8096">8096</a> 		list.add(readifier(File.<strong class="jxr_keyword">class</strong>, (File x) -&gt; safe(() -&gt; read(x))));
+<a class="jxr_linenumber" name="L8097" href="#L8097">8097</a> 		list.add(readifier(byte[].<strong class="jxr_keyword">class</strong>, x -&gt; toHex(x)));
+<a class="jxr_linenumber" name="L8098" href="#L8098">8098</a> 		list.add(readifier(Enum.<strong class="jxr_keyword">class</strong>, x -&gt; ((Enum&lt;?&gt;)x).name()));
+<a class="jxr_linenumber" name="L8099" href="#L8099">8099</a> 		list.add(readifier(Class.<strong class="jxr_keyword">class</strong>, x -&gt; cns(x)));
+<a class="jxr_linenumber" name="L8100" href="#L8100">8100</a> 		list.add(readifier(Constructor.<strong class="jxr_keyword">class</strong>, x -&gt; ConstructorInfo.of(x).getFullName()));
+<a class="jxr_linenumber" name="L8101" href="#L8101">8101</a> 		list.add(readifier(Method.<strong class="jxr_keyword">class</strong>, x -&gt; MethodInfo.of(x).getFullName()));
+<a class="jxr_linenumber" name="L8102" href="#L8102">8102</a> 		list.add(readifier(Field.<strong class="jxr_keyword">class</strong>, x -&gt; FieldInfo.of(x).toString()));
+<a class="jxr_linenumber" name="L8103" href="#L8103">8103</a> 		list.add(readifier(Parameter.<strong class="jxr_keyword">class</strong>, x -&gt; ParameterInfo.of(x).toString()));
+<a class="jxr_linenumber" name="L8104" href="#L8104">8104</a> 		list.add(readifier(ClassInfo.<strong class="jxr_keyword">class</strong>, ClassInfo::toString));
+<a class="jxr_linenumber" name="L8105" href="#L8105">8105</a> 		list.add(readifier(MethodInfo.<strong class="jxr_keyword">class</strong>, MethodInfo::toString));
+<a class="jxr_linenumber" name="L8106" href="#L8106">8106</a> 		list.add(readifier(ConstructorInfo.<strong class="jxr_keyword">class</strong>, ConstructorInfo::toString));
+<a class="jxr_linenumber" name="L8107" href="#L8107">8107</a> 		list.add(readifier(FieldInfo.<strong class="jxr_keyword">class</strong>, FieldInfo::toString));
+<a class="jxr_linenumber" name="L8108" href="#L8108">8108</a> 		list.add(readifier(ParameterInfo.<strong class="jxr_keyword">class</strong>, ParameterInfo::toString));
+<a class="jxr_linenumber" name="L8109" href="#L8109">8109</a> 
+<a class="jxr_linenumber" name="L8110" href="#L8110">8110</a> 		<strong class="jxr_keyword">return</strong> Collections.unmodifiableList(list);
+<a class="jxr_linenumber" name="L8111" href="#L8111">8111</a> 	}
 <a class="jxr_linenumber" name="L8112" href="#L8112">8112</a> 
-<a class="jxr_linenumber" name="L8113" href="#L8113">8113</a> 		<strong class="jxr_keyword">return</strong> Collections.unmodifiableList(list);
-<a class="jxr_linenumber" name="L8114" href="#L8114">8114</a> 	}
-<a class="jxr_linenumber" name="L8115" href="#L8115">8115</a> 
-<a class="jxr_linenumber" name="L8116" href="#L8116">8116</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L8117" href="#L8117">8117</a> <em class="jxr_javadoccomment">	 * Determines the multiplier value based on the suffix character in a string.</em>
-<a class="jxr_linenumber" name="L8118" href="#L8118">8118</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L8119" href="#L8119">8119</a> <em class="jxr_javadoccomment">	 * @param s The string to analyze for multiplier suffix.</em>
-<a class="jxr_linenumber" name="L8120" href="#L8120">8120</a> <em class="jxr_javadoccomment">	 * @return The multiplier value (1 if no valid suffix found).</em>
-<a class="jxr_linenumber" name="L8121" href="#L8121">8121</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L8122" href="#L8122">8122</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">int</strong> multiplierInt(String s) {
-<a class="jxr_linenumber" name="L8123" href="#L8123">8123</a> 		<strong class="jxr_keyword">var</strong> c = isEmpty(s) ? 'z' : s.charAt(s.length() - 1);
-<a class="jxr_linenumber" name="L8124" href="#L8124">8124</a> 		<strong class="jxr_keyword">if</strong> (c == 'G')
-<a class="jxr_linenumber" name="L8125" href="#L8125">8125</a> 			<strong class="jxr_keyword">return</strong> 1024 * 1024 * 1024;
-<a class="jxr_linenumber" name="L8126" href="#L8126">8126</a> 		<strong class="jxr_keyword">if</strong> (c == 'M')
-<a class="jxr_linenumber" name="L8127" href="#L8127">8127</a> 			<strong class="jxr_keyword">return</strong> 1024 * 1024;
-<a class="jxr_linenumber" name="L8128" href="#L8128">8128</a> 		<strong class="jxr_keyword">if</strong> (c == 'K')
-<a class="jxr_linenumber" name="L8129" href="#L8129">8129</a> 			<strong class="jxr_keyword">return</strong> 1024;
-<a class="jxr_linenumber" name="L8130" href="#L8130">8130</a> 		<strong class="jxr_keyword">if</strong> (c == 'g')
-<a class="jxr_linenumber" name="L8131" href="#L8131">8131</a> 			<strong class="jxr_keyword">return</strong> 1000 * 1000 * 1000;
-<a class="jxr_linenumber" name="L8132" href="#L8132">8132</a> 		<strong class="jxr_keyword">if</strong> (c == 'm')
-<a class="jxr_linenumber" name="L8133" href="#L8133">8133</a> 			<strong class="jxr_keyword">return</strong> 1000 * 1000;
-<a class="jxr_linenumber" name="L8134" href="#L8134">8134</a> 		<strong class="jxr_keyword">if</strong> (c == 'k')
-<a class="jxr_linenumber" name="L8135" href="#L8135">8135</a> 			<strong class="jxr_keyword">return</strong> 1000;
-<a class="jxr_linenumber" name="L8136" href="#L8136">8136</a> 		<strong class="jxr_keyword">return</strong> 1;
-<a class="jxr_linenumber" name="L8137" href="#L8137">8137</a> 	}
-<a class="jxr_linenumber" name="L8138" href="#L8138">8138</a> 
-<a class="jxr_linenumber" name="L8139" href="#L8139">8139</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L8140" href="#L8140">8140</a> <em class="jxr_javadoccomment">	 * Determines the long multiplier value based on the suffix character in a string.</em>
-<a class="jxr_linenumber" name="L8141" href="#L8141">8141</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L8142" href="#L8142">8142</a> <em class="jxr_javadoccomment">	 * @param s The string to analyze for multiplier suffix.</em>
-<a class="jxr_linenumber" name="L8143" href="#L8143">8143</a> <em class="jxr_javadoccomment">	 * @return The multiplier value (1 if no valid suffix found).</em>
-<a class="jxr_linenumber" name="L8144" href="#L8144">8144</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L8145" href="#L8145">8145</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">long</strong> multiplierLong(String s) {
-<a class="jxr_linenumber" name="L8146" href="#L8146">8146</a> 		<strong class="jxr_keyword">if</strong> (isEmpty(s))
-<a class="jxr_linenumber" name="L8147" href="#L8147">8147</a> 			<strong class="jxr_keyword">return</strong> 1;
-<a class="jxr_linenumber" name="L8148" href="#L8148">8148</a> 		<strong class="jxr_keyword">var</strong> c = s.charAt(s.length() - 1);
-<a class="jxr_linenumber" name="L8149" href="#L8149">8149</a> 		<strong class="jxr_keyword">if</strong> (c == 'P')
-<a class="jxr_linenumber" name="L8150" href="#L8150">8150</a> 			<strong class="jxr_keyword">return</strong> 1125899906842624L;  <em class="jxr_comment">// 1024^5</em>
-<a class="jxr_linenumber" name="L8151" href="#L8151">8151</a> 		<strong class="jxr_keyword">if</strong> (c == 'T')
-<a class="jxr_linenumber" name="L8152" href="#L8152">8152</a> 			<strong class="jxr_keyword">return</strong> 1099511627776L;  <em class="jxr_comment">// 1024^4</em>
-<a class="jxr_linenumber" name="L8153" href="#L8153">8153</a> 		<strong class="jxr_keyword">if</strong> (c == 'G')
-<a class="jxr_linenumber" name="L8154" href="#L8154">8154</a> 			<strong class="jxr_keyword">return</strong> 1073741824L;  <em class="jxr_comment">// 1024^3</em>
-<a class="jxr_linenumber" name="L8155" href="#L8155">8155</a> 		<strong class="jxr_keyword">if</strong> (c == 'M')
-<a class="jxr_linenumber" name="L8156" href="#L8156">8156</a> 			<strong class="jxr_keyword">return</strong> 1048576L;  <em class="jxr_comment">// 1024^2</em>
-<a class="jxr_linenumber" name="L8157" href="#L8157">8157</a> 		<strong class="jxr_keyword">if</strong> (c == 'K')
-<a class="jxr_linenumber" name="L8158" href="#L8158">8158</a> 			<strong class="jxr_keyword">return</strong> 1024L;
-<a class="jxr_linenumber" name="L8159" href="#L8159">8159</a> 		<strong class="jxr_keyword">if</strong> (c == 'p')
-<a class="jxr_linenumber" name="L8160" href="#L8160">8160</a> 			<strong class="jxr_keyword">return</strong> 1000000000000000L;  <em class="jxr_comment">// 1000^5</em>
-<a class="jxr_linenumber" name="L8161" href="#L8161">8161</a> 		<strong class="jxr_keyword">if</strong> (c == 't')
-<a class="jxr_linenumber" name="L8162" href="#L8162">8162</a> 			<strong class="jxr_keyword">return</strong> 1000000000000L;  <em class="jxr_comment">// 1000^4</em>
-<a class="jxr_linenumber" name="L8163" href="#L8163">8163</a> 		<strong class="jxr_keyword">if</strong> (c == 'g')
-<a class="jxr_linenumber" name="L8164" href="#L8164">8164</a> 			<strong class="jxr_keyword">return</strong> 1000000000L;  <em class="jxr_comment">// 1000^3</em>
-<a class="jxr_linenumber" name="L8165" href="#L8165">8165</a> 		<strong class="jxr_keyword">if</strong> (c == 'm')
-<a class="jxr_linenumber" name="L8166" href="#L8166">8166</a> 			<strong class="jxr_keyword">return</strong> 1000000L;  <em class="jxr_comment">// 1000^2</em>
-<a class="jxr_linenumber" name="L8167" href="#L8167">8167</a> 		<strong class="jxr_keyword">if</strong> (c == 'k')
-<a class="jxr_linenumber" name="L8168" href="#L8168">8168</a> 			<strong class="jxr_keyword">return</strong> 1000L;
-<a class="jxr_linenumber" name="L8169" href="#L8169">8169</a> 		<strong class="jxr_keyword">return</strong> 1;
-<a class="jxr_linenumber" name="L8170" href="#L8170">8170</a> 	}
-<a class="jxr_linenumber" name="L8171" href="#L8171">8171</a> 
-<a class="jxr_linenumber" name="L8172" href="#L8172">8172</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L8173" href="#L8173">8173</a> <em class="jxr_javadoccomment">	 * Parses a unit string and converts the value to milliseconds.</em>
-<a class="jxr_linenumber" name="L8174" href="#L8174">8174</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L8175" href="#L8175">8175</a> <em class="jxr_javadoccomment">	 * @param unit The unit string (case-insensitive, already lowercased).</em>
-<a class="jxr_linenumber" name="L8176" href="#L8176">8176</a> <em class="jxr_javadoccomment">	 * @param value The numeric value.</em>
-<a class="jxr_linenumber" name="L8177" href="#L8177">8177</a> <em class="jxr_javadoccomment">	 * @return The value in milliseconds, or &lt;c&gt;-1&lt;/c&gt; if the unit is invalid.</em>
-<a class="jxr_linenumber" name="L8178" href="#L8178">8178</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L8179" href="#L8179">8179</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">long</strong> parseUnit(String unit, <strong class="jxr_keyword">double</strong> value) {
-<a class="jxr_linenumber" name="L8180" href="#L8180">8180</a> 		<strong class="jxr_keyword">if</strong> (isEmpty(unit)) {
-<a class="jxr_linenumber" name="L8181" href="#L8181">8181</a> 			<em class="jxr_comment">// No unit means milliseconds</em>
-<a class="jxr_linenumber" name="L8182" href="#L8182">8182</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)value;
-<a class="jxr_linenumber" name="L8183" href="#L8183">8183</a> 		}
-<a class="jxr_linenumber" name="L8184" href="#L8184">8184</a> 
-<a class="jxr_linenumber" name="L8185" href="#L8185">8185</a> 		<em class="jxr_comment">// Check milliseconds first (before minutes) - must check exact "ms" before checking "m"</em>
-<a class="jxr_linenumber" name="L8186" href="#L8186">8186</a> 		<strong class="jxr_keyword">if</strong> (unit.equals(<span class="jxr_string">"ms"</span>) || unit.equals(<span class="jxr_string">"millis"</span>) || unit.equals(<span class="jxr_string">"milliseconds"</span>))
-<a class="jxr_linenumber" name="L8187" href="#L8187">8187</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)value;
-<a class="jxr_linenumber" name="L8188" href="#L8188">8188</a> 
-<a class="jxr_linenumber" name="L8189" href="#L8189">8189</a> 		<em class="jxr_comment">// Seconds</em>
-<a class="jxr_linenumber" name="L8190" href="#L8190">8190</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"s"</span>) &amp;&amp; !unit.startsWith(<span class="jxr_string">"sec"</span>))
-<a class="jxr_linenumber" name="L8191" href="#L8191">8191</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000);
-<a class="jxr_linenumber" name="L8192" href="#L8192">8192</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"sec"</span>) || unit.startsWith(<span class="jxr_string">"second"</span>))
-<a class="jxr_linenumber" name="L8193" href="#L8193">8193</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000);
-<a class="jxr_linenumber" name="L8194" href="#L8194">8194</a> 
-<a class="jxr_linenumber" name="L8195" href="#L8195">8195</a> 		<em class="jxr_comment">// Minutes (must check after milliseconds and months)</em>
-<a class="jxr_linenumber" name="L8196" href="#L8196">8196</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"m"</span>) &amp;&amp; !unit.startsWith(<span class="jxr_string">"mo"</span>) &amp;&amp; !unit.startsWith(<span class="jxr_string">"mill"</span>) &amp;&amp; !unit.startsWith(<span class="jxr_string">"ms"</span>))
-<a class="jxr_linenumber" name="L8197" href="#L8197">8197</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60);
-<a class="jxr_linenumber" name="L8198" href="#L8198">8198</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"min"</span>) || unit.startsWith(<span class="jxr_string">"minute"</span>))
-<a class="jxr_linenumber" name="L8199" href="#L8199">8199</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60);
-<a class="jxr_linenumber" name="L8200" href="#L8200">8200</a> 
-<a class="jxr_linenumber" name="L8201" href="#L8201">8201</a> 		<em class="jxr_comment">// Hours</em>
-<a class="jxr_linenumber" name="L8202" href="#L8202">8202</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"h"</span>) || unit.startsWith(<span class="jxr_string">"hour"</span>))
-<a class="jxr_linenumber" name="L8203" href="#L8203">8203</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60);
-<a class="jxr_linenumber" name="L8204" href="#L8204">8204</a> 
-<a class="jxr_linenumber" name="L8205" href="#L8205">8205</a> 		<em class="jxr_comment">// Days</em>
-<a class="jxr_linenumber" name="L8206" href="#L8206">8206</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"d"</span>) &amp;&amp; !unit.startsWith(<span class="jxr_string">"da"</span>))
-<a class="jxr_linenumber" name="L8207" href="#L8207">8207</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60 * 24);
-<a class="jxr_linenumber" name="L8208" href="#L8208">8208</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"day"</span>))
-<a class="jxr_linenumber" name="L8209" href="#L8209">8209</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60 * 24);
-<a class="jxr_linenumber" name="L8210" href="#L8210">8210</a> 
-<a class="jxr_linenumber" name="L8211" href="#L8211">8211</a> 		<em class="jxr_comment">// Weeks</em>
-<a class="jxr_linenumber" name="L8212" href="#L8212">8212</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"w"</span>) || unit.startsWith(<span class="jxr_string">"week"</span>))
-<a class="jxr_linenumber" name="L8213" href="#L8213">8213</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60 * 24 * 7);
-<a class="jxr_linenumber" name="L8214" href="#L8214">8214</a> 
-<a class="jxr_linenumber" name="L8215" href="#L8215">8215</a> 		<em class="jxr_comment">// Months (30 days)</em>
-<a class="jxr_linenumber" name="L8216" href="#L8216">8216</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"mo"</span>) || unit.startsWith(<span class="jxr_string">"month"</span>))
-<a class="jxr_linenumber" name="L8217" href="#L8217">8217</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60 * 24 * 30);
-<a class="jxr_linenumber" name="L8218" href="#L8218">8218</a> 
-<a class="jxr_linenumber" name="L8219" href="#L8219">8219</a> 		<em class="jxr_comment">// Years (365 days)</em>
-<a class="jxr_linenumber" name="L8220" href="#L8220">8220</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"y"</span>) &amp;&amp; !unit.startsWith(<span class="jxr_string">"yr"</span>))
-<a class="jxr_linenumber" name="L8221" href="#L8221">8221</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60 * 24 * 365);
-<a class="jxr_linenumber" name="L8222" href="#L8222">8222</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"yr"</span>) || unit.startsWith(<span class="jxr_string">"year"</span>))
-<a class="jxr_linenumber" name="L8223" href="#L8223">8223</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60 * 24 * 365);
-<a class="jxr_linenumber" name="L8224" href="#L8224">8224</a> 
-<a class="jxr_linenumber" name="L8225" href="#L8225">8225</a> 		<em class="jxr_comment">// Unknown unit</em>
-<a class="jxr_linenumber" name="L8226" href="#L8226">8226</a> 		<strong class="jxr_keyword">return</strong> -1;
-<a class="jxr_linenumber" name="L8227" href="#L8227">8227</a> 	}
-<a class="jxr_linenumber" name="L8228" href="#L8228">8228</a> 
-<a class="jxr_linenumber" name="L8229" href="#L8229">8229</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L8230" href="#L8230">8230</a> <em class="jxr_javadoccomment">	 * Skips over a single comment sequence in a StringReader.</em>
-<a class="jxr_linenumber" name="L8231" href="#L8231">8231</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L8232" href="#L8232">8232</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
-<a class="jxr_linenumber" name="L8233" href="#L8233">8233</a> <em class="jxr_javadoccomment">	 * The reader must be positioned at the first &lt;js&gt;'/'&lt;/js&gt; character of a comment.</em>
-<a class="jxr_linenumber" name="L8234" href="#L8234">8234</a> <em class="jxr_javadoccomment">	 * This method will skip only the comment it's currently positioned on, not all comments in the reader.</em>
+<a class="jxr_linenumber" name="L8113" href="#L8113">8113</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L8114" href="#L8114">8114</a> <em class="jxr_javadoccomment">	 * Determines the multiplier value based on the suffix character in a string.</em>
+<a class="jxr_linenumber" name="L8115" href="#L8115">8115</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L8116" href="#L8116">8116</a> <em class="jxr_javadoccomment">	 * @param s The string to analyze for multiplier suffix.</em>
+<a class="jxr_linenumber" name="L8117" href="#L8117">8117</a> <em class="jxr_javadoccomment">	 * @return The multiplier value (1 if no valid suffix found).</em>
+<a class="jxr_linenumber" name="L8118" href="#L8118">8118</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L8119" href="#L8119">8119</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">int</strong> multiplierInt(String s) {
+<a class="jxr_linenumber" name="L8120" href="#L8120">8120</a> 		<strong class="jxr_keyword">var</strong> c = isEmpty(s) ? 'z' : s.charAt(s.length() - 1);
+<a class="jxr_linenumber" name="L8121" href="#L8121">8121</a> 		<strong class="jxr_keyword">if</strong> (c == 'G')
+<a class="jxr_linenumber" name="L8122" href="#L8122">8122</a> 			<strong class="jxr_keyword">return</strong> 1024 * 1024 * 1024;
+<a class="jxr_linenumber" name="L8123" href="#L8123">8123</a> 		<strong class="jxr_keyword">if</strong> (c == 'M')
+<a class="jxr_linenumber" name="L8124" href="#L8124">8124</a> 			<strong class="jxr_keyword">return</strong> 1024 * 1024;
+<a class="jxr_linenumber" name="L8125" href="#L8125">8125</a> 		<strong class="jxr_keyword">if</strong> (c == 'K')
+<a class="jxr_linenumber" name="L8126" href="#L8126">8126</a> 			<strong class="jxr_keyword">return</strong> 1024;
+<a class="jxr_linenumber" name="L8127" href="#L8127">8127</a> 		<strong class="jxr_keyword">if</strong> (c == 'g')
+<a class="jxr_linenumber" name="L8128" href="#L8128">8128</a> 			<strong class="jxr_keyword">return</strong> 1000 * 1000 * 1000;
+<a class="jxr_linenumber" name="L8129" href="#L8129">8129</a> 		<strong class="jxr_keyword">if</strong> (c == 'm')
+<a class="jxr_linenumber" name="L8130" href="#L8130">8130</a> 			<strong class="jxr_keyword">return</strong> 1000 * 1000;
+<a class="jxr_linenumber" name="L8131" href="#L8131">8131</a> 		<strong class="jxr_keyword">if</strong> (c == 'k')
+<a class="jxr_linenumber" name="L8132" href="#L8132">8132</a> 			<strong class="jxr_keyword">return</strong> 1000;
+<a class="jxr_linenumber" name="L8133" href="#L8133">8133</a> 		<strong class="jxr_keyword">return</strong> 1;
+<a class="jxr_linenumber" name="L8134" href="#L8134">8134</a> 	}
+<a class="jxr_linenumber" name="L8135" href="#L8135">8135</a> 
+<a class="jxr_linenumber" name="L8136" href="#L8136">8136</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L8137" href="#L8137">8137</a> <em class="jxr_javadoccomment">	 * Determines the long multiplier value based on the suffix character in a string.</em>
+<a class="jxr_linenumber" name="L8138" href="#L8138">8138</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L8139" href="#L8139">8139</a> <em class="jxr_javadoccomment">	 * @param s The string to analyze for multiplier suffix.</em>
+<a class="jxr_linenumber" name="L8140" href="#L8140">8140</a> <em class="jxr_javadoccomment">	 * @return The multiplier value (1 if no valid suffix found).</em>
+<a class="jxr_linenumber" name="L8141" href="#L8141">8141</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L8142" href="#L8142">8142</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">long</strong> multiplierLong(String s) {
+<a class="jxr_linenumber" name="L8143" href="#L8143">8143</a> 		<strong class="jxr_keyword">if</strong> (isEmpty(s))
+<a class="jxr_linenumber" name="L8144" href="#L8144">8144</a> 			<strong class="jxr_keyword">return</strong> 1;
+<a class="jxr_linenumber" name="L8145" href="#L8145">8145</a> 		<strong class="jxr_keyword">var</strong> c = s.charAt(s.length() - 1);
+<a class="jxr_linenumber" name="L8146" href="#L8146">8146</a> 		<strong class="jxr_keyword">if</strong> (c == 'P')
+<a class="jxr_linenumber" name="L8147" href="#L8147">8147</a> 			<strong class="jxr_keyword">return</strong> 1125899906842624L;  <em class="jxr_comment">// 1024^5</em>
+<a class="jxr_linenumber" name="L8148" href="#L8148">8148</a> 		<strong class="jxr_keyword">if</strong> (c == 'T')
+<a class="jxr_linenumber" name="L8149" href="#L8149">8149</a> 			<strong class="jxr_keyword">return</strong> 1099511627776L;  <em class="jxr_comment">// 1024^4</em>
+<a class="jxr_linenumber" name="L8150" href="#L8150">8150</a> 		<strong class="jxr_keyword">if</strong> (c == 'G')
+<a class="jxr_linenumber" name="L8151" href="#L8151">8151</a> 			<strong class="jxr_keyword">return</strong> 1073741824L;  <em class="jxr_comment">// 1024^3</em>
+<a class="jxr_linenumber" name="L8152" href="#L8152">8152</a> 		<strong class="jxr_keyword">if</strong> (c == 'M')
+<a class="jxr_linenumber" name="L8153" href="#L8153">8153</a> 			<strong class="jxr_keyword">return</strong> 1048576L;  <em class="jxr_comment">// 1024^2</em>
+<a class="jxr_linenumber" name="L8154" href="#L8154">8154</a> 		<strong class="jxr_keyword">if</strong> (c == 'K')
+<a class="jxr_linenumber" name="L8155" href="#L8155">8155</a> 			<strong class="jxr_keyword">return</strong> 1024L;
+<a class="jxr_linenumber" name="L8156" href="#L8156">8156</a> 		<strong class="jxr_keyword">if</strong> (c == 'p')
+<a class="jxr_linenumber" name="L8157" href="#L8157">8157</a> 			<strong class="jxr_keyword">return</strong> 1000000000000000L;  <em class="jxr_comment">// 1000^5</em>
+<a class="jxr_linenumber" name="L8158" href="#L8158">8158</a> 		<strong class="jxr_keyword">if</strong> (c == 't')
+<a class="jxr_linenumber" name="L8159" href="#L8159">8159</a> 			<strong class="jxr_keyword">return</strong> 1000000000000L;  <em class="jxr_comment">// 1000^4</em>
+<a class="jxr_linenumber" name="L8160" href="#L8160">8160</a> 		<strong class="jxr_keyword">if</strong> (c == 'g')
+<a class="jxr_linenumber" name="L8161" href="#L8161">8161</a> 			<strong class="jxr_keyword">return</strong> 1000000000L;  <em class="jxr_comment">// 1000^3</em>
+<a class="jxr_linenumber" name="L8162" href="#L8162">8162</a> 		<strong class="jxr_keyword">if</strong> (c == 'm')
+<a class="jxr_linenumber" name="L8163" href="#L8163">8163</a> 			<strong class="jxr_keyword">return</strong> 1000000L;  <em class="jxr_comment">// 1000^2</em>
+<a class="jxr_linenumber" name="L8164" href="#L8164">8164</a> 		<strong class="jxr_keyword">if</strong> (c == 'k')
+<a class="jxr_linenumber" name="L8165" href="#L8165">8165</a> 			<strong class="jxr_keyword">return</strong> 1000L;
+<a class="jxr_linenumber" name="L8166" href="#L8166">8166</a> 		<strong class="jxr_keyword">return</strong> 1;
+<a class="jxr_linenumber" name="L8167" href="#L8167">8167</a> 	}
+<a class="jxr_linenumber" name="L8168" href="#L8168">8168</a> 
+<a class="jxr_linenumber" name="L8169" href="#L8169">8169</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L8170" href="#L8170">8170</a> <em class="jxr_javadoccomment">	 * Parses a unit string and converts the value to milliseconds.</em>
+<a class="jxr_linenumber" name="L8171" href="#L8171">8171</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L8172" href="#L8172">8172</a> <em class="jxr_javadoccomment">	 * @param unit The unit string (case-insensitive, already lowercased).</em>
+<a class="jxr_linenumber" name="L8173" href="#L8173">8173</a> <em class="jxr_javadoccomment">	 * @param value The numeric value.</em>
+<a class="jxr_linenumber" name="L8174" href="#L8174">8174</a> <em class="jxr_javadoccomment">	 * @return The value in milliseconds, or &lt;c&gt;-1&lt;/c&gt; if the unit is invalid.</em>
+<a class="jxr_linenumber" name="L8175" href="#L8175">8175</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L8176" href="#L8176">8176</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">long</strong> parseUnit(String unit, <strong class="jxr_keyword">double</strong> value) {
+<a class="jxr_linenumber" name="L8177" href="#L8177">8177</a> 		<strong class="jxr_keyword">if</strong> (isEmpty(unit)) {
+<a class="jxr_linenumber" name="L8178" href="#L8178">8178</a> 			<em class="jxr_comment">// No unit means milliseconds</em>
+<a class="jxr_linenumber" name="L8179" href="#L8179">8179</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)value;
+<a class="jxr_linenumber" name="L8180" href="#L8180">8180</a> 		}
+<a class="jxr_linenumber" name="L8181" href="#L8181">8181</a> 
+<a class="jxr_linenumber" name="L8182" href="#L8182">8182</a> 		<em class="jxr_comment">// Check milliseconds first (before minutes) - must check exact "ms" before checking "m"</em>
+<a class="jxr_linenumber" name="L8183" href="#L8183">8183</a> 		<strong class="jxr_keyword">if</strong> (unit.equals(<span class="jxr_string">"ms"</span>) || unit.equals(<span class="jxr_string">"millis"</span>) || unit.equals(<span class="jxr_string">"milliseconds"</span>))
+<a class="jxr_linenumber" name="L8184" href="#L8184">8184</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)value;
+<a class="jxr_linenumber" name="L8185" href="#L8185">8185</a> 
+<a class="jxr_linenumber" name="L8186" href="#L8186">8186</a> 		<em class="jxr_comment">// Seconds</em>
+<a class="jxr_linenumber" name="L8187" href="#L8187">8187</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"s"</span>) &amp;&amp; !unit.startsWith(<span class="jxr_string">"sec"</span>))
+<a class="jxr_linenumber" name="L8188" href="#L8188">8188</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000);
+<a class="jxr_linenumber" name="L8189" href="#L8189">8189</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"sec"</span>) || unit.startsWith(<span class="jxr_string">"second"</span>))
+<a class="jxr_linenumber" name="L8190" href="#L8190">8190</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000);
+<a class="jxr_linenumber" name="L8191" href="#L8191">8191</a> 
+<a class="jxr_linenumber" name="L8192" href="#L8192">8192</a> 		<em class="jxr_comment">// Minutes (must check after milliseconds and months)</em>
+<a class="jxr_linenumber" name="L8193" href="#L8193">8193</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"m"</span>) &amp;&amp; !unit.startsWith(<span class="jxr_string">"mo"</span>) &amp;&amp; !unit.startsWith(<span class="jxr_string">"mill"</span>) &amp;&amp; !unit.startsWith(<span class="jxr_string">"ms"</span>))
+<a class="jxr_linenumber" name="L8194" href="#L8194">8194</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60);
+<a class="jxr_linenumber" name="L8195" href="#L8195">8195</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"min"</span>) || unit.startsWith(<span class="jxr_string">"minute"</span>))
+<a class="jxr_linenumber" name="L8196" href="#L8196">8196</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60);
+<a class="jxr_linenumber" name="L8197" href="#L8197">8197</a> 
+<a class="jxr_linenumber" name="L8198" href="#L8198">8198</a> 		<em class="jxr_comment">// Hours</em>
+<a class="jxr_linenumber" name="L8199" href="#L8199">8199</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"h"</span>) || unit.startsWith(<span class="jxr_string">"hour"</span>))
+<a class="jxr_linenumber" name="L8200" href="#L8200">8200</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60);
+<a class="jxr_linenumber" name="L8201" href="#L8201">8201</a> 
+<a class="jxr_linenumber" name="L8202" href="#L8202">8202</a> 		<em class="jxr_comment">// Days</em>
+<a class="jxr_linenumber" name="L8203" href="#L8203">8203</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"d"</span>) &amp;&amp; !unit.startsWith(<span class="jxr_string">"da"</span>))
+<a class="jxr_linenumber" name="L8204" href="#L8204">8204</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60 * 24);
+<a class="jxr_linenumber" name="L8205" href="#L8205">8205</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"day"</span>))
+<a class="jxr_linenumber" name="L8206" href="#L8206">8206</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60 * 24);
+<a class="jxr_linenumber" name="L8207" href="#L8207">8207</a> 
+<a class="jxr_linenumber" name="L8208" href="#L8208">8208</a> 		<em class="jxr_comment">// Weeks</em>
+<a class="jxr_linenumber" name="L8209" href="#L8209">8209</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"w"</span>) || unit.startsWith(<span class="jxr_string">"week"</span>))
+<a class="jxr_linenumber" name="L8210" href="#L8210">8210</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60 * 24 * 7);
+<a class="jxr_linenumber" name="L8211" href="#L8211">8211</a> 
+<a class="jxr_linenumber" name="L8212" href="#L8212">8212</a> 		<em class="jxr_comment">// Months (30 days)</em>
+<a class="jxr_linenumber" name="L8213" href="#L8213">8213</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"mo"</span>) || unit.startsWith(<span class="jxr_string">"month"</span>))
+<a class="jxr_linenumber" name="L8214" href="#L8214">8214</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60 * 24 * 30);
+<a class="jxr_linenumber" name="L8215" href="#L8215">8215</a> 
+<a class="jxr_linenumber" name="L8216" href="#L8216">8216</a> 		<em class="jxr_comment">// Years (365 days)</em>
+<a class="jxr_linenumber" name="L8217" href="#L8217">8217</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"y"</span>) &amp;&amp; !unit.startsWith(<span class="jxr_string">"yr"</span>))
+<a class="jxr_linenumber" name="L8218" href="#L8218">8218</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60 * 24 * 365);
+<a class="jxr_linenumber" name="L8219" href="#L8219">8219</a> 		<strong class="jxr_keyword">if</strong> (unit.startsWith(<span class="jxr_string">"yr"</span>) || unit.startsWith(<span class="jxr_string">"year"</span>))
+<a class="jxr_linenumber" name="L8220" href="#L8220">8220</a> 			<strong class="jxr_keyword">return</strong> (<strong class="jxr_keyword">long</strong>)(value * 1000 * 60 * 60 * 24 * 365);
+<a class="jxr_linenumber" name="L8221" href="#L8221">8221</a> 
+<a class="jxr_linenumber" name="L8222" href="#L8222">8222</a> 		<em class="jxr_comment">// Unknown unit</em>
+<a class="jxr_linenumber" name="L8223" href="#L8223">8223</a> 		<strong class="jxr_keyword">return</strong> -1;
+<a class="jxr_linenumber" name="L8224" href="#L8224">8224</a> 	}
+<a class="jxr_linenumber" name="L8225" href="#L8225">8225</a> 
+<a class="jxr_linenumber" name="L8226" href="#L8226">8226</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L8227" href="#L8227">8227</a> <em class="jxr_javadoccomment">	 * Skips over a single comment sequence in a StringReader.</em>
+<a class="jxr_linenumber" name="L8228" href="#L8228">8228</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L8229" href="#L8229">8229</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
+<a class="jxr_linenumber" name="L8230" href="#L8230">8230</a> <em class="jxr_javadoccomment">	 * The reader must be positioned at the first &lt;js&gt;'/'&lt;/js&gt; character of a comment.</em>
+<a class="jxr_linenumber" name="L8231" href="#L8231">8231</a> <em class="jxr_javadoccomment">	 * This method will skip only the comment it's currently positioned on, not all comments in the reader.</em>
+<a class="jxr_linenumber" name="L8232" href="#L8232">8232</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L8233" href="#L8233">8233</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
+<a class="jxr_linenumber" name="L8234" href="#L8234">8234</a> <em class="jxr_javadoccomment">	 * Supports both &lt;js&gt;"/* * /"&lt;/js&gt; style block comments and &lt;js&gt;"//"&lt;/js&gt; style line comments.</em>
 <a class="jxr_linenumber" name="L8235" href="#L8235">8235</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L8236" href="#L8236">8236</a> <em class="jxr_javadoccomment">	 * &lt;p&gt;</em>
-<a class="jxr_linenumber" name="L8237" href="#L8237">8237</a> <em class="jxr_javadoccomment">	 * Supports both &lt;js&gt;"/* * /"&lt;/js&gt; style block comments and &lt;js&gt;"//"&lt;/js&gt; style line comments.</em>
-<a class="jxr_linenumber" name="L8238" href="#L8238">8238</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L8239" href="#L8239">8239</a> <em class="jxr_javadoccomment">	 * @param r The StringReader positioned at the start of a comment (at the first &lt;js&gt;'/'&lt;/js&gt;).</em>
-<a class="jxr_linenumber" name="L8240" href="#L8240">8240</a> <em class="jxr_javadoccomment">	 * @throws IOException If an I/O error occurs.</em>
-<a class="jxr_linenumber" name="L8241" href="#L8241">8241</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L8242" href="#L8242">8242</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">void</strong> skipComments(StringReader r) <strong class="jxr_keyword">throws</strong> IOException {
-<a class="jxr_linenumber" name="L8243" href="#L8243">8243</a> 		<strong class="jxr_keyword">var</strong> c = r.read();
-<a class="jxr_linenumber" name="L8244" href="#L8244">8244</a> 		<em class="jxr_comment">//  "/* */" style comments</em>
-<a class="jxr_linenumber" name="L8245" href="#L8245">8245</a> 		<strong class="jxr_keyword">if</strong> (c == '*') {
-<a class="jxr_linenumber" name="L8246" href="#L8246">8246</a> 			c = r.read();
-<a class="jxr_linenumber" name="L8247" href="#L8247">8247</a> 			<strong class="jxr_keyword">while</strong> (c != -1) {
-<a class="jxr_linenumber" name="L8248" href="#L8248">8248</a> 				<strong class="jxr_keyword">if</strong> (c == '*') {
-<a class="jxr_linenumber" name="L8249" href="#L8249">8249</a> 					c = r.read();
-<a class="jxr_linenumber" name="L8250" href="#L8250">8250</a> 					<strong class="jxr_keyword">if</strong> (c == '/')
-<a class="jxr_linenumber" name="L8251" href="#L8251">8251</a> 						<strong class="jxr_keyword">return</strong>;
-<a class="jxr_linenumber" name="L8252" href="#L8252">8252</a> 					<em class="jxr_comment">// If not '/', continue checking from this character</em>
-<a class="jxr_linenumber" name="L8253" href="#L8253">8253</a> 					<em class="jxr_comment">// Don't read again, just continue the loop</em>
-<a class="jxr_linenumber" name="L8254" href="#L8254">8254</a> 				} <strong class="jxr_keyword">else</strong> {
-<a class="jxr_linenumber" name="L8255" href="#L8255">8255</a> 					c = r.read();
-<a class="jxr_linenumber" name="L8256" href="#L8256">8256</a> 				}
-<a class="jxr_linenumber" name="L8257" href="#L8257">8257</a> 			}
-<a class="jxr_linenumber" name="L8258" href="#L8258">8258</a> 			<em class="jxr_comment">//  "//" style comments</em>
-<a class="jxr_linenumber" name="L8259" href="#L8259">8259</a> 		} <strong class="jxr_keyword">else</strong> <strong class="jxr_keyword">if</strong> (c == '/') {
-<a class="jxr_linenumber" name="L8260" href="#L8260">8260</a> 			<strong class="jxr_keyword">while</strong> ((c = r.read()) != -1) {
-<a class="jxr_linenumber" name="L8261" href="#L8261">8261</a> 				<strong class="jxr_keyword">if</strong> (c == '\n')
-<a class="jxr_linenumber" name="L8262" href="#L8262">8262</a> 					<strong class="jxr_keyword">return</strong>;
-<a class="jxr_linenumber" name="L8263" href="#L8263">8263</a> 			}
-<a class="jxr_linenumber" name="L8264" href="#L8264">8264</a> 		}
-<a class="jxr_linenumber" name="L8265" href="#L8265">8265</a> 	}
-<a class="jxr_linenumber" name="L8266" href="#L8266">8266</a> 
-<a class="jxr_linenumber" name="L8267" href="#L8267">8267</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L8268" href="#L8268">8268</a> <em class="jxr_javadoccomment">	 * Gets or creates an AsciiSet for escaping the specified character.</em>
-<a class="jxr_linenumber" name="L8269" href="#L8269">8269</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L8270" href="#L8270">8270</a> <em class="jxr_javadoccomment">	 * @param c The character to create an escape set for.</em>
-<a class="jxr_linenumber" name="L8271" href="#L8271">8271</a> <em class="jxr_javadoccomment">	 * @return An AsciiSet containing the character and backslash.</em>
-<a class="jxr_linenumber" name="L8272" href="#L8272">8272</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L8273" href="#L8273">8273</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <a name="AsciiSet" href="../../../../../org/apache/juneau/commons/utils/AsciiSet.html#AsciiSet">AsciiSet</a> getEscapeSet(<strong class="jxr_keyword">char</strong> c) {
-<a class="jxr_linenumber" name="L8274" href="#L8274">8274</a> 		<strong class="jxr_keyword">return</strong> ESCAPE_SETS.computeIfAbsent(c, key -&gt; AsciiSet.create().chars(key, '&#92;&#92;').build());
-<a class="jxr_linenumber" name="L8275" href="#L8275">8275</a> 	}
-<a class="jxr_linenumber" name="L8276" href="#L8276">8276</a> 
-<a class="jxr_linenumber" name="L8277" href="#L8277">8277</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L8278" href="#L8278">8278</a> <em class="jxr_javadoccomment">	 * Helper method to split a string into words.</em>
-<a class="jxr_linenumber" name="L8279" href="#L8279">8279</a> <em class="jxr_javadoccomment">	 * Detects word boundaries from separators (spaces, underscores, hyphens) and case changes.</em>
-<a class="jxr_linenumber" name="L8280" href="#L8280">8280</a> <em class="jxr_javadoccomment">	 *</em>
-<a class="jxr_linenumber" name="L8281" href="#L8281">8281</a> <em class="jxr_javadoccomment">	 * @param str The string to split.</em>
-<a class="jxr_linenumber" name="L8282" href="#L8282">8282</a> <em class="jxr_javadoccomment">	 * @return A list of words, or empty list if input is null or empty.</em>
-<a class="jxr_linenumber" name="L8283" href="#L8283">8283</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L8284" href="#L8284">8284</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> List&lt;String&gt; splitWords(String str) {
-<a class="jxr_linenumber" name="L8285" href="#L8285">8285</a> 		<strong class="jxr_keyword">if</strong> (str == <strong class="jxr_keyword">null</strong> || isEmpty(str))
-<a class="jxr_linenumber" name="L8286" href="#L8286">8286</a> 			<strong class="jxr_keyword">return</strong> Collections.emptyList();
-<a class="jxr_linenumber" name="L8287" href="#L8287">8287</a> 
-<a class="jxr_linenumber" name="L8288" href="#L8288">8288</a> 		<strong class="jxr_keyword">var</strong> words = <strong class="jxr_keyword">new</strong> ArrayList&lt;String&gt;();
-<a class="jxr_linenumber" name="L8289" href="#L8289">8289</a> 		<strong class="jxr_keyword">var</strong> sb = <strong class="jxr_keyword">new</strong> StringBuilder();
-<a class="jxr_linenumber" name="L8290" href="#L8290">8290</a> 		<strong class="jxr_keyword">var</strong> wasLowerCase = false;
-<a class="jxr_linenumber" name="L8291" href="#L8291">8291</a> 		<strong class="jxr_keyword">var</strong> wasUpperCase = false;
-<a class="jxr_linenumber" name="L8292" href="#L8292">8292</a> 		<strong class="jxr_keyword">var</strong> consecutiveUpperCount = 0;
-<a class="jxr_linenumber" name="L8293" href="#L8293">8293</a> 
-<a class="jxr_linenumber" name="L8294" href="#L8294">8294</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; str.length(); i++) {
-<a class="jxr_linenumber" name="L8295" href="#L8295">8295</a> 			<strong class="jxr_keyword">var</strong> c = str.charAt(i);
-<a class="jxr_linenumber" name="L8296" href="#L8296">8296</a> 			<strong class="jxr_keyword">var</strong> isSeparator = (c == ' ' || c == '_' || c == '-' || c == '\t');
-<a class="jxr_linenumber" name="L8297" href="#L8297">8297</a> 			<strong class="jxr_keyword">var</strong> isUpperCase = LETTER_UC.contains(c);
-<a class="jxr_linenumber" name="L8298" href="#L8298">8298</a> 			<strong class="jxr_keyword">var</strong> isLowerCase = LETTER_LC.contains(c);
-<a class="jxr_linenumber" name="L8299" href="#L8299">8299</a> 			<strong class="jxr_keyword">var</strong> isLetter = LETTER.contains(c);
-<a class="jxr_linenumber" name="L8300" href="#L8300">8300</a> 
-<a class="jxr_linenumber" name="L8301" href="#L8301">8301</a> 			<strong class="jxr_keyword">if</strong> (isSeparator) {
-<a class="jxr_linenumber" name="L8302" href="#L8302">8302</a> 				<strong class="jxr_keyword">if</strong> (sb.length() &gt; 0) {
-<a class="jxr_linenumber" name="L8303" href="#L8303">8303</a> 					words.add(sb.toString());
-<a class="jxr_linenumber" name="L8304" href="#L8304">8304</a> 					sb.setLength(0);
-<a class="jxr_linenumber" name="L8305" href="#L8305">8305</a> 				}
-<a class="jxr_linenumber" name="L8306" href="#L8306">8306</a> 				wasLowerCase = false;
-<a class="jxr_linenumber" name="L8307" href="#L8307">8307</a> 				wasUpperCase = false;
-<a class="jxr_linenumber" name="L8308" href="#L8308">8308</a> 				consecutiveUpperCount = 0;
-<a class="jxr_linenumber" name="L8309" href="#L8309">8309</a> 			} <strong class="jxr_keyword">else</strong> <strong class="jxr_keyword">if</strong> (isLetter) {
-<a class="jxr_linenumber" name="L8310" href="#L8310">8310</a> 				<em class="jxr_comment">// Detect word boundary:</em>
-<a class="jxr_linenumber" name="L8311" href="#L8311">8311</a> 				<em class="jxr_comment">// 1. Uppercase after lowercase (e.g., "helloWorld" → "hello", "World")</em>
-<a class="jxr_linenumber" name="L8312" href="#L8312">8312</a> 				<em class="jxr_comment">// 2. Uppercase after consecutive uppercase when next is lowercase (e.g., "XMLHttp" → "XML", "Http")</em>
-<a class="jxr_linenumber" name="L8313" href="#L8313">8313</a> 				<em class="jxr_comment">// 3. Lowercase after 2+ consecutive uppercase (e.g., "XMLHttp" → "XML", "Http")</em>
-<a class="jxr_linenumber" name="L8314" href="#L8314">8314</a> 				<strong class="jxr_keyword">if</strong> (sb.length() &gt; 0) {
-<a class="jxr_linenumber" name="L8315" href="#L8315">8315</a> 					<strong class="jxr_keyword">if</strong> (isUpperCase &amp;&amp; wasLowerCase) {
-<a class="jxr_linenumber" name="L8316" href="#L8316">8316</a> 						<em class="jxr_comment">// Case 1: uppercase after lowercase (e.g., "helloWorld" → "hello", "World")</em>
-<a class="jxr_linenumber" name="L8317" href="#L8317">8317</a> 						words.add(sb.toString());
-<a class="jxr_linenumber" name="L8318" href="#L8318">8318</a> 						sb.setLength(0);
-<a class="jxr_linenumber" name="L8319" href="#L8319">8319</a> 						consecutiveUpperCount = 0;
-<a class="jxr_linenumber" name="L8320" href="#L8320">8320</a> 					} <strong class="jxr_keyword">else</strong> <strong class="jxr_keyword">if</strong> (isUpperCase &amp;&amp; wasUpperCase &amp;&amp; consecutiveUpperCount &gt;= 2) {
-<a class="jxr_linenumber" name="L8321" href="#L8321">8321</a> 						<em class="jxr_comment">// Case 2: uppercase after uppercase - check if this starts a new word</em>
-<a class="jxr_linenumber" name="L8322" href="#L8322">8322</a> 						<em class="jxr_comment">// Look ahead to see if next character is lowercase</em>
-<a class="jxr_linenumber" name="L8323" href="#L8323">8323</a> 						<em class="jxr_comment">// This handles "XMLHttp" where 'H' starts "Http"</em>
-<a class="jxr_linenumber" name="L8324" href="#L8324">8324</a> 						<em class="jxr_comment">// We need at least 2 consecutive uppercase letters before this one to split</em>
-<a class="jxr_linenumber" name="L8325" href="#L8325">8325</a> 						<strong class="jxr_keyword">if</strong> (i + 1 &lt; str.length()) {
-<a class="jxr_linenumber" name="L8326" href="#L8326">8326</a> 							<strong class="jxr_keyword">var</strong> nextChar = str.charAt(i + 1);
-<a class="jxr_linenumber" name="L8327" href="#L8327">8327</a> 							<strong class="jxr_keyword">if</strong> (LETTER_LC.contains(nextChar)) {
-<a class="jxr_linenumber" name="L8328" href="#L8328">8328</a> 								<em class="jxr_comment">// This uppercase starts a new word, split before it</em>
-<a class="jxr_linenumber" name="L8329" href="#L8329">8329</a> 								words.add(sb.toString());
-<a class="jxr_linenumber" name="L8330" href="#L8330">8330</a> 								sb.setLength(0);
-<a class="jxr_linenumber" name="L8331" href="#L8331">8331</a> 								consecutiveUpperCount = 0;
-<a class="jxr_linenumber" name="L8332" href="#L8332">8332</a> 							}
-<a class="jxr_linenumber" name="L8333" href="#L8333">8333</a> 						}
-<a class="jxr_linenumber" name="L8334" href="#L8334">8334</a> 					} <strong class="jxr_keyword">else</strong> <strong class="jxr_keyword">if</strong> (isLowerCase &amp;&amp; wasUpperCase &amp;&amp; consecutiveUpperCount &gt;= 2) {
-<a class="jxr_linenumber" name="L8335" href="#L8335">8335</a> 						<em class="jxr_comment">// Case 3: lowercase after 2+ consecutive uppercase</em>
-<a class="jxr_linenumber" name="L8336" href="#L8336">8336</a> 						<em class="jxr_comment">// Split all but the last uppercase (e.g., "XMLH" → "XML" + "H")</em>
-<a class="jxr_linenumber" name="L8337" href="#L8337">8337</a> 						<strong class="jxr_keyword">var</strong> splitPoint = sb.length() - 1;
-<a class="jxr_linenumber" name="L8338" href="#L8338">8338</a> 						words.add(sb.substring(0, splitPoint));
-<a class="jxr_linenumber" name="L8339" href="#L8339">8339</a> 						sb.delete(0, splitPoint);
-<a class="jxr_linenumber" name="L8340" href="#L8340">8340</a> 						consecutiveUpperCount = 0;
-<a class="jxr_linenumber" name="L8341" href="#L8341">8341</a> 					}
-<a class="jxr_linenumber" name="L8342" href="#L8342">8342</a> 				}
-<a class="jxr_linenumber" name="L8343" href="#L8343">8343</a> 				sb.append(c);
-<a class="jxr_linenumber" name="L8344" href="#L8344">8344</a> 				<em class="jxr_comment">// Update state AFTER appending</em>
-<a class="jxr_linenumber" name="L8345" href="#L8345">8345</a> 				wasLowerCase = isLowerCase;
-<a class="jxr_linenumber" name="L8346" href="#L8346">8346</a> 				wasUpperCase = isUpperCase;
-<a class="jxr_linenumber" name="L8347" href="#L8347">8347</a> 				<strong class="jxr_keyword">if</strong> (isUpperCase) {
-<a class="jxr_linenumber" name="L8348" href="#L8348">8348</a> 					consecutiveUpperCount++;
-<a class="jxr_linenumber" name="L8349" href="#L8349">8349</a> 				} <strong class="jxr_keyword">else</strong> {
-<a class="jxr_linenumber" name="L8350" href="#L8350">8350</a> 					consecutiveUpperCount = 0;
-<a class="jxr_linenumber" name="L8351" href="#L8351">8351</a> 				}
-<a class="jxr_linenumber" name="L8352" href="#L8352">8352</a> 			} <strong class="jxr_keyword">else</strong> {
-<a class="jxr_linenumber" name="L8353" href="#L8353">8353</a> 				<em class="jxr_comment">// Non-letter characters (digits, etc.) - treat as part of current word</em>
-<a class="jxr_linenumber" name="L8354" href="#L8354">8354</a> 				sb.append(c);
-<a class="jxr_linenumber" name="L8355" href="#L8355">8355</a> 				wasLowerCase = false;
-<a class="jxr_linenumber" name="L8356" href="#L8356">8356</a> 				wasUpperCase = false;
-<a class="jxr_linenumber" name="L8357" href="#L8357">8357</a> 				consecutiveUpperCount = 0;
-<a class="jxr_linenumber" name="L8358" href="#L8358">8358</a> 			}
-<a class="jxr_linenumber" name="L8359" href="#L8359">8359</a> 		}
+<a class="jxr_linenumber" name="L8236" href="#L8236">8236</a> <em class="jxr_javadoccomment">	 * @param r The StringReader positioned at the start of a comment (at the first &lt;js&gt;'/'&lt;/js&gt;).</em>
+<a class="jxr_linenumber" name="L8237" href="#L8237">8237</a> <em class="jxr_javadoccomment">	 * @throws IOException If an I/O error occurs.</em>
+<a class="jxr_linenumber" name="L8238" href="#L8238">8238</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L8239" href="#L8239">8239</a> 	<strong class="jxr_keyword">public</strong> <strong class="jxr_keyword">static</strong> <strong class="jxr_keyword">void</strong> skipComments(StringReader r) <strong class="jxr_keyword">throws</strong> IOException {
+<a class="jxr_linenumber" name="L8240" href="#L8240">8240</a> 		<strong class="jxr_keyword">var</strong> c = r.read();
+<a class="jxr_linenumber" name="L8241" href="#L8241">8241</a> 		<em class="jxr_comment">//  "/* */" style comments</em>
+<a class="jxr_linenumber" name="L8242" href="#L8242">8242</a> 		<strong class="jxr_keyword">if</strong> (c == '*') {
+<a class="jxr_linenumber" name="L8243" href="#L8243">8243</a> 			c = r.read();
+<a class="jxr_linenumber" name="L8244" href="#L8244">8244</a> 			<strong class="jxr_keyword">while</strong> (c != -1) {
+<a class="jxr_linenumber" name="L8245" href="#L8245">8245</a> 				<strong class="jxr_keyword">if</strong> (c == '*') {
+<a class="jxr_linenumber" name="L8246" href="#L8246">8246</a> 					c = r.read();
+<a class="jxr_linenumber" name="L8247" href="#L8247">8247</a> 					<strong class="jxr_keyword">if</strong> (c == '/')
+<a class="jxr_linenumber" name="L8248" href="#L8248">8248</a> 						<strong class="jxr_keyword">return</strong>;
+<a class="jxr_linenumber" name="L8249" href="#L8249">8249</a> 					<em class="jxr_comment">// If not '/', continue checking from this character</em>
+<a class="jxr_linenumber" name="L8250" href="#L8250">8250</a> 					<em class="jxr_comment">// Don't read again, just continue the loop</em>
+<a class="jxr_linenumber" name="L8251" href="#L8251">8251</a> 				} <strong class="jxr_keyword">else</strong> {
+<a class="jxr_linenumber" name="L8252" href="#L8252">8252</a> 					c = r.read();
+<a class="jxr_linenumber" name="L8253" href="#L8253">8253</a> 				}
+<a class="jxr_linenumber" name="L8254" href="#L8254">8254</a> 			}
+<a class="jxr_linenumber" name="L8255" href="#L8255">8255</a> 			<em class="jxr_comment">//  "//" style comments</em>
+<a class="jxr_linenumber" name="L8256" href="#L8256">8256</a> 		} <strong class="jxr_keyword">else</strong> <strong class="jxr_keyword">if</strong> (c == '/') {
+<a class="jxr_linenumber" name="L8257" href="#L8257">8257</a> 			<strong class="jxr_keyword">while</strong> ((c = r.read()) != -1) {
+<a class="jxr_linenumber" name="L8258" href="#L8258">8258</a> 				<strong class="jxr_keyword">if</strong> (c == '\n')
+<a class="jxr_linenumber" name="L8259" href="#L8259">8259</a> 					<strong class="jxr_keyword">return</strong>;
+<a class="jxr_linenumber" name="L8260" href="#L8260">8260</a> 			}
+<a class="jxr_linenumber" name="L8261" href="#L8261">8261</a> 		}
+<a class="jxr_linenumber" name="L8262" href="#L8262">8262</a> 	}
+<a class="jxr_linenumber" name="L8263" href="#L8263">8263</a> 
+<a class="jxr_linenumber" name="L8264" href="#L8264">8264</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L8265" href="#L8265">8265</a> <em class="jxr_javadoccomment">	 * Gets or creates an AsciiSet for escaping the specified character.</em>
+<a class="jxr_linenumber" name="L8266" href="#L8266">8266</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L8267" href="#L8267">8267</a> <em class="jxr_javadoccomment">	 * @param c The character to create an escape set for.</em>
+<a class="jxr_linenumber" name="L8268" href="#L8268">8268</a> <em class="jxr_javadoccomment">	 * @return An AsciiSet containing the character and backslash.</em>
+<a class="jxr_linenumber" name="L8269" href="#L8269">8269</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L8270" href="#L8270">8270</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> <a name="AsciiSet" href="../../../../../org/apache/juneau/commons/utils/AsciiSet.html#AsciiSet">AsciiSet</a> getEscapeSet(<strong class="jxr_keyword">char</strong> c) {
+<a class="jxr_linenumber" name="L8271" href="#L8271">8271</a> 		<strong class="jxr_keyword">return</strong> ESCAPE_SETS.computeIfAbsent(c, key -&gt; AsciiSet.create().chars(key, '&#92;&#92;').build());
+<a class="jxr_linenumber" name="L8272" href="#L8272">8272</a> 	}
+<a class="jxr_linenumber" name="L8273" href="#L8273">8273</a> 
+<a class="jxr_linenumber" name="L8274" href="#L8274">8274</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L8275" href="#L8275">8275</a> <em class="jxr_javadoccomment">	 * Helper method to split a string into words.</em>
+<a class="jxr_linenumber" name="L8276" href="#L8276">8276</a> <em class="jxr_javadoccomment">	 * Detects word boundaries from separators (spaces, underscores, hyphens) and case changes.</em>
+<a class="jxr_linenumber" name="L8277" href="#L8277">8277</a> <em class="jxr_javadoccomment">	 *</em>
+<a class="jxr_linenumber" name="L8278" href="#L8278">8278</a> <em class="jxr_javadoccomment">	 * @param str The string to split.</em>
+<a class="jxr_linenumber" name="L8279" href="#L8279">8279</a> <em class="jxr_javadoccomment">	 * @return A list of words, or empty list if input is null or empty.</em>
+<a class="jxr_linenumber" name="L8280" href="#L8280">8280</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L8281" href="#L8281">8281</a> 	<strong class="jxr_keyword">private</strong> <strong class="jxr_keyword">static</strong> List&lt;String&gt; splitWords(String str) {
+<a class="jxr_linenumber" name="L8282" href="#L8282">8282</a> 		<strong class="jxr_keyword">if</strong> (str == <strong class="jxr_keyword">null</strong> || isEmpty(str))
+<a class="jxr_linenumber" name="L8283" href="#L8283">8283</a> 			<strong class="jxr_keyword">return</strong> Collections.emptyList();
+<a class="jxr_linenumber" name="L8284" href="#L8284">8284</a> 
+<a class="jxr_linenumber" name="L8285" href="#L8285">8285</a> 		<strong class="jxr_keyword">var</strong> words = <strong class="jxr_keyword">new</strong> ArrayList&lt;String&gt;();
+<a class="jxr_linenumber" name="L8286" href="#L8286">8286</a> 		<strong class="jxr_keyword">var</strong> sb = <strong class="jxr_keyword">new</strong> StringBuilder();
+<a class="jxr_linenumber" name="L8287" href="#L8287">8287</a> 		<strong class="jxr_keyword">var</strong> wasLowerCase = false;
+<a class="jxr_linenumber" name="L8288" href="#L8288">8288</a> 		<strong class="jxr_keyword">var</strong> wasUpperCase = false;
+<a class="jxr_linenumber" name="L8289" href="#L8289">8289</a> 		<strong class="jxr_keyword">var</strong> consecutiveUpperCount = 0;
+<a class="jxr_linenumber" name="L8290" href="#L8290">8290</a> 
+<a class="jxr_linenumber" name="L8291" href="#L8291">8291</a> 		<strong class="jxr_keyword">for</strong> (<strong class="jxr_keyword">var</strong> i = 0; i &lt; str.length(); i++) {
+<a class="jxr_linenumber" name="L8292" href="#L8292">8292</a> 			<strong class="jxr_keyword">var</strong> c = str.charAt(i);
+<a class="jxr_linenumber" name="L8293" href="#L8293">8293</a> 			<strong class="jxr_keyword">var</strong> isSeparator = (c == ' ' || c == '_' || c == '-' || c == '\t');
+<a class="jxr_linenumber" name="L8294" href="#L8294">8294</a> 			<strong class="jxr_keyword">var</strong> isUpperCase = LETTER_UC.contains(c);
+<a class="jxr_linenumber" name="L8295" href="#L8295">8295</a> 			<strong class="jxr_keyword">var</strong> isLowerCase = LETTER_LC.contains(c);
+<a class="jxr_linenumber" name="L8296" href="#L8296">8296</a> 			<strong class="jxr_keyword">var</strong> isLetter = LETTER.contains(c);
+<a class="jxr_linenumber" name="L8297" href="#L8297">8297</a> 
+<a class="jxr_linenumber" name="L8298" href="#L8298">8298</a> 			<strong class="jxr_keyword">if</strong> (isSeparator) {
+<a class="jxr_linenumber" name="L8299" href="#L8299">8299</a> 				<strong class="jxr_keyword">if</strong> (sb.length() &gt; 0) {
+<a class="jxr_linenumber" name="L8300" href="#L8300">8300</a> 					words.add(sb.toString());
+<a class="jxr_linenumber" name="L8301" href="#L8301">8301</a> 					sb.setLength(0);
+<a class="jxr_linenumber" name="L8302" href="#L8302">8302</a> 				}
+<a class="jxr_linenumber" name="L8303" href="#L8303">8303</a> 				wasLowerCase = false;
+<a class="jxr_linenumber" name="L8304" href="#L8304">8304</a> 				wasUpperCase = false;
+<a class="jxr_linenumber" name="L8305" href="#L8305">8305</a> 				consecutiveUpperCount = 0;
+<a class="jxr_linenumber" name="L8306" href="#L8306">8306</a> 			} <strong class="jxr_keyword">else</strong> <strong class="jxr_keyword">if</strong> (isLetter) {
+<a class="jxr_linenumber" name="L8307" href="#L8307">8307</a> 				<em class="jxr_comment">// Detect word boundary:</em>
+<a class="jxr_linenumber" name="L8308" href="#L8308">8308</a> 				<em class="jxr_comment">// 1. Uppercase after lowercase (e.g., "helloWorld" → "hello", "World")</em>
+<a class="jxr_linenumber" name="L8309" href="#L8309">8309</a> 				<em class="jxr_comment">// 2. Uppercase after consecutive uppercase when next is lowercase (e.g., "XMLHttp" → "XML", "Http")</em>
+<a class="jxr_linenumber" name="L8310" href="#L8310">8310</a> 				<em class="jxr_comment">// 3. Lowercase after 2+ consecutive uppercase (e.g., "XMLHttp" → "XML", "Http")</em>
+<a class="jxr_linenumber" name="L8311" href="#L8311">8311</a> 				<strong class="jxr_keyword">if</strong> (sb.length() &gt; 0) {
+<a class="jxr_linenumber" name="L8312" href="#L8312">8312</a> 					<strong class="jxr_keyword">if</strong> (isUpperCase &amp;&amp; wasLowerCase) {
+<a class="jxr_linenumber" name="L8313" href="#L8313">8313</a> 						<em class="jxr_comment">// Case 1: uppercase after lowercase (e.g., "helloWorld" → "hello", "World")</em>
+<a class="jxr_linenumber" name="L8314" href="#L8314">8314</a> 						words.add(sb.toString());
+<a class="jxr_linenumber" name="L8315" href="#L8315">8315</a> 						sb.setLength(0);
+<a class="jxr_linenumber" name="L8316" href="#L8316">8316</a> 						consecutiveUpperCount = 0;
+<a class="jxr_linenumber" name="L8317" href="#L8317">8317</a> 					} <strong class="jxr_keyword">else</strong> <strong class="jxr_keyword">if</strong> (isUpperCase &amp;&amp; wasUpperCase &amp;&amp; consecutiveUpperCount &gt;= 2) {
+<a class="jxr_linenumber" name="L8318" href="#L8318">8318</a> 						<em class="jxr_comment">// Case 2: uppercase after uppercase - check if this starts a new word</em>
+<a class="jxr_linenumber" name="L8319" href="#L8319">8319</a> 						<em class="jxr_comment">// Look ahead to see if next character is lowercase</em>
+<a class="jxr_linenumber" name="L8320" href="#L8320">8320</a> 						<em class="jxr_comment">// This handles "XMLHttp" where 'H' starts "Http"</em>
+<a class="jxr_linenumber" name="L8321" href="#L8321">8321</a> 						<em class="jxr_comment">// We need at least 2 consecutive uppercase letters before this one to split</em>
+<a class="jxr_linenumber" name="L8322" href="#L8322">8322</a> 						<strong class="jxr_keyword">if</strong> (i + 1 &lt; str.length()) {
+<a class="jxr_linenumber" name="L8323" href="#L8323">8323</a> 							<strong class="jxr_keyword">var</strong> nextChar = str.charAt(i + 1);
+<a class="jxr_linenumber" name="L8324" href="#L8324">8324</a> 							<strong class="jxr_keyword">if</strong> (LETTER_LC.contains(nextChar)) {
+<a class="jxr_linenumber" name="L8325" href="#L8325">8325</a> 								<em class="jxr_comment">// This uppercase starts a new word, split before it</em>
+<a class="jxr_linenumber" name="L8326" href="#L8326">8326</a> 								words.add(sb.toString());
+<a class="jxr_linenumber" name="L8327" href="#L8327">8327</a> 								sb.setLength(0);
+<a class="jxr_linenumber" name="L8328" href="#L8328">8328</a> 								consecutiveUpperCount = 0;
+<a class="jxr_linenumber" name="L8329" href="#L8329">8329</a> 							}
+<a class="jxr_linenumber" name="L8330" href="#L8330">8330</a> 						}
+<a class="jxr_linenumber" name="L8331" href="#L8331">8331</a> 					} <strong class="jxr_keyword">else</strong> <strong class="jxr_keyword">if</strong> (isLowerCase &amp;&amp; wasUpperCase &amp;&amp; consecutiveUpperCount &gt;= 2) {
+<a class="jxr_linenumber" name="L8332" href="#L8332">8332</a> 						<em class="jxr_comment">// Case 3: lowercase after 2+ consecutive uppercase</em>
+<a class="jxr_linenumber" name="L8333" href="#L8333">8333</a> 						<em class="jxr_comment">// Split all but the last uppercase (e.g., "XMLH" → "XML" + "H")</em>
+<a class="jxr_linenumber" name="L8334" href="#L8334">8334</a> 						<strong class="jxr_keyword">var</strong> splitPoint = sb.length() - 1;
+<a class="jxr_linenumber" name="L8335" href="#L8335">8335</a> 						words.add(sb.substring(0, splitPoint));
+<a class="jxr_linenumber" name="L8336" href="#L8336">8336</a> 						sb.delete(0, splitPoint);
+<a class="jxr_linenumber" name="L8337" href="#L8337">8337</a> 						consecutiveUpperCount = 0;
+<a class="jxr_linenumber" name="L8338" href="#L8338">8338</a> 					}
+<a class="jxr_linenumber" name="L8339" href="#L8339">8339</a> 				}
+<a class="jxr_linenumber" name="L8340" href="#L8340">8340</a> 				sb.append(c);
+<a class="jxr_linenumber" name="L8341" href="#L8341">8341</a> 				<em class="jxr_comment">// Update state AFTER appending</em>
+<a class="jxr_linenumber" name="L8342" href="#L8342">8342</a> 				wasLowerCase = isLowerCase;
+<a class="jxr_linenumber" name="L8343" href="#L8343">8343</a> 				wasUpperCase = isUpperCase;
+<a class="jxr_linenumber" name="L8344" href="#L8344">8344</a> 				<strong class="jxr_keyword">if</strong> (isUpperCase) {
+<a class="jxr_linenumber" name="L8345" href="#L8345">8345</a> 					consecutiveUpperCount++;
+<a class="jxr_linenumber" name="L8346" href="#L8346">8346</a> 				} <strong class="jxr_keyword">else</strong> {
+<a class="jxr_linenumber" name="L8347" href="#L8347">8347</a> 					consecutiveUpperCount = 0;
+<a class="jxr_linenumber" name="L8348" href="#L8348">8348</a> 				}
+<a class="jxr_linenumber" name="L8349" href="#L8349">8349</a> 			} <strong class="jxr_keyword">else</strong> {
+<a class="jxr_linenumber" name="L8350" href="#L8350">8350</a> 				<em class="jxr_comment">// Non-letter characters (digits, etc.) - treat as part of current word</em>
+<a class="jxr_linenumber" name="L8351" href="#L8351">8351</a> 				sb.append(c);
+<a class="jxr_linenumber" name="L8352" href="#L8352">8352</a> 				wasLowerCase = false;
+<a class="jxr_linenumber" name="L8353" href="#L8353">8353</a> 				wasUpperCase = false;
+<a class="jxr_linenumber" name="L8354" href="#L8354">8354</a> 				consecutiveUpperCount = 0;
+<a class="jxr_linenumber" name="L8355" href="#L8355">8355</a> 			}
+<a class="jxr_linenumber" name="L8356" href="#L8356">8356</a> 		}
+<a class="jxr_linenumber" name="L8357" href="#L8357">8357</a> 
+<a class="jxr_linenumber" name="L8358" href="#L8358">8358</a> 		<strong class="jxr_keyword">if</strong> (sb.length() &gt; 0)
+<a class="jxr_linenumber" name="L8359" href="#L8359">8359</a> 			words.add(sb.toString());
 <a class="jxr_linenumber" name="L8360" href="#L8360">8360</a> 
-<a class="jxr_linenumber" name="L8361" href="#L8361">8361</a> 		<strong class="jxr_keyword">if</strong> (sb.length() &gt; 0)
-<a class="jxr_linenumber" name="L8362" href="#L8362">8362</a> 			words.add(sb.toString());
+<a class="jxr_linenumber" name="L8361" href="#L8361">8361</a> 		<strong class="jxr_keyword">return</strong> words;
+<a class="jxr_linenumber" name="L8362" href="#L8362">8362</a> 	}
 <a class="jxr_linenumber" name="L8363" href="#L8363">8363</a> 
-<a class="jxr_linenumber" name="L8364" href="#L8364">8364</a> 		<strong class="jxr_keyword">return</strong> words;
-<a class="jxr_linenumber" name="L8365" href="#L8365">8365</a> 	}
-<a class="jxr_linenumber" name="L8366" href="#L8366">8366</a> 
-<a class="jxr_linenumber" name="L8367" href="#L8367">8367</a> 	<em class="jxr_javadoccomment">/**</em>
-<a class="jxr_linenumber" name="L8368" href="#L8368">8368</a> <em class="jxr_javadoccomment">	 * Constructor.</em>
-<a class="jxr_linenumber" name="L8369" href="#L8369">8369</a> <em class="jxr_javadoccomment">	 */</em>
-<a class="jxr_linenumber" name="L8370" href="#L8370">8370</a> 	<strong class="jxr_keyword">protected</strong> <a name="StringUtils" href="../../../../../org/apache/juneau/commons/utils/StringUtils.html#StringUtils">StringUtils</a>() {}
-<a class="jxr_linenumber" name="L8371" href="#L8371">8371</a> }
+<a class="jxr_linenumber" name="L8364" href="#L8364">8364</a> 	<em class="jxr_javadoccomment">/**</em>
+<a class="jxr_linenumber" name="L8365" href="#L8365">8365</a> <em class="jxr_javadoccomment">	 * Constructor.</em>
+<a class="jxr_linenumber" name="L8366" href="#L8366">8366</a> <em class="jxr_javadoccomment">	 */</em>
+<a class="jxr_linenumber" name="L8367" href="#L8367">8367</a> 	<strong class="jxr_keyword">protected</strong> <a name="StringUtils" href="../../../../../org/apache/juneau/commons/utils/StringUtils.html#StringUtils">StringUtils</a>() {}
+<a class="jxr_linenumber" name="L8368" href="#L8368">8368</a> }
 </pre>
 <hr/>
 <div id="footer">© 2016–2025 <a href="https://www.apache.org/">The Apache Software Foundation</a></div>