001 /** 002 * Copyright (c) 2000-present Liferay, Inc. All rights reserved. 003 * 004 * This library is free software; you can redistribute it and/or modify it under 005 * the terms of the GNU Lesser General Public License as published by the Free 006 * Software Foundation; either version 2.1 of the License, or (at your option) 007 * any later version. 008 * 009 * This library is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 011 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 012 * details. 013 */ 014 015 package com.liferay.portal.kernel.util; 016 017 import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader; 018 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader; 019 import com.liferay.portal.kernel.log.Log; 020 import com.liferay.portal.kernel.log.LogFactoryUtil; 021 import com.liferay.portal.kernel.search.highlight.HighlightUtil; 022 import com.liferay.portal.kernel.security.RandomUtil; 023 024 import java.io.IOException; 025 import java.io.InputStream; 026 import java.io.InputStreamReader; 027 028 import java.net.URL; 029 030 import java.util.ArrayList; 031 import java.util.Collection; 032 import java.util.Enumeration; 033 import java.util.List; 034 import java.util.Locale; 035 import java.util.Map; 036 import java.util.Random; 037 import java.util.regex.Pattern; 038 039 /** 040 * The String utility class. 041 * 042 * @author Brian Wing Shun Chan 043 * @author Sandeep Soni 044 * @author Ganesh Ram 045 * @author Shuyang Zhou 046 * @author Hugo Huijser 047 */ 048 public class StringUtil { 049 050 /** 051 * Adds string <code>add</code> to string <code>s</code> resulting in a 052 * comma delimited list of strings, disallowing duplicate strings in the 053 * list. 054 * 055 * <p> 056 * The resulting string ends with a comma even if the original string does 057 * not. 058 * </p> 059 * 060 * @param s the original string, representing a comma delimited list of 061 * strings 062 * @param add the string to add to the original, representing the string to 063 * add to the list 064 * @return a string that represents the original string and the added string 065 * separated by a comma, or <code>null</code> if the string to add 066 * is <code>null</code> 067 */ 068 public static String add(String s, String add) { 069 return add(s, add, StringPool.COMMA); 070 } 071 072 /** 073 * Adds string <code>add</code> to string <code>s</code> that represents a 074 * delimited list of strings, using a specified delimiter and disallowing 075 * duplicate words. 076 * 077 * <p> 078 * The returned string ends with the delimiter even if the original string 079 * does not. 080 * </p> 081 * 082 * @param s the original string, representing a delimited list of strings 083 * @param add the string to add to the original, representing the string to 084 * add to the list 085 * @param delimiter the delimiter used to separate strings in the list 086 * @return a string that represents the original string and the added string 087 * separated by the delimiter, or <code>null</code> if the string to 088 * add or the delimiter string is <code>null</code> 089 */ 090 public static String add(String s, String add, String delimiter) { 091 return add(s, add, delimiter, false); 092 } 093 094 /** 095 * Adds string <code>add</code> to string <code>s</code> that represents a 096 * delimited list of strings, using a specified delimiter and optionally 097 * allowing duplicate words. 098 * 099 * <p> 100 * The returned string ends with the delimiter even if the original string 101 * does not. 102 * </p> 103 * 104 * @param s the original string, representing a delimited list of strings 105 * @param add the string to add to the original, representing the string to 106 * add to the list 107 * @param delimiter the delimiter used to separate strings in the list 108 * @param allowDuplicates whether to allow duplicate strings 109 * @return a string that represents the original string and the added string 110 * separated by the delimiter, or <code>null</code> if the string to 111 * add or the delimiter string is <code>null</code> 112 */ 113 public static String add( 114 String s, String add, String delimiter, boolean allowDuplicates) { 115 116 if ((add == null) || (delimiter == null)) { 117 return null; 118 } 119 120 if (s == null) { 121 s = StringPool.BLANK; 122 } 123 124 if (allowDuplicates || !contains(s, add, delimiter)) { 125 StringBundler sb = new StringBundler(4); 126 127 sb.append(s); 128 129 if (Validator.isNull(s) || s.endsWith(delimiter)) { 130 sb.append(add); 131 sb.append(delimiter); 132 } 133 else { 134 sb.append(delimiter); 135 sb.append(add); 136 sb.append(delimiter); 137 } 138 139 s = sb.toString(); 140 } 141 142 return s; 143 } 144 145 /** 146 * Returns the original string with an appended space followed by the string 147 * value of the suffix surrounded by parentheses. 148 * 149 * <p> 150 * If the original string ends with a numerical parenthetical suffix having 151 * an integer value equal to <code>suffix - 1</code>, then the existing 152 * parenthetical suffix is replaced by the new one. 153 * </p> 154 * 155 * <p> 156 * Examples: 157 * </p> 158 * 159 * <p> 160 * <pre> 161 * <code> 162 * appendParentheticalSuffix("file", 0) returns "file (0)" 163 * appendParentheticalSuffix("file (0)", 0) returns "file (0) (0)" 164 * appendParentheticalSuffix("file (0)", 1) returns "file (1)" 165 * appendParentheticalSuffix("file (0)", 2) returns "file (0) (2)" 166 * </code> 167 * </pre> 168 * </p> 169 * 170 * @param s the original string 171 * @param suffix the suffix to be appended 172 * @return the resultant string whose characters equal those of the original 173 * string, followed by a space, followed by the specified suffix 174 * enclosed in parentheses, or, if the difference between the 175 * provided suffix and the existing suffix is 1, the existing suffix 176 * is incremented by 1 177 */ 178 public static String appendParentheticalSuffix(String s, int suffix) { 179 if (Pattern.matches(".* \\(" + String.valueOf(suffix - 1) + "\\)", s)) { 180 int pos = s.lastIndexOf(" ("); 181 182 s = s.substring(0, pos); 183 } 184 185 return appendParentheticalSuffix(s, String.valueOf(suffix)); 186 } 187 188 /** 189 * Returns the original string with an appended space followed by the suffix 190 * surrounded by parentheses. 191 * 192 * <p> 193 * Example: 194 * </p> 195 * 196 * <p> 197 * <pre> 198 * <code> 199 * appendParentheticalSuffix("Java", "EE") returns "Java (EE)" 200 * </code> 201 * </pre> 202 * </p> 203 * 204 * @param s the original string 205 * @param suffix the suffix to be appended 206 * @return a string that represents the original string, followed by a 207 * space, followed by the suffix enclosed in parentheses 208 */ 209 public static String appendParentheticalSuffix(String s, String suffix) { 210 StringBundler sb = new StringBundler(5); 211 212 sb.append(s); 213 sb.append(StringPool.SPACE); 214 sb.append(StringPool.OPEN_PARENTHESIS); 215 sb.append(suffix); 216 sb.append(StringPool.CLOSE_PARENTHESIS); 217 218 return sb.toString(); 219 } 220 221 /** 222 * Converts an array of bytes to a string representing the bytes in 223 * hexadecimal form. 224 * 225 * @param bytes the array of bytes to be converted 226 * @return the string representing the bytes in hexadecimal form 227 */ 228 public static String bytesToHexString(byte[] bytes) { 229 char[] chars = new char[bytes.length * 2]; 230 231 for (int i = 0; i < bytes.length; i++) { 232 chars[i * 2] = HEX_DIGITS[(bytes[i] & 0xFF) >> 4]; 233 chars[i * 2 + 1] = HEX_DIGITS[bytes[i] & 0x0F]; 234 } 235 236 return new String(chars); 237 } 238 239 /** 240 * Returns <code>true</code> if the string contains the text as a comma 241 * delimited list entry. 242 * 243 * <p> 244 * Example: 245 * </p> 246 * 247 * <p> 248 * <pre> 249 * <code> 250 * contains("one,two,three", "two") returns true 251 * contains("one,two,three", "thr") returns false 252 * </code> 253 * </pre> 254 * </p> 255 * 256 * @param s the string in which to search 257 * @param text the text to search for in the string 258 * @return <code>true</code> if the string contains the text as a comma 259 * delimited list entry; <code>false</code> otherwise 260 */ 261 public static boolean contains(String s, String text) { 262 return contains(s, text, StringPool.COMMA); 263 } 264 265 /** 266 * Returns <code>true</code> if the string contains the text as a delimited 267 * list entry. 268 * 269 * <p> 270 * Examples: 271 * </p> 272 * 273 * <p> 274 * <pre> 275 * <code> 276 * contains("three...two...one", "two", "...") returns true 277 * contains("three...two...one", "thr", "...") returns false 278 * </code> 279 * </pre> 280 * </p> 281 * 282 * @param s the string in which to search 283 * @param text the text to search for in the string 284 * @param delimiter the delimiter 285 * @return <code>true</code> if the string contains the text as a delimited 286 * list entry; <code>false</code> otherwise 287 */ 288 public static boolean contains(String s, String text, String delimiter) { 289 if ((s == null) || (text == null) || (delimiter == null)) { 290 return false; 291 } 292 293 if (!s.endsWith(delimiter)) { 294 s = s.concat(delimiter); 295 } 296 297 String dtd = delimiter.concat(text).concat(delimiter); 298 299 int pos = s.indexOf(dtd); 300 301 if (pos == -1) { 302 String td = text.concat(delimiter); 303 304 if (s.startsWith(td)) { 305 return true; 306 } 307 308 return false; 309 } 310 311 return true; 312 } 313 314 /** 315 * Returns the number of times the text appears in the string. 316 * 317 * @param s the string in which to search 318 * @param text the text to search for in the string 319 * @return the number of times the text appears in the string 320 */ 321 public static int count(String s, String text) { 322 if ((s == null) || (s.length() == 0) || (text == null) || 323 (text.length() == 0)) { 324 325 return 0; 326 } 327 328 int count = 0; 329 330 int pos = s.indexOf(text); 331 332 while (pos != -1) { 333 pos = s.indexOf(text, pos + text.length()); 334 335 count++; 336 } 337 338 return count; 339 } 340 341 /** 342 * Returns <code>true</code> if the string ends with the specified 343 * character, ignoring case. 344 * 345 * @param s the string in which to search 346 * @param end the character to search for at the end of the string 347 * @return <code>true</code> if the string ends with the specified 348 * character, ignoring case; <code>false</code> otherwise 349 */ 350 public static boolean endsWith(String s, char end) { 351 return endsWith(s, (Character.valueOf(end)).toString()); 352 } 353 354 /** 355 * Returns <code>true</code> if the string ends with the string 356 * <code>end</code>, ignoring case. 357 * 358 * @param s the string in which to search 359 * @param end the string to check for at the end of the string 360 * @return <code>true</code> if the string ends with the string 361 * <code>end</code>, ignoring case; <code>false</code> otherwise 362 */ 363 public static boolean endsWith(String s, String end) { 364 if ((s == null) || (end == null)) { 365 return false; 366 } 367 368 if (end.length() > s.length()) { 369 return false; 370 } 371 372 String temp = s.substring(s.length() - end.length()); 373 374 if (equalsIgnoreCase(temp, end)) { 375 return true; 376 } 377 else { 378 return false; 379 } 380 } 381 382 /** 383 * Returns <code>true</code> if the strings are equal, ignoring new line 384 * characters. 385 * 386 * @param s1 the first string to compare 387 * @param s2 the second string to compare 388 * @return <code>true</code> if the strings are equal, ignoring new line 389 * characters; <code>false</code> otherwise 390 */ 391 public static boolean equalsIgnoreBreakLine(String s1, String s2) { 392 if (s1 == s2) { 393 return true; 394 } 395 396 if ((s1 == null) || (s2 == null)) { 397 return false; 398 } 399 400 s1 = replace( 401 s1, new String[] {StringPool.RETURN_NEW_LINE, StringPool.NEW_LINE}, 402 new String[] {StringPool.BLANK, StringPool.BLANK}); 403 s2 = replace( 404 s2, new String[] {StringPool.RETURN_NEW_LINE, StringPool.NEW_LINE}, 405 new String[] {StringPool.BLANK, StringPool.BLANK}); 406 407 if (s1.length() != s2.length()) { 408 return false; 409 } 410 411 return s1.equals(s2); 412 } 413 414 /** 415 * Returns <code>true</code> if the strings are equal, ignoring case. 416 * 417 * @param s1 the first string to compare 418 * @param s2 the second string to compare 419 * @return <code>true</code> if the strings are equal, ignoring case; 420 * <code>false</code> otherwise 421 */ 422 public static boolean equalsIgnoreCase(String s1, String s2) { 423 if (s1 == s2) { 424 return true; 425 } 426 427 if ((s1 == null) || (s2 == null)) { 428 return false; 429 } 430 431 if (s1.length() != s2.length()) { 432 return false; 433 } 434 435 for (int i = 0; i < s1.length(); i++) { 436 char c1 = s1.charAt(i); 437 438 char c2 = s2.charAt(i); 439 440 if (c1 == c2) { 441 continue; 442 } 443 444 if ((c1 > 127) || (c2 > 127)) { 445 446 // Georgian alphabet needs to check both upper and lower case 447 448 if ((Character.toLowerCase(c1) == Character.toLowerCase(c2)) || 449 (Character.toUpperCase(c1) == Character.toUpperCase(c2))) { 450 451 continue; 452 } 453 454 return false; 455 } 456 457 int delta = c1 - c2; 458 459 if ((delta != 32) && (delta != -32)) { 460 return false; 461 } 462 } 463 464 return true; 465 } 466 467 /** 468 * Returns the substring of each character instance in string <code>s</code> 469 * that is found in the character array <code>chars</code>. The substring of 470 * characters returned maintain their original order. 471 * 472 * @param s the string from which to extract characters 473 * @param chars the characters to extract from the string 474 * @return the substring of each character instance in string <code>s</code> 475 * that is found in the character array <code>chars</code>, or an 476 * empty string if the given string is <code>null</code> 477 */ 478 public static String extract(String s, char[] chars) { 479 if (s == null) { 480 return StringPool.BLANK; 481 } 482 483 StringBundler sb = new StringBundler(); 484 485 for (char c1 : s.toCharArray()) { 486 for (char c2 : chars) { 487 if (c1 == c2) { 488 sb.append(c1); 489 490 break; 491 } 492 } 493 } 494 495 return sb.toString(); 496 } 497 498 /** 499 * Returns the substring of English characters from the string. 500 * 501 * @param s the string from which to extract characters 502 * @return the substring of English characters from the string, or an empty 503 * string if the given string is <code>null</code> 504 */ 505 public static String extractChars(String s) { 506 if (s == null) { 507 return StringPool.BLANK; 508 } 509 510 StringBundler sb = new StringBundler(); 511 512 char[] chars = s.toCharArray(); 513 514 for (char c : chars) { 515 if (Validator.isChar(c)) { 516 sb.append(c); 517 } 518 } 519 520 return sb.toString(); 521 } 522 523 /** 524 * Returns a string consisting of all of the digits extracted from the 525 * string. 526 * 527 * @param s the string from which to extract digits 528 * @return a string consisting of all of the digits extracted from the 529 * string 530 */ 531 public static String extractDigits(String s) { 532 if (s == null) { 533 return StringPool.BLANK; 534 } 535 536 StringBundler sb = new StringBundler(); 537 538 char[] chars = s.toCharArray(); 539 540 for (char c : chars) { 541 if (Validator.isDigit(c)) { 542 sb.append(c); 543 } 544 } 545 546 return sb.toString(); 547 } 548 549 /** 550 * Returns the substring of <code>s</code> up to but not including the first 551 * occurrence of the delimiter. 552 * 553 * @param s the string from which to extract a substring 554 * @param delimiter the character whose index in the string marks where to 555 * end the substring 556 * @return the substring of <code>s</code> up to but not including the first 557 * occurrence of the delimiter, <code>null</code> if the string is 558 * <code>null</code> or the delimiter does not occur in the string 559 */ 560 public static String extractFirst(String s, char delimiter) { 561 if (s == null) { 562 return null; 563 } 564 565 int index = s.indexOf(delimiter); 566 567 if (index < 0) { 568 return null; 569 } 570 else { 571 return s.substring(0, index); 572 } 573 } 574 575 /** 576 * Returns the substring of <code>s</code> up to but not including the first 577 * occurrence of the delimiter. 578 * 579 * @param s the string from which to extract a substring 580 * @param delimiter the smaller string whose index in the larger string 581 * marks where to end the substring 582 * @return the substring of <code>s</code> up to but not including the first 583 * occurrence of the delimiter, <code>null</code> if the string is 584 * <code>null</code> or the delimiter does not occur in the string 585 */ 586 public static String extractFirst(String s, String delimiter) { 587 if (s == null) { 588 return null; 589 } 590 591 int index = s.indexOf(delimiter); 592 593 if (index < 0) { 594 return null; 595 } 596 else { 597 return s.substring(0, index); 598 } 599 } 600 601 /** 602 * Returns the substring of <code>s</code> after but not including the last 603 * occurrence of the delimiter. 604 * 605 * @param s the string from which to extract the substring 606 * @param delimiter the character whose last index in the string marks 607 * where to begin the substring 608 * @return the substring of <code>s</code> after but not including the last 609 * occurrence of the delimiter, <code>null</code> if the string is 610 * <code>null</code> or the delimiter does not occur in the string 611 */ 612 public static String extractLast(String s, char delimiter) { 613 if (s == null) { 614 return null; 615 } 616 617 int index = s.lastIndexOf(delimiter); 618 619 if (index < 0) { 620 return null; 621 } 622 else { 623 return s.substring(index + 1); 624 } 625 } 626 627 /** 628 * Returns the substring of <code>s</code> after but not including the last 629 * occurrence of the delimiter. 630 * 631 * @param s the string from which to extract the substring 632 * @param delimiter the string whose last index in the string marks where 633 * to begin the substring 634 * @return the substring of <code>s</code> after but not including the last 635 * occurrence of the delimiter, <code>null</code> if the string is 636 * <code>null</code> or the delimiter does not occur in the string 637 */ 638 public static String extractLast(String s, String delimiter) { 639 if (s == null) { 640 return null; 641 } 642 643 int index = s.lastIndexOf(delimiter); 644 645 if (index < 0) { 646 return null; 647 } 648 else { 649 return s.substring(index + delimiter.length()); 650 } 651 } 652 653 /** 654 * Returns the substring of all leading digits of string <code>s</code>, or 655 * an empty string if it has no leading digits. 656 * 657 * @param s the string from which to extract the substring 658 * @return the substring of all leading digits of string <code>s</code>, or 659 * an empty string if it has no leading digits 660 */ 661 public static String extractLeadingDigits(String s) { 662 if (s == null) { 663 return StringPool.BLANK; 664 } 665 666 StringBundler sb = new StringBundler(); 667 668 char[] chars = s.toCharArray(); 669 670 for (char c : chars) { 671 if (Validator.isDigit(c)) { 672 sb.append(c); 673 } 674 else { 675 return sb.toString(); 676 } 677 } 678 679 return sb.toString(); 680 } 681 682 /** 683 * @deprecated As of 7.0.0, moved to {@link HighlightUtil#highlight(String, 684 * String[])}} 685 */ 686 @Deprecated 687 public static String highlight(String s, String[] queryTerms) { 688 return HighlightUtil.highlight(s, queryTerms); 689 } 690 691 /** 692 * @deprecated As of 7.0.0, moved to {@link HighlightUtil#highlight(String, 693 * String[], String, String)}} 694 */ 695 @Deprecated 696 public static String highlight( 697 String s, String[] queryTerms, String highlight1, String highlight2) { 698 699 return HighlightUtil.highlight(s, queryTerms, highlight1, highlight2); 700 } 701 702 /** 703 * Returns the index within the string of the first occurrence of any 704 * character from the array. 705 * 706 * <p> 707 * A <code>null</code> string returns <code>-1</code>. A <code>null</code> 708 * or empty array returns <code>-1</code>. 709 * </p> 710 * 711 * <p> 712 * Examples: 713 * </p> 714 * 715 * <p> 716 * <pre> 717 * <code> 718 * indexOfAny(null, *) returns -1 719 * indexOfAny(*, null) returns -1 720 * indexOfAny(*, []) returns -1 721 * indexOfAny("zzabyycdxx", ['a','c']) returns 2 722 * indexOfAny("zzabyycdxx", ['c','a']) returns 2 723 * indexOfAny("zzabyycdxx", ['m','n']) returns -1 724 * </code> 725 * </pre> 726 * </p> 727 * 728 * @param s the string to search (optionally <code>null</code>) 729 * @param chars the characters to search for (optionally <code>null</code>) 730 * @return the index within the string of the first occurrence of any 731 * character from the array, or <code>-1</code> if none of the 732 * characters occur 733 */ 734 public static int indexOfAny(String s, char[] chars) { 735 if (s == null) { 736 return -1; 737 } 738 739 return indexOfAny(s, chars, 0, s.length() - 1); 740 } 741 742 /** 743 * Returns the index within the string of the first occurrence of any 744 * character from the array, starting the search at the specified index 745 * within the string. 746 * 747 * <p> 748 * A <code>null</code> string returns <code>-1</code>. A <code>null</code> 749 * or empty array returns <code>-1</code>. 750 * </p> 751 * 752 * <p> 753 * Examples: 754 * </p> 755 * 756 * <p> 757 * <pre> 758 * <code> 759 * indexOfAny(null, *, *) returns -1 760 * indexOfAny(*, null, *) returns -1 761 * indexOfAny(*, [], *) returns -1 762 * indexOfAny("zzabyycdxx", ['a','c'], 3) returns 6 763 * </code> 764 * </pre> 765 * </p> 766 * 767 * @param s the string to search (optionally <code>null</code>) 768 * @param chars the characters to search for (optionally <code>null</code>) 769 * @param fromIndex the start index within the string 770 * @return the index within the string of the first occurrence of any 771 * character from the array, starting the search at the specified 772 * index within the string, or <code>-1</code> if none of the 773 * characters occur 774 */ 775 public static int indexOfAny(String s, char[] chars, int fromIndex) { 776 if (s == null) { 777 return -1; 778 } 779 780 return indexOfAny(s, chars, fromIndex, s.length() - 1); 781 } 782 783 /** 784 * Returns the index within the string of the first occurrence of any 785 * character from the array, up to and including the specified end index 786 * within the string, starting the search at the specified start index 787 * within the string. 788 * 789 * <p> 790 * A <code>null</code> string returns <code>-1</code>. A <code>null</code> 791 * or empty array returns <code>-1</code>. 792 * </p> 793 * 794 * <p> 795 * Examples: 796 * </p> 797 * 798 * <p> 799 * <pre> 800 * <code> 801 * indexOfAny(null, *, *, *) returns -1 802 * indexOfAny(*, null, *, *) returns -1 803 * indexOfAny(*, [], *, *) returns -1 804 * indexOfAny("zzabyycdxx", ['a','c'], 3, 7) returns 6 805 * </code> 806 * </pre> 807 * </p> 808 * 809 * @param s the string to search (optionally <code>null</code>) 810 * @param chars the characters to search for (optionally <code>null</code>) 811 * @param fromIndex the start index within the string 812 * @param toIndex the end index within the string 813 * @return the index within the string of the first occurrence of any 814 * character from the array, up to and including the specified end 815 * index within the string, starting the search at the specified 816 * start index within the string, or <code>-1</code> if none of the 817 * characters occur 818 */ 819 public static int indexOfAny( 820 String s, char[] chars, int fromIndex, int toIndex) { 821 822 if ((s == null) || (toIndex < fromIndex)) { 823 return -1; 824 } 825 826 if (ArrayUtil.isEmpty(chars)) { 827 return -1; 828 } 829 830 if (fromIndex >= s.length()) { 831 return -1; 832 } 833 834 if (fromIndex < 0) { 835 fromIndex = 0; 836 } 837 838 if (toIndex >= s.length()) { 839 toIndex = s.length() - 1; 840 } 841 842 for (int i = fromIndex; i <= toIndex; i++) { 843 char c = s.charAt(i); 844 845 for (int j = 0; j < chars.length; j++) { 846 if (c == chars[j]) { 847 return i; 848 } 849 } 850 } 851 852 return -1; 853 } 854 855 /** 856 * Returns the index within the string of the first occurrence of any string 857 * from the array. 858 * 859 * <p> 860 * A <code>null</code> string returns <code>-1</code>. A <code>null</code> 861 * or empty array returns <code>-1</code>, but an array containing 862 * <code>""</code> returns <code>0</code> if the string is not 863 * <code>null</code>. 864 * </p> 865 * 866 * <p> 867 * Examples: 868 * </p> 869 * 870 * <p> 871 * <pre> 872 * <code> 873 * indexOfAny(null, *) returns -1 874 * indexOfAny(*, null) returns -1 875 * indexOfAny(*, [null]) returns -1 876 * indexOfAny(*, []) returns -1 877 * indexOfAny("zzabyycdxx", ["ab","cd"]) returns 2 878 * indexOfAny("zzabyycdxx", ["cd","ab"]) returns 2 879 * indexOfAny("zzabyycdxx", ["mn","op"]) returns -1 880 * indexOfAny("zzabyycdxx", ["mn",""]) returns 0 881 * </code> 882 * </pre> 883 * </p> 884 * 885 * @param s the string (optionally <code>null</code>) 886 * @param texts the strings to search for (optionally <code>null</code>) 887 * @return the index within the string of the first occurrence of any string 888 * from the array, <code>0</code> if the search array contains 889 * <code>""</code>, or <code>-1</code> if none of the strings occur 890 */ 891 public static int indexOfAny(String s, String[] texts) { 892 if (s == null) { 893 return -1; 894 } 895 896 return indexOfAny(s, texts, 0, s.length() - 1); 897 } 898 899 /** 900 * Returns the index within the string of the first occurrence of any string 901 * from the array, starting the search at the specified index within the 902 * string. 903 * 904 * <p> 905 * A <code>null</code> string returns <code>-1</code>. A <code>null</code> 906 * or empty array returns <code>-1</code>, but an array containing 907 * <code>""</code> returns the specified start index if the string is not 908 * <code>null</code>. 909 * </p> 910 * 911 * <p> 912 * Examples: 913 * </p> 914 * 915 * <p> 916 * <pre> 917 * <code> 918 * indexOfAny(null, *, *) returns -1 919 * indexOfAny(*, null, *) returns -1 920 * indexOfAny(*, [null], *) returns -1 921 * indexOfAny(*, [], *) returns -1 922 * indexOfAny("zzabyycdxx", ["ab","cd"], 3) returns 6 923 * indexOfAny("zzabyycdxx", ["cd","ab"], 3) returns 6 924 * indexOfAny("zzabyycdxx", ["mn","op"], *) returns -1 925 * indexOfAny("zzabyycdxx", ["mn",""], 3) returns 3 926 * </code> 927 * </pre> 928 * </p> 929 * 930 * @param s the string to search (optionally <code>null</code>) 931 * @param texts the strings to search for (optionally <code>null</code>) 932 * @param fromIndex the start index within the string 933 * @return the index within the string of the first occurrence of any string 934 * from the array, starting the search at the specified index within 935 * the string, the start index if the search array contains 936 * <code>""</code>, or <code>-1</code> if none of the strings occur 937 */ 938 public static int indexOfAny(String s, String[] texts, int fromIndex) { 939 if (s == null) { 940 return -1; 941 } 942 943 return indexOfAny(s, texts, fromIndex, s.length() - 1); 944 } 945 946 /** 947 * Returns the index within the string of the first occurrence of any string 948 * from the array, up to and including the specified end index within the 949 * string, starting the search at the specified start index within the 950 * string. 951 * 952 * <p> 953 * A <code>null</code> string returns <code>-1</code>. A <code>null</code> 954 * or empty array returns <code>-1</code>, but an array containing 955 * <code>""</code> returns the specified start index if the string is not 956 * <code>null</code>. 957 * </p> 958 * 959 * <p> 960 * Examples: 961 * </p> 962 * 963 * <p> 964 * <pre> 965 * <code> 966 * indexOfAny(null, *, *, *) returns -1 967 * indexOfAny(*, null, *, *) returns -1 968 * indexOfAny(*, [null], *, *) returns -1 969 * indexOfAny(*, [], *, *) returns -1 970 * indexOfAny("zzabyycdxx", ["ab","cd"], 3, 7) returns 6 971 * indexOfAny("zzabyycdxx", ["cd","ab"], 2, 7) returns 2 972 * indexOfAny("zzabyycdxx", ["mn","op"], *, *) returns -1 973 * indexOfAny("zzabyycdxx", ["mn",""], 3, *) returns 3 974 * </code> 975 * </pre> 976 * </p> 977 * 978 * @param s the string to search (optionally <code>null</code>) 979 * @param texts the strings to search for (optionally <code>null</code>) 980 * @param fromIndex the start index within the string 981 * @param toIndex the end index within the string 982 * @return the index within the string of the first occurrence of any string 983 * from the array, up to and including the specified end index 984 * within the string, starting the search at the specified start 985 * index within the string, the start index if the search array 986 * contains <code>""</code>, or <code>-1</code> if none of the 987 * strings occur 988 */ 989 public static int indexOfAny( 990 String s, String[] texts, int fromIndex, int toIndex) { 991 992 if ((s == null) || (toIndex < fromIndex)) { 993 return -1; 994 } 995 996 if (ArrayUtil.isEmpty(texts)) { 997 return -1; 998 } 999 1000 if (fromIndex >= s.length()) { 1001 return -1; 1002 } 1003 1004 if (fromIndex < 0) { 1005 fromIndex = 0; 1006 } 1007 1008 if (toIndex >= s.length()) { 1009 toIndex = s.length() - 1; 1010 } 1011 1012 for (int i = fromIndex; i <= toIndex; i++) { 1013 for (int j = 0; j < texts.length; j++) { 1014 if (texts[j] == null) { 1015 continue; 1016 } 1017 1018 if ((i + texts[j].length() <= toIndex + 1) && 1019 s.startsWith(texts[j], i)) { 1020 1021 return i; 1022 } 1023 } 1024 } 1025 1026 return -1; 1027 } 1028 1029 /** 1030 * Inserts one string into the other at the specified offset index. 1031 * 1032 * @param s the original string 1033 * @param insert the string to be inserted into the original string 1034 * @param offset the index of the original string where the insertion 1035 * should take place 1036 * @return a string representing the original string with the other string 1037 * inserted at the specified offset index, or <code>null</code> if 1038 * the original string is <code>null</code> 1039 */ 1040 public static String insert(String s, String insert, int offset) { 1041 if (s == null) { 1042 return null; 1043 } 1044 1045 if (insert == null) { 1046 return s; 1047 } 1048 1049 if (offset > s.length()) { 1050 return s.concat(insert); 1051 } 1052 1053 String prefix = s.substring(0, offset); 1054 String postfix = s.substring(offset); 1055 1056 return prefix.concat(insert).concat(postfix); 1057 } 1058 1059 /** 1060 * Returns <code>true</code> if all the characters in string <code>s</code> 1061 * are lower case, ignoring any non-alphabetic characters. 1062 * 1063 * @param s the string in which to search 1064 * @return <code>true</code> if all the characters in string <code>s</code> 1065 * are lower case, ignoring any non-alphabetic characters; 1066 * <code>false</code> otherwise 1067 */ 1068 public static boolean isLowerCase(String s) { 1069 if (s == null) { 1070 return false; 1071 } 1072 1073 for (int i = 0; i < s.length(); i++) { 1074 char c = s.charAt(i); 1075 1076 // Fast path for ascii code, fallback to the slow unicode detection 1077 1078 if (c <= 127) { 1079 if ((c >= CharPool.UPPER_CASE_A) && 1080 (c <= CharPool.UPPER_CASE_Z)) { 1081 1082 return false; 1083 } 1084 1085 continue; 1086 } 1087 1088 if (Character.isLetter(c) && Character.isUpperCase(c)) { 1089 return false; 1090 } 1091 } 1092 1093 return true; 1094 } 1095 1096 /** 1097 * Returns <code>true</code> if all the characters in string <code>s</code> 1098 * are upper case, ignoring any non-alphabetic characters. 1099 * 1100 * @param s the string in which to search 1101 * @return <code>true</code> if all the characters in string <code>s</code> 1102 * are upper case, ignoring any non-alphabetic characters; 1103 * <code>false</code> otherwise 1104 */ 1105 public static boolean isUpperCase(String s) { 1106 if (s == null) { 1107 return false; 1108 } 1109 1110 for (int i = 0; i < s.length(); i++) { 1111 char c = s.charAt(i); 1112 1113 // Fast path for ascii code, fallback to the slow unicode detection 1114 1115 if (c <= 127) { 1116 if ((c >= CharPool.LOWER_CASE_A) && 1117 (c <= CharPool.LOWER_CASE_Z)) { 1118 1119 return false; 1120 } 1121 1122 continue; 1123 } 1124 1125 if (Character.isLetter(c) && Character.isLowerCase(c)) { 1126 return false; 1127 } 1128 } 1129 1130 return true; 1131 } 1132 1133 /** 1134 * Returns the index within the string of the last occurrence of any 1135 * character from the array. 1136 * 1137 * <p> 1138 * A <code>null</code> string returns <code>-1</code>. A <code>null</code> 1139 * or empty array returns <code>-1</code>. 1140 * </p> 1141 * 1142 * <p> 1143 * Examples: 1144 * </p> 1145 * 1146 * <p> 1147 * <pre> 1148 * <code> 1149 * lastIndexOfAny(null, *) returns -1 1150 * lastIndexOfAny(*, null) returns -1 1151 * lastIndexOfAny(*, []) returns -1 1152 * lastIndexOfAny("zzabyycdxx", ['a','c']) returns 6 1153 * lastIndexOfAny("zzabyycdxx", ['c','a']) returns 6 1154 * lastIndexOfAny("zzabyycdxx", ['m','n']) returns -1 1155 * </code> 1156 * </pre> 1157 * </p> 1158 * 1159 * @param s the string to search (optionally <code>null</code>) 1160 * @param chars the characters to search for (optionally <code>null</code>) 1161 * @return the index within the string of the last occurrence of any 1162 * character from the array, or <code>-1</code> if none of the 1163 * characters occur 1164 */ 1165 public static int lastIndexOfAny(String s, char[] chars) { 1166 if (s == null) { 1167 return -1; 1168 } 1169 1170 return lastIndexOfAny(s, chars, 0, s.length() - 1); 1171 } 1172 1173 /** 1174 * Returns the index within the string of the last occurrence of any 1175 * character from the array, starting the search at the specified index 1176 * within the string. 1177 * 1178 * <p> 1179 * A <code>null</code> string returns <code>-1</code>. A <code>null</code> 1180 * or empty array returns <code>-1</code>. 1181 * </p> 1182 * 1183 * <p> 1184 * Examples: 1185 * </p> 1186 * 1187 * <p> 1188 * <pre> 1189 * <code> 1190 * lastIndexOfAny(null, *, *) returns -1 1191 * lastIndexOfAny(*, null, *) returns -1 1192 * lastIndexOfAny(*, [], *) returns -1 1193 * lastIndexOfAny("zzabyycdxx", ['a','c'], 5) returns 2 1194 * lastIndexOfAny("zzabyycdxx", ['m','n'], *) returns -1 1195 * </code> 1196 * </pre> 1197 * </p> 1198 * 1199 * @param s the string to search (optionally <code>null</code>) 1200 * @param chars the characters to search for (optionally <code>null</code>) 1201 * @param toIndex the end index within the string 1202 * @return the index within the string of the last occurrence of any 1203 * character from the array, starting the search at the specified 1204 * index within the string, or <code>-1</code> if none of the 1205 * characters occur 1206 */ 1207 public static int lastIndexOfAny(String s, char[] chars, int toIndex) { 1208 if (s == null) { 1209 return -1; 1210 } 1211 1212 return lastIndexOfAny(s, chars, 0, toIndex); 1213 } 1214 1215 /** 1216 * Returns the index within the string of the last occurrence of any 1217 * character from the array, up to and including the specified end index 1218 * within the string, starting the search at the specified start index 1219 * within the string. 1220 * 1221 * <p> 1222 * A <code>null</code> string returns <code>-1</code>. A <code>null</code> 1223 * or empty array returns <code>-1</code>. 1224 * </p> 1225 * 1226 * <p> 1227 * Examples: 1228 * </p> 1229 * 1230 * <p> 1231 * <pre> 1232 * <code> 1233 * lastIndexOfAny(null</code>, *, *, *) returns -1 1234 * lastIndexOfAny(*, null</code>, *, *) returns -1 1235 * lastIndexOfAny(*, [], *, *) returns -1 1236 * lastIndexOfAny("zzabyycdxx", ['a','c'], 5, 7) returns 6 1237 * lastIndexOfAny("zzabyycdxx", ['m','n'], *, *) returns -1 1238 * </code> 1239 * </pre> 1240 * </p> 1241 * 1242 * @param s the string to search (optionally <code>null</code>) 1243 * @param chars the characters to search for (optionally <code>null</code>) 1244 * @param fromIndex the start index within the string 1245 * @param toIndex the end index within the string 1246 * @return the index within the string of the last occurrence of any 1247 * character from the array, up to and including the specified end 1248 * index within the string, starting the search at the specified 1249 * start index within the string, or <code>-1</code> if none of the 1250 * characters occur 1251 */ 1252 public static int lastIndexOfAny( 1253 String s, char[] chars, int fromIndex, int toIndex) { 1254 1255 if ((s == null) || (toIndex < fromIndex)) { 1256 return -1; 1257 } 1258 1259 if (ArrayUtil.isEmpty(chars)) { 1260 return -1; 1261 } 1262 1263 if (fromIndex >= s.length()) { 1264 return -1; 1265 } 1266 1267 if (fromIndex < 0) { 1268 fromIndex = 0; 1269 } 1270 1271 if (toIndex >= s.length()) { 1272 toIndex = s.length() - 1; 1273 } 1274 1275 for (int i = toIndex; i >= fromIndex; i--) { 1276 char c = s.charAt(i); 1277 1278 for (int j = 0; j < chars.length; j++) { 1279 if (c == chars[j]) { 1280 return i; 1281 } 1282 } 1283 } 1284 1285 return -1; 1286 } 1287 1288 /** 1289 * Returns the index within the string of the last occurrence of any string 1290 * from the array. 1291 * 1292 * <p> 1293 * A <code>null</code> string returns <code>-1</code>. A <code>null</code> 1294 * or empty array returns <code>-1</code>, but an array containing 1295 * <code>""</code> returns <code>0</code> if the string is not 1296 * <code>null</code>. 1297 * </p> 1298 * 1299 * <p> 1300 * Examples: 1301 * </p> 1302 * 1303 * <p> 1304 * <pre> 1305 * <code> 1306 * lastIndexOfAny(null</code>, *) returns -1 1307 * lastIndexOfAny(*, null</code>) returns -1 1308 * lastIndexOfAny(*, []) returns -1 1309 * lastIndexOfAny(*, [null</code>]) returns -1 1310 * lastIndexOfAny("zzabyycdxx", ["ab","cd"]) returns 6 1311 * lastIndexOfAny("zzabyycdxx", ["cd","ab"]) returns 6 1312 * lastIndexOfAny("zzabyycdxx", ["mn","op"]) returns -1 1313 * lastIndexOfAny("zzabyycdxx", ["mn",""]) returns 10 1314 * </code> 1315 * </pre> 1316 * </p> 1317 * 1318 * @param s the string to search (optionally <code>null</code>) 1319 * @param texts the strings to search for (optionally <code>null</code>) 1320 * @return the index within the string of the last occurrence of any string 1321 * from the array, <code>0</code> if the search array contains 1322 * <code>""</code>, or <code>-1</code> if none of the strings occur 1323 */ 1324 public static int lastIndexOfAny(String s, String[] texts) { 1325 if (s == null) { 1326 return -1; 1327 } 1328 1329 return lastIndexOfAny(s, texts, 0, s.length() - 1); 1330 } 1331 1332 /** 1333 * Returns the index within the string of the last occurrence of any string 1334 * from the array, starting the search at the specified index within the 1335 * string. 1336 * 1337 * <p> 1338 * A <code>null</code> string returns <code>-1</code>. A <code>null</code> 1339 * or empty array returns <code>-1</code>, but an array containing 1340 * <code>""</code> returns the specified start index if the string is not 1341 * <code>null</code>. 1342 * </p> 1343 * 1344 * <p> 1345 * Examples: 1346 * </p> 1347 * 1348 * <p> 1349 * <pre> 1350 * <code> 1351 * lastIndexOfAny(null, *, *) returns -1 1352 * lastIndexOfAny(*, null, *) returns -1 1353 * lastIndexOfAny(*, [], *) returns -1 1354 * lastIndexOfAny(*, [null], *) returns -1 1355 * lastIndexOfAny("zzabyycdxx", ["ab","cd"], 5) returns 2 1356 * lastIndexOfAny("zzabyycdxx", ["cd","ab"], 5) returns 2 1357 * lastIndexOfAny("zzabyycdxx", ["mn","op"], *) returns -1 1358 * lastIndexOfAny("zzabyycdxx", ["mn",""], 5) returns 5 1359 * </code> 1360 * </pre> 1361 * </p> 1362 * 1363 * @param s the string to search (optionally <code>null</code>) 1364 * @param texts the strings to search for (optionally <code>null</code>) 1365 * @param toIndex the end index within the string 1366 * @return the index within the string of the last occurrence of any string 1367 * from the array, starting the search at the specified index within 1368 * the string, the start index if the search array contains 1369 * <code>""</code>, or <code>-1</code> if none of the strings occur 1370 */ 1371 public static int lastIndexOfAny(String s, String[] texts, int toIndex) { 1372 if (s == null) { 1373 return -1; 1374 } 1375 1376 return lastIndexOfAny(s, texts, 0, toIndex); 1377 } 1378 1379 /** 1380 * Returns the index within the string of the last occurrence of any string 1381 * from the array, up to and including the specified end index within the 1382 * string, starting the search at the specified start index within the 1383 * string. 1384 * 1385 * <p> 1386 * A <code>null</code> string returns <code>-1</code>. A <code>null</code> 1387 * or empty array returns <code>-1</code>, but an array containing 1388 * <code>""</code> returns the specified end index if the string is not 1389 * <code>null</code>. 1390 * </p> 1391 * 1392 * <p> 1393 * Examples: 1394 * </p> 1395 * 1396 * <p> 1397 * <pre> 1398 * <code> 1399 * lastIndexOfAny(null, *, *, *) returns -1 1400 * lastIndexOfAny(*, null, *, *) returns -1 1401 * lastIndexOfAny(*, [], *, *) returns -1 1402 * lastIndexOfAny(*, [null], *, *) returns -1 1403 * lastIndexOfAny("zzabyycdxx", ["ab","cd"], 2, 5) returns 2 1404 * lastIndexOfAny("zzabyycdxx", ["mn","op"], *, *) returns -1 1405 * lastIndexOfAny("zzabyycdxx", ["mn",""], 2, 5) returns 5 1406 * </code> 1407 * </pre> 1408 * </p> 1409 * 1410 * @param s the string to search (optionally <code>null</code>) 1411 * @param texts the strings to search for (optionally <code>null</code>) 1412 * @param fromIndex the start index within the string 1413 * @param toIndex the end index within the string 1414 * @return the index within the string of the last occurrence of any string 1415 * from the array, up to and including the specified end index 1416 * within the string, starting the search at the specified start 1417 * index within the string, the end index if the search array 1418 * contains <code>""</code>, or <code>-1</code> if none of the 1419 * strings occur 1420 */ 1421 public static int lastIndexOfAny( 1422 String s, String[] texts, int fromIndex, int toIndex) { 1423 1424 if ((s == null) || (toIndex < fromIndex)) { 1425 return -1; 1426 } 1427 1428 if (ArrayUtil.isEmpty(texts)) { 1429 return -1; 1430 } 1431 1432 if (fromIndex >= s.length()) { 1433 return -1; 1434 } 1435 1436 if (fromIndex < 0) { 1437 fromIndex = 0; 1438 } 1439 1440 if (toIndex >= s.length()) { 1441 toIndex = s.length() - 1; 1442 } 1443 1444 for (int i = toIndex; i >= fromIndex; i--) { 1445 for (int j = 0; j < texts.length; j++) { 1446 if (texts[j] == null) { 1447 continue; 1448 } 1449 1450 if ((i + texts[j].length() <= toIndex + 1) && 1451 s.startsWith(texts[j], i)) { 1452 1453 return i; 1454 } 1455 } 1456 } 1457 1458 return -1; 1459 } 1460 1461 /** 1462 * Converts all of the characters in the string to lower case. 1463 * 1464 * @param s the string to convert 1465 * @return the string, converted to lower case, or <code>null</code> if the 1466 * string is <code>null</code> 1467 * @see String#toLowerCase() 1468 */ 1469 public static String lowerCase(String s) { 1470 return toLowerCase(s); 1471 } 1472 1473 /** 1474 * Converts all of the characters in the arbitrary number of strings to 1475 * lower case. 1476 * 1477 * @param array the array or sequence of string arguments 1478 */ 1479 public static void lowerCase(String... array) { 1480 if (array != null) { 1481 for (int i = 0; i < array.length; i++) { 1482 array[i] = toLowerCase(array[i]); 1483 } 1484 } 1485 } 1486 1487 /** 1488 * Converts the first character of the string to lower case. 1489 * 1490 * @param s the string whose first character is to be converted 1491 * @return the string, with its first character converted to lower-case 1492 */ 1493 public static String lowerCaseFirstLetter(String s) { 1494 char[] chars = s.toCharArray(); 1495 1496 if ((chars[0] >= 65) && (chars[0] <= 90)) { 1497 chars[0] = (char)(chars[0] + 32); 1498 } 1499 1500 return new String(chars); 1501 } 1502 1503 /** 1504 * Returns <code>true</code> if the specified pattern occurs at any position 1505 * in the string. 1506 * 1507 * @param s the string 1508 * @param pattern the pattern to search for in the string 1509 * @return <code>true</code> if the specified pattern occurs at any position 1510 * in the string 1511 */ 1512 public static boolean matches(String s, String pattern) { 1513 String[] array = pattern.split("\\*"); 1514 1515 for (String element : array) { 1516 int pos = s.indexOf(element); 1517 1518 if (pos == -1) { 1519 return false; 1520 } 1521 1522 s = s.substring(pos + element.length()); 1523 } 1524 1525 return true; 1526 } 1527 1528 /** 1529 * Returns <code>true</code> if the specified pattern occurs at any position 1530 * in the string, ignoring case. 1531 * 1532 * @param s the string 1533 * @param pattern the pattern to search for in the string 1534 * @return <code>true</code> if the specified pattern occurs at any position 1535 * in the string 1536 */ 1537 public static boolean matchesIgnoreCase(String s, String pattern) { 1538 return matches(lowerCase(s), lowerCase(pattern)); 1539 } 1540 1541 /** 1542 * Merges the elements of the boolean array into a string representing a 1543 * comma delimited list of its values. 1544 * 1545 * @param array the boolean values to merge 1546 * @return a string representing a comma delimited list of the values of the 1547 * boolean array, an empty string if the array is empty, or 1548 * <code>null</code> if the array is <code>null</code> 1549 */ 1550 public static String merge(boolean[] array) { 1551 return merge(array, StringPool.COMMA); 1552 } 1553 1554 /** 1555 * Merges the elements of the boolean array into a string representing a 1556 * delimited list of its values. 1557 * 1558 * @param array the boolean values to merge 1559 * @param delimiter the delimiter 1560 * @return a string representing a comma delimited list of the values of the 1561 * boolean array, an empty string if the array is empty, or 1562 * <code>null</code> if the array is <code>null</code> 1563 */ 1564 public static String merge(boolean[] array, String delimiter) { 1565 if (array == null) { 1566 return null; 1567 } 1568 1569 if (array.length == 0) { 1570 return StringPool.BLANK; 1571 } 1572 1573 StringBundler sb = new StringBundler(2 * array.length - 1); 1574 1575 for (int i = 0; i < array.length; i++) { 1576 if (i != 0) { 1577 sb.append(delimiter); 1578 } 1579 1580 sb.append(String.valueOf(array[i])); 1581 } 1582 1583 return sb.toString(); 1584 } 1585 1586 /** 1587 * Merges the elements of the character array into a string representing a 1588 * comma delimited list of its values. 1589 * 1590 * @param array the characters to merge 1591 * @return a string representing a comma delimited list of the values of the 1592 * character array, an empty string if the array is empty, or 1593 * <code>null</code> if the array is <code>null</code> 1594 */ 1595 public static String merge(char[] array) { 1596 return merge(array, StringPool.COMMA); 1597 } 1598 1599 /** 1600 * Merges the elements of the character array into a string representing a 1601 * delimited list of its values. 1602 * 1603 * @param array the characters to merge 1604 * @param delimiter the delimiter 1605 * @return a string representing a delimited list of the values of the 1606 * character array, an empty string if the array is empty, or 1607 * <code>null</code> if the array is <code>null</code> 1608 */ 1609 public static String merge(char[] array, String delimiter) { 1610 if (array == null) { 1611 return null; 1612 } 1613 1614 if (array.length == 0) { 1615 return StringPool.BLANK; 1616 } 1617 1618 StringBundler sb = new StringBundler(2 * array.length - 1); 1619 1620 for (int i = 0; i < array.length; i++) { 1621 if (i != 0) { 1622 sb.append(delimiter); 1623 } 1624 1625 sb.append(String.valueOf(array[i])); 1626 } 1627 1628 return sb.toString(); 1629 } 1630 1631 /** 1632 * Merges the elements of the collection by returning a string representing 1633 * a comma delimited list of its values. 1634 * 1635 * @param col the collection of objects 1636 * @return the merged collection elements, or <code>null</code> if the 1637 * collection is <code>null</code> 1638 */ 1639 public static String merge(Collection<?> col) { 1640 return merge(col, StringPool.COMMA); 1641 } 1642 1643 /** 1644 * Merges the elements of the collection by returning a string representing 1645 * a delimited list of its values. 1646 * 1647 * @param col the collection of objects 1648 * @param delimiter the string whose last index in the string marks where 1649 * to begin the substring 1650 * @return the merged collection elements, or <code>null</code> if the 1651 * collection is <code>null</code> 1652 */ 1653 public static String merge(Collection<?> col, String delimiter) { 1654 if (col == null) { 1655 return null; 1656 } 1657 1658 return merge(col.toArray(new Object[col.size()]), delimiter); 1659 } 1660 1661 /** 1662 * Merges the elements of an array of double-precision decimal numbers by 1663 * returning a string representing a comma delimited list of its values. 1664 * 1665 * @param array the doubles to merge 1666 * @return a string representing a comma delimited list of the values of the 1667 * array of double-precision decimal numbers, an empty string if the 1668 * array is empty, or <code>null</code> if the array is 1669 * <code>null</code> 1670 */ 1671 public static String merge(double[] array) { 1672 return merge(array, StringPool.COMMA); 1673 } 1674 1675 /** 1676 * Merges the elements of an array of double-precision decimal numbers by 1677 * returning a string representing a delimited list of its values. 1678 * 1679 * @param array the doubles to merge 1680 * @param delimiter the delimiter 1681 * @return a string representing a delimited list of the values of the array 1682 * of double-precision decimal numbers, an empty string if the array 1683 * is empty, or <code>null</code> if the array is <code>null</code> 1684 */ 1685 public static String merge(double[] array, String delimiter) { 1686 if (array == null) { 1687 return null; 1688 } 1689 1690 if (array.length == 0) { 1691 return StringPool.BLANK; 1692 } 1693 1694 StringBundler sb = new StringBundler(2 * array.length - 1); 1695 1696 for (int i = 0; i < array.length; i++) { 1697 if (i != 0) { 1698 sb.append(delimiter); 1699 } 1700 1701 sb.append(String.valueOf(array[i])); 1702 } 1703 1704 return sb.toString(); 1705 } 1706 1707 /** 1708 * Merges the elements of an array of decimal numbers into a string 1709 * representing a comma delimited list of its values. 1710 * 1711 * @param array the floats to merge 1712 * @return a string representing a comma delimited list of the values of the 1713 * array of decimal numbers, an empty string if the array is empty, 1714 * or <code>null</code> if the array is <code>null</code> 1715 */ 1716 public static String merge(float[] array) { 1717 return merge(array, StringPool.COMMA); 1718 } 1719 1720 /** 1721 * Merges the elements of an array of decimal numbers into a string 1722 * representing a delimited list of its values. 1723 * 1724 * @param array the floats to merge 1725 * @param delimiter the delimiter 1726 * @return a string representing a delimited list of the values of the array 1727 * of decimal numbers, an empty string if the array is empty, or 1728 * <code>null</code> if the array is <code>null</code> 1729 */ 1730 public static String merge(float[] array, String delimiter) { 1731 if (array == null) { 1732 return null; 1733 } 1734 1735 if (array.length == 0) { 1736 return StringPool.BLANK; 1737 } 1738 1739 StringBundler sb = new StringBundler(2 * array.length - 1); 1740 1741 for (int i = 0; i < array.length; i++) { 1742 if (i != 0) { 1743 sb.append(delimiter); 1744 } 1745 1746 sb.append(String.valueOf(array[i])); 1747 } 1748 1749 return sb.toString(); 1750 } 1751 1752 /** 1753 * Merges the elements of an array of integers into a string representing a 1754 * comma delimited list of its values. 1755 * 1756 * @param array the integers to merge 1757 * @return a string representing a comma delimited list of the values of the 1758 * array of integers, an empty string if the array is empty, or 1759 * <code>null</code> if the array is <code>null</code> 1760 */ 1761 public static String merge(int[] array) { 1762 return merge(array, StringPool.COMMA); 1763 } 1764 1765 /** 1766 * Merges the elements of an array of integers into a string representing a 1767 * delimited list of its values. 1768 * 1769 * @param array the integers to merge 1770 * @param delimiter the delimiter 1771 * @return a string representing a delimited list of the values of the array 1772 * of integers, an empty string if the array is empty, or 1773 * <code>null</code> if the array is <code>null</code> 1774 */ 1775 public static String merge(int[] array, String delimiter) { 1776 if (array == null) { 1777 return null; 1778 } 1779 1780 if (array.length == 0) { 1781 return StringPool.BLANK; 1782 } 1783 1784 StringBundler sb = new StringBundler(2 * array.length - 1); 1785 1786 for (int i = 0; i < array.length; i++) { 1787 if (i != 0) { 1788 sb.append(delimiter); 1789 } 1790 1791 sb.append(String.valueOf(array[i])); 1792 } 1793 1794 return sb.toString(); 1795 } 1796 1797 /** 1798 * Merges the elements of an array of long integers by returning a string 1799 * representing a comma delimited list of its values. 1800 * 1801 * @param array the long integers to merge 1802 * @return a string representing a comma delimited list of the values of the 1803 * array of long integers, an empty string if the array is empty, or 1804 * <code>null</code> if the array is <code>null</code> 1805 */ 1806 public static String merge(long[] array) { 1807 return merge(array, StringPool.COMMA); 1808 } 1809 1810 /** 1811 * Merges the elements of an array of long integers by returning a string 1812 * representing a delimited list of its values. 1813 * 1814 * @param array the long integers to merge 1815 * @param delimiter the delimiter 1816 * @return a string representing a delimited list of the values of the array 1817 * of long integers, an empty string if the array is empty, or 1818 * <code>null</code> if the array is <code>null</code> 1819 */ 1820 public static String merge(long[] array, String delimiter) { 1821 if (array == null) { 1822 return null; 1823 } 1824 1825 if (array.length == 0) { 1826 return StringPool.BLANK; 1827 } 1828 1829 StringBundler sb = new StringBundler(2 * array.length - 1); 1830 1831 for (int i = 0; i < array.length; i++) { 1832 if (i != 0) { 1833 sb.append(delimiter); 1834 } 1835 1836 sb.append(String.valueOf(array[i])); 1837 } 1838 1839 return sb.toString(); 1840 } 1841 1842 /** 1843 * Merges the elements of an array of objects into a string representing a 1844 * comma delimited list of the objects. 1845 * 1846 * @param array the objects to merge 1847 * @return a string representing a comma delimited list of the objects, an 1848 * empty string if the array is empty, or <code>null</code> if the 1849 * array is <code>null</code> 1850 */ 1851 public static String merge(Object[] array) { 1852 return merge(array, StringPool.COMMA); 1853 } 1854 1855 /** 1856 * Merges the elements of an array of objects into a string representing a 1857 * delimited list of the objects. 1858 * 1859 * @param array the objects to merge 1860 * @param delimiter the delimiter 1861 * @return a string representing a delimited list of the objects, an empty 1862 * string if the array is empty, or <code>null</code> if the array 1863 * is <code>null</code> 1864 */ 1865 public static String merge(Object[] array, String delimiter) { 1866 if (array == null) { 1867 return null; 1868 } 1869 1870 if (array.length == 0) { 1871 return StringPool.BLANK; 1872 } 1873 1874 StringBundler sb = new StringBundler(2 * array.length - 1); 1875 1876 for (int i = 0; i < array.length; i++) { 1877 if (i != 0) { 1878 sb.append(delimiter); 1879 } 1880 1881 sb.append(String.valueOf(array[i]).trim()); 1882 } 1883 1884 return sb.toString(); 1885 } 1886 1887 /** 1888 * Merges the elements of an array of short integers by returning a string 1889 * representing a comma delimited list of its values. 1890 * 1891 * @param array the short integers to merge 1892 * @return a string representing a comma delimited list of the values of the 1893 * array of short integers, an empty string if the array is empty, 1894 * or <code>null</code> if the array is <code>null</code> 1895 */ 1896 public static String merge(short[] array) { 1897 return merge(array, StringPool.COMMA); 1898 } 1899 1900 /** 1901 * Merges the elements of an array of short integers by returning a string 1902 * representing a delimited list of its values. 1903 * 1904 * @param array the short integers to merge 1905 * @param delimiter the delimiter 1906 * @return a string representing a delimited list of the values of the array 1907 * of short integers, an empty string if the array is empty, or 1908 * <code>null</code> if the array is <code>null</code> 1909 */ 1910 public static String merge(short[] array, String delimiter) { 1911 if (array == null) { 1912 return null; 1913 } 1914 1915 if (array.length == 0) { 1916 return StringPool.BLANK; 1917 } 1918 1919 StringBundler sb = new StringBundler(2 * array.length - 1); 1920 1921 for (int i = 0; i < array.length; i++) { 1922 if (i != 0) { 1923 sb.append(delimiter); 1924 } 1925 1926 sb.append(String.valueOf(array[i])); 1927 } 1928 1929 return sb.toString(); 1930 } 1931 1932 /** 1933 * Returns the string enclosed by apostrophes. 1934 * 1935 * <p> 1936 * Example: 1937 * </p> 1938 * 1939 * <p> 1940 * <pre> 1941 * <code> 1942 * quote("Hello, World!") returns "'Hello, World!'" 1943 * </code> 1944 * </pre> 1945 * </p> 1946 * 1947 * @param s the string to enclose in apostrophes 1948 * @return the string enclosed by apostrophes, or <code>null</code> if the 1949 * string is <code>null</code> 1950 */ 1951 public static String quote(String s) { 1952 return quote(s, CharPool.APOSTROPHE); 1953 } 1954 1955 /** 1956 * Returns the string enclosed by the quote character. 1957 * 1958 * <p> 1959 * Example: 1960 * </p> 1961 * 1962 * <p> 1963 * <pre> 1964 * <code> 1965 * quote("PATH", '%') returns "%PATH%" 1966 * </code> 1967 * </pre> 1968 * </p> 1969 * 1970 * @param s the string to enclose in quotes 1971 * @param quote the character to insert to insert to the beginning of and 1972 * append to the end of the string 1973 * @return the string enclosed in the quote characters, or <code>null</code> 1974 * if the string is <code>null</code> 1975 */ 1976 public static String quote(String s, char quote) { 1977 if (s == null) { 1978 return null; 1979 } 1980 1981 return quote(s, String.valueOf(quote)); 1982 } 1983 1984 /** 1985 * Returns the string enclosed by the quote strings. 1986 * 1987 * <p> 1988 * Example: 1989 * </p> 1990 * 1991 * <p> 1992 * <pre> 1993 * <code> 1994 * quote("WARNING", "!!!") returns "!!!WARNING!!!" 1995 * </code> 1996 * </pre> 1997 * </p> 1998 * 1999 * @param s the string to enclose in quotes 2000 * @param quote the quote string to insert to insert to the beginning of 2001 * and append to the end of the string 2002 * @return the string enclosed in the quote strings, or <code>null</code> if 2003 * the string is <code>null</code> 2004 */ 2005 public static String quote(String s, String quote) { 2006 if (s == null) { 2007 return null; 2008 } 2009 2010 return quote.concat(s).concat(quote); 2011 } 2012 2013 /** 2014 * Returns a randomized string of four lower case, alphabetic characters. 2015 * 2016 * @return a randomized string of four lower case, alphabetic characters 2017 */ 2018 public static String randomId() { 2019 Random random = new Random(); 2020 2021 char[] chars = new char[4]; 2022 2023 for (int i = 0; i < 4; i++) { 2024 chars[i] = (char)(CharPool.LOWER_CASE_A + random.nextInt(26)); 2025 } 2026 2027 return new String(chars); 2028 } 2029 2030 /** 2031 * Pseudorandomly permutes the characters of the string. 2032 * 2033 * @param s the string whose characters are to be randomized 2034 * @return a string of the same length as the string whose characters 2035 * represent a pseudorandom permutation of the characters of the 2036 * string 2037 */ 2038 public static String randomize(String s) { 2039 return RandomUtil.shuffle(s); 2040 } 2041 2042 /** 2043 * Returns a randomized string of eight characters consisting of lower case 2044 * letters, upper case letters, and single-digit whole numbers. 2045 * 2046 * @return a randomized string of eight characters consisting of lower case 2047 * letters, upper case letters, and single-digit whole numbers 2048 */ 2049 public static String randomString() { 2050 return randomString(8); 2051 } 2052 2053 /** 2054 * Returns a randomized string of the specified length consisting of lower 2055 * case letters, upper case letters, and single-digit whole numbers. 2056 * 2057 * @param length the character length of the randomized string 2058 * @return a randomized string of the specified length consisting of lower 2059 * case letters, upper case letters, and single-digit whole numbers 2060 */ 2061 public static String randomString(int length) { 2062 Random random = new Random(); 2063 2064 char[] chars = new char[length]; 2065 2066 for (int i = 0; i < length; i++) { 2067 int index = random.nextInt(_RANDOM_STRING_CHAR_TABLE.length); 2068 2069 chars[i] = _RANDOM_STRING_CHAR_TABLE[index]; 2070 } 2071 2072 return new String(chars); 2073 } 2074 2075 public static String read(ClassLoader classLoader, String name) 2076 throws IOException { 2077 2078 return read(classLoader, name, false); 2079 } 2080 2081 public static String read(ClassLoader classLoader, String name, boolean all) 2082 throws IOException { 2083 2084 if (all) { 2085 StringBundler sb = new StringBundler(); 2086 2087 Enumeration<URL> enu = classLoader.getResources(name); 2088 2089 while (enu.hasMoreElements()) { 2090 URL url = enu.nextElement(); 2091 2092 InputStream is = url.openStream(); 2093 2094 if (is == null) { 2095 throw new IOException( 2096 "Unable to open resource at " + url.toString()); 2097 } 2098 2099 try { 2100 String s = read(is); 2101 2102 if (s != null) { 2103 sb.append(s); 2104 sb.append(StringPool.NEW_LINE); 2105 } 2106 } 2107 finally { 2108 StreamUtil.cleanUp(is); 2109 } 2110 } 2111 2112 return sb.toString().trim(); 2113 } 2114 2115 InputStream is = classLoader.getResourceAsStream(name); 2116 2117 if (is == null) { 2118 throw new IOException( 2119 "Unable to open resource in class loader " + name); 2120 } 2121 2122 try { 2123 String s = read(is); 2124 2125 return s; 2126 } 2127 finally { 2128 StreamUtil.cleanUp(is); 2129 } 2130 } 2131 2132 public static String read(InputStream is) throws IOException { 2133 StringBundler sb = new StringBundler(); 2134 2135 try (UnsyncBufferedReader unsyncBufferedReader = 2136 new UnsyncBufferedReader(new InputStreamReader(is))) { 2137 2138 String line = null; 2139 2140 while ((line = unsyncBufferedReader.readLine()) != null) { 2141 sb.append(line); 2142 sb.append(CharPool.NEW_LINE); 2143 } 2144 } 2145 2146 return sb.toString().trim(); 2147 } 2148 2149 public static void readLines(InputStream is, Collection<String> lines) 2150 throws IOException { 2151 2152 try (UnsyncBufferedReader unsyncBufferedReader = 2153 new UnsyncBufferedReader(new InputStreamReader(is))) { 2154 2155 String line = null; 2156 2157 while ((line = unsyncBufferedReader.readLine()) != null) { 2158 lines.add(line); 2159 } 2160 } 2161 } 2162 2163 /** 2164 * @deprecated As of 7.0.0, replaced by {@link #removeFromList(String, 2165 * String)} 2166 */ 2167 @Deprecated 2168 public static String remove(String s, String element) { 2169 return removeFromList(s, element, StringPool.COMMA); 2170 } 2171 2172 /** 2173 * @deprecated As of 7.0.0, replaced by {@link #removeFromList(String, 2174 * String, String)} 2175 */ 2176 @Deprecated 2177 public static String remove(String s, String element, String delimiter) { 2178 return removeFromList(s, element, delimiter); 2179 } 2180 2181 /** 2182 * Removes the <code>remove</code> string from string <code>s</code> that 2183 * represents a list of comma delimited strings. 2184 * 2185 * <p> 2186 * The resulting string ends with a comma even if the original string does 2187 * not. 2188 * </p> 2189 * 2190 * <p> 2191 * Examples: 2192 * </p> 2193 * 2194 * <p> 2195 * <pre> 2196 * <code> 2197 * remove("red,blue,green,yellow", "blue") returns "red,green,yellow," 2198 * remove("blue", "blue") returns "" 2199 * remove("blue,", "blue") returns "" 2200 * </code> 2201 * </pre> 2202 * </p> 2203 * 2204 * @param s the string representing the list of comma delimited strings 2205 * @param element the string to remove 2206 * @return a string representing the list of comma delimited strings with 2207 * the <code>remove</code> string removed, or <code>null</code> if 2208 * the original string, the string to remove, or the delimiter is 2209 * <code>null</code> 2210 */ 2211 public static String removeFromList(String s, String element) { 2212 return removeFromList(s, element, StringPool.COMMA); 2213 } 2214 2215 /** 2216 * Removes the <code>remove</code> string from string <code>s</code> that 2217 * represents a list of delimited strings. 2218 * 2219 * <p> 2220 * The resulting string ends with the delimiter even if the original string 2221 * does not. 2222 * </p> 2223 * 2224 * <p> 2225 * Examples: 2226 * </p> 2227 * 2228 * <p> 2229 * <pre> 2230 * <code> 2231 * remove("red;blue;green;yellow", "blue", ";") returns "red;green;yellow;" 2232 * remove("blue", "blue", ";") returns "" 2233 * remove("blue;", "blue", ";") returns "" 2234 * </code> 2235 * </pre> 2236 * </p> 2237 * 2238 * @param s the string representing the list of delimited strings 2239 * @param element the string to remove 2240 * @param delimiter the delimiter 2241 * @return a string representing the list of delimited strings with the 2242 * <code>remove</code> string removed, or <code>null</code> if the 2243 * original string, the string to remove, or the delimiter is 2244 * <code>null</code> 2245 */ 2246 public static String removeFromList( 2247 String s, String element, String delimiter) { 2248 2249 if ((s == null) || (element == null) || (delimiter == null)) { 2250 return null; 2251 } 2252 2253 if (Validator.isNotNull(s) && !s.endsWith(delimiter)) { 2254 s += delimiter; 2255 } 2256 2257 String drd = delimiter.concat(element).concat(delimiter); 2258 2259 String rd = element.concat(delimiter); 2260 2261 while (contains(s, element, delimiter)) { 2262 int pos = s.indexOf(drd); 2263 2264 if (pos == -1) { 2265 if (s.startsWith(rd)) { 2266 int x = element.length() + delimiter.length(); 2267 int y = s.length(); 2268 2269 s = s.substring(x, y); 2270 } 2271 } 2272 else { 2273 int x = pos + element.length() + delimiter.length(); 2274 int y = s.length(); 2275 2276 String temp = s.substring(0, pos); 2277 2278 s = temp.concat(s.substring(x, y)); 2279 } 2280 } 2281 2282 return s; 2283 } 2284 2285 /** 2286 * Replaces all occurrences of the character with the new character. 2287 * 2288 * @param s the original string 2289 * @param oldSub the character to be searched for and replaced in the 2290 * original string 2291 * @param newSub the character with which to replace the 2292 * <code>oldSub</code> character 2293 * @return a string representing the original string with all occurrences of 2294 * the <code>oldSub</code> character replaced with the 2295 * <code>newSub</code> character, or <code>null</code> if the 2296 * original string is <code>null</code> 2297 */ 2298 public static String replace(String s, char oldSub, char newSub) { 2299 if (s == null) { 2300 return null; 2301 } 2302 2303 return s.replace(oldSub, newSub); 2304 } 2305 2306 /** 2307 * Replaces all occurrences of the character with the new string. 2308 * 2309 * @param s the original string 2310 * @param oldSub the character to be searched for and replaced in the 2311 * original string 2312 * @param newSub the string with which to replace the <code>oldSub</code> 2313 * character 2314 * @return a string representing the original string with all occurrences of 2315 * the <code>oldSub</code> character replaced with the string 2316 * <code>newSub</code>, or <code>null</code> if the original string 2317 * is <code>null</code> 2318 */ 2319 public static String replace(String s, char oldSub, String newSub) { 2320 if ((s == null) || (newSub == null)) { 2321 return null; 2322 } 2323 2324 // The number 5 is arbitrary and is used as extra padding to reduce 2325 // buffer expansion 2326 2327 StringBundler sb = new StringBundler(s.length() + 5 * newSub.length()); 2328 2329 char[] chars = s.toCharArray(); 2330 2331 for (char c : chars) { 2332 if (c == oldSub) { 2333 sb.append(newSub); 2334 } 2335 else { 2336 sb.append(c); 2337 } 2338 } 2339 2340 return sb.toString(); 2341 } 2342 2343 /** 2344 * Replaces all occurrences of the string with the new string. 2345 * 2346 * @param s the original string 2347 * @param oldSub the string to be searched for and replaced in the original 2348 * string 2349 * @param newSub the string with which to replace the <code>oldSub</code> 2350 * string 2351 * @return a string representing the original string with all occurrences of 2352 * the <code>oldSub</code> string replaced with the string 2353 * <code>newSub</code>, or <code>null</code> if the original string 2354 * is <code>null</code> 2355 */ 2356 public static String replace(String s, String oldSub, String newSub) { 2357 return replace(s, oldSub, newSub, 0); 2358 } 2359 2360 /** 2361 * Replaces all occurrences of the string with the new string, starting from 2362 * the specified index. 2363 * 2364 * @param s the original string 2365 * @param oldSub the string to be searched for and replaced in the original 2366 * string 2367 * @param newSub the string with which to replace the <code>oldSub</code> 2368 * string 2369 * @param fromIndex the index of the original string from which to begin 2370 * searching 2371 * @return a string representing the original string with all occurrences of 2372 * the <code>oldSub</code> string occurring after the specified 2373 * index replaced with the string <code>newSub</code>, or 2374 * <code>null</code> if the original string is <code>null</code> 2375 */ 2376 public static String replace( 2377 String s, String oldSub, String newSub, int fromIndex) { 2378 2379 if (s == null) { 2380 return null; 2381 } 2382 2383 if ((oldSub == null) || oldSub.equals(StringPool.BLANK)) { 2384 return s; 2385 } 2386 2387 if (newSub == null) { 2388 newSub = StringPool.BLANK; 2389 } 2390 2391 int y = s.indexOf(oldSub, fromIndex); 2392 2393 if (y >= 0) { 2394 StringBundler sb = new StringBundler(); 2395 2396 int length = oldSub.length(); 2397 int x = 0; 2398 2399 while (x <= y) { 2400 sb.append(s.substring(x, y)); 2401 sb.append(newSub); 2402 2403 x = y + length; 2404 y = s.indexOf(oldSub, x); 2405 } 2406 2407 sb.append(s.substring(x)); 2408 2409 return sb.toString(); 2410 } 2411 else { 2412 return s; 2413 } 2414 } 2415 2416 /** 2417 * Replaces all occurrences of the keywords found in the substring, defined 2418 * by the beginning and ending strings, with the new values. 2419 * 2420 * <p> 2421 * For example, with the following initialized variables: 2422 * </p> 2423 * 2424 * <p> 2425 * <pre> 2426 * <code> 2427 * String s = "http://www.example-url/${userId}"; 2428 * String begin = "${"; 2429 * String end = "}"; 2430 * Map<String, String> values = new HashMap<String, String>(); 2431 * values.put("userId", "jbloggs"); 2432 * </code> 2433 * </pre> 2434 * </p> 2435 * 2436 * <p> 2437 * <code>replace(s, begin, end, values)</code> returns 2438 * <code>"http://www.example-url/jbloggs"</code> 2439 * </p> 2440 * 2441 * @param s the original string 2442 * @param begin the string preceding the substring to be modified. This 2443 * string is excluded from the result. 2444 * @param end the string following the substring to be modified. This 2445 * string is excluded from the result. 2446 * @param values the key-value map values 2447 * @return a string representing the original string with all occurrences of 2448 * the of the keywords found in the substring, replaced with the new 2449 * values. <code>null</code> is returned if the original string, the 2450 * beginning string, the ending string, or the key-map values are 2451 * <code>null</code>. 2452 */ 2453 public static String replace( 2454 String s, String begin, String end, Map<String, String> values) { 2455 2456 StringBundler sb = replaceToStringBundler(s, begin, end, values); 2457 2458 return sb.toString(); 2459 } 2460 2461 /** 2462 * Replaces all occurrences of the elements of the string array with the 2463 * corresponding elements of the new string array. 2464 * 2465 * @param s the original string 2466 * @param oldSubs the strings to be searched for and replaced in the 2467 * original string 2468 * @param newSubs the strings with which to replace the 2469 * <code>oldSubs</code> strings 2470 * @return a string representing the original string with all occurrences of 2471 * the <code>oldSubs</code> strings replaced with the corresponding 2472 * <code>newSubs</code> strings, or <code>null</code> if the 2473 * original string, the <code>oldSubs</code> array, or the 2474 * <code>newSubs</code> is <code>null</code> 2475 */ 2476 public static String replace(String s, String[] oldSubs, String[] newSubs) { 2477 if ((s == null) || (oldSubs == null) || (newSubs == null)) { 2478 return null; 2479 } 2480 2481 if (oldSubs.length != newSubs.length) { 2482 return s; 2483 } 2484 2485 for (int i = 0; i < oldSubs.length; i++) { 2486 s = replace(s, oldSubs[i], newSubs[i]); 2487 } 2488 2489 return s; 2490 } 2491 2492 /** 2493 * Replaces all occurrences of the elements of the string array with the 2494 * corresponding elements of the new string array, optionally replacing only 2495 * substrings that are surrounded by word boundaries. 2496 * 2497 * <p> 2498 * Examples: 2499 * </p> 2500 * 2501 * <p> 2502 * <pre> 2503 * <code> 2504 * replace("redorangeyellow", {"red", "orange", "yellow"}, {"RED","ORANGE", "YELLOW"}, false) returns "REDORANGEYELLOW" 2505 * replace("redorangeyellow", {"red", "orange", "yellow"}, {"RED","ORANGE", "YELLOW"}, true) returns "redorangeyellow" 2506 * replace("redorange yellow", {"red", "orange", "yellow"}, {"RED","ORANGE", "YELLOW"}, false) returns "REDORANGE YELLOW" 2507 * replace("redorange yellow", {"red", "orange", "yellow"}, {"RED","ORANGE", "YELLOW"}, true) returns "redorange YELLOW" 2508 * replace("red orange yellow", {"red", "orange", "yellow"}, {"RED","ORANGE", "YELLOW"}, false) returns "RED ORANGE YELLOW" 2509 * replace("redorange.yellow", {"red", "orange", "yellow"}, {"RED","ORANGE", * "YELLOW"}, true) returns "redorange.YELLOW" 2510 * </code> 2511 * </pre> 2512 * </p> 2513 * 2514 * @param s the original string 2515 * @param oldSubs the strings to be searched for and replaced in the 2516 * original string 2517 * @param newSubs the strings with which to replace the 2518 * <code>oldSubs</code> strings 2519 * @param exactMatch whether or not to replace only substrings of 2520 * <code>s</code> that are surrounded by word boundaries 2521 * @return if <code>exactMatch</code> is <code>true</code>, a string 2522 * representing the original string with all occurrences of the 2523 * <code>oldSubs</code> strings that are surrounded by word 2524 * boundaries replaced with the corresponding <code>newSubs</code> 2525 * strings, or else a string representing the original string with 2526 * all occurrences of the <code>oldSubs</code> strings replaced with 2527 * the corresponding <code>newSubs</code> strings, or 2528 * <code>null</code> if the original string, the 2529 * <code>oldSubs</code> array, or the <code>newSubs</code> is 2530 * <code>null</code> 2531 */ 2532 public static String replace( 2533 String s, String[] oldSubs, String[] newSubs, boolean exactMatch) { 2534 2535 if ((s == null) || (oldSubs == null) || (newSubs == null)) { 2536 return null; 2537 } 2538 2539 if (oldSubs.length != newSubs.length) { 2540 return s; 2541 } 2542 2543 if (!exactMatch) { 2544 return replace(s, oldSubs, newSubs); 2545 } 2546 2547 for (int i = 0; i < oldSubs.length; i++) { 2548 s = s.replaceAll("\\b" + oldSubs[i] + "\\b", newSubs[i]); 2549 } 2550 2551 return s; 2552 } 2553 2554 /** 2555 * Replaces the first occurrence of the character with the new character. 2556 * 2557 * @param s the original string 2558 * @param oldSub the character whose first occurrence in the original 2559 * string is to be searched for and replaced 2560 * @param newSub the character with which to replace the first occurrence 2561 * of the <code>oldSub</code> character 2562 * @return a string representing the original string except with the first 2563 * occurrence of the character <code>oldSub</code> replaced with the 2564 * character <code>newSub</code> 2565 */ 2566 public static String replaceFirst(String s, char oldSub, char newSub) { 2567 if (s == null) { 2568 return null; 2569 } 2570 2571 return replaceFirst(s, String.valueOf(oldSub), String.valueOf(newSub)); 2572 } 2573 2574 /** 2575 * Replaces the first occurrence of the character with the new string. 2576 * 2577 * @param s the original string 2578 * @param oldSub the character whose first occurrence in the original 2579 * string is to be searched for and replaced 2580 * @param newSub the string with which to replace the first occurrence of 2581 * the <code>oldSub</code> character 2582 * @return a string representing the original string except with the first 2583 * occurrence of the character <code>oldSub</code> replaced with the 2584 * string <code>newSub</code> 2585 */ 2586 public static String replaceFirst(String s, char oldSub, String newSub) { 2587 if ((s == null) || (newSub == null)) { 2588 return null; 2589 } 2590 2591 return replaceFirst(s, String.valueOf(oldSub), newSub); 2592 } 2593 2594 /** 2595 * Replaces the first occurrence of the string with the new string. 2596 * 2597 * @param s the original string 2598 * @param oldSub the string whose first occurrence in the original string 2599 * is to be searched for and replaced 2600 * @param newSub the string with which to replace the first occurrence of 2601 * the <code>oldSub</code> string 2602 * @return a string representing the original string except with the first 2603 * occurrence of the string <code>oldSub</code> replaced with the 2604 * string <code>newSub</code> 2605 */ 2606 public static String replaceFirst(String s, String oldSub, String newSub) { 2607 return replaceFirst(s, oldSub, newSub, 0); 2608 } 2609 2610 /** 2611 * Replaces the first occurrences of the elements of the string array with 2612 * the corresponding elements of the new string array, beginning the element 2613 * search from the index position. 2614 * 2615 * @param s the original string 2616 * @param oldSub the strings whose first occurrences are to be searched for 2617 * and replaced in the original string 2618 * @param newSub the strings with which to replace the first occurrences of 2619 * the <code>oldSubs</code> strings 2620 * @param fromIndex the start index within the string 2621 * @return a string representing the original string with the first 2622 * occurrences of the <code>oldSubs</code> strings replaced with the 2623 * corresponding <code>newSubs</code> strings, or <code>null</code> 2624 * if the original string, the <code>oldSubs</code> string, or the 2625 * <code>newSubs</code> string is <code>null</code> 2626 */ 2627 public static String replaceFirst( 2628 String s, String oldSub, String newSub, int fromIndex) { 2629 2630 if ((s == null) || (oldSub == null) || (newSub == null)) { 2631 return null; 2632 } 2633 2634 if (oldSub.equals(newSub)) { 2635 return s; 2636 } 2637 2638 int y = s.indexOf(oldSub, fromIndex); 2639 2640 if (y >= 0) { 2641 return s.substring(0, y).concat(newSub).concat( 2642 s.substring(y + oldSub.length())); 2643 } 2644 else { 2645 return s; 2646 } 2647 } 2648 2649 /** 2650 * Replaces the first occurrences of the elements of the string array with 2651 * the corresponding elements of the new string array. 2652 * 2653 * @param s the original string 2654 * @param oldSubs the strings whose first occurrences are to be searched 2655 * for and replaced in the original string 2656 * @param newSubs the strings with which to replace the first occurrences 2657 * of the <code>oldSubs</code> strings 2658 * @return a string representing the original string with the first 2659 * occurrences of the <code>oldSubs</code> strings replaced with the 2660 * corresponding <code>newSubs</code> strings, or <code>null</code> 2661 * if the original string, the <code>oldSubs</code> array, or the 2662 * <code>newSubs</code> is <code>null</code> 2663 */ 2664 public static String replaceFirst( 2665 String s, String[] oldSubs, String[] newSubs) { 2666 2667 if ((s == null) || (oldSubs == null) || (newSubs == null)) { 2668 return null; 2669 } 2670 2671 if (oldSubs.length != newSubs.length) { 2672 return s; 2673 } 2674 2675 for (int i = 0; i < oldSubs.length; i++) { 2676 s = replaceFirst(s, oldSubs[i], newSubs[i]); 2677 } 2678 2679 return s; 2680 } 2681 2682 /** 2683 * Replaces the last occurrence of the character with the new character. 2684 * 2685 * @param s the original string 2686 * @param oldSub the character whose last occurrence in the original string 2687 * is to be searched for and replaced 2688 * @param newSub the character with which to replace the last occurrence of 2689 * the <code>oldSub</code> character 2690 * @return a string representing the original string except with the first 2691 * occurrence of the character <code>oldSub</code> replaced with the 2692 * character <code>newSub</code> 2693 */ 2694 public static String replaceLast(String s, char oldSub, char newSub) { 2695 if (s == null) { 2696 return null; 2697 } 2698 2699 return replaceLast(s, String.valueOf(oldSub), String.valueOf(newSub)); 2700 } 2701 2702 /** 2703 * Replaces the last occurrence of the character with the new string. 2704 * 2705 * @param s the original string 2706 * @param oldSub the character whose last occurrence in the original string 2707 * is to be searched for and replaced 2708 * @param newSub the string with which to replace the last occurrence of 2709 * the <code>oldSub</code> character 2710 * @return a string representing the original string except with the last 2711 * occurrence of the character <code>oldSub</code> replaced with the 2712 * string <code>newSub</code> 2713 */ 2714 public static String replaceLast(String s, char oldSub, String newSub) { 2715 if ((s == null) || (newSub == null)) { 2716 return null; 2717 } 2718 2719 return replaceLast(s, String.valueOf(oldSub), newSub); 2720 } 2721 2722 /** 2723 * Replaces the last occurrence of the string <code>oldSub</code> in the 2724 * string <code>s</code> with the string <code>newSub</code>. 2725 * 2726 * @param s the original string 2727 * @param oldSub the string whose last occurrence in the original string is 2728 * to be searched for and replaced 2729 * @param newSub the string with which to replace the last occurrence of 2730 * the <code>oldSub</code> string 2731 * @return a string representing the original string except with the last 2732 * occurrence of the string <code>oldSub</code> replaced with the 2733 * string <code>newSub</code> 2734 */ 2735 public static String replaceLast(String s, String oldSub, String newSub) { 2736 if ((s == null) || (oldSub == null) || (newSub == null)) { 2737 return null; 2738 } 2739 2740 if (oldSub.equals(newSub)) { 2741 return s; 2742 } 2743 2744 int y = s.lastIndexOf(oldSub); 2745 2746 if (y >= 0) { 2747 return s.substring(0, y).concat(newSub).concat( 2748 s.substring(y + oldSub.length())); 2749 } 2750 else { 2751 return s; 2752 } 2753 } 2754 2755 /** 2756 * Replaces the last occurrences of the elements of the string array with 2757 * the corresponding elements of the new string array. 2758 * 2759 * @param s the original string 2760 * @param oldSubs the strings whose last occurrences are to be searched for 2761 * and replaced in the original string 2762 * @param newSubs the strings with which to replace the last occurrences of 2763 * the <code>oldSubs</code> strings 2764 * @return a string representing the original string with the last 2765 * occurrences of the <code>oldSubs</code> strings replaced with the 2766 * corresponding <code>newSubs</code> strings, or <code>null</code> 2767 * if the original string, the <code>oldSubs</code> array, or the 2768 * <code>newSubs</code> is <code>null</code> 2769 */ 2770 public static String replaceLast( 2771 String s, String[] oldSubs, String[] newSubs) { 2772 2773 if ((s == null) || (oldSubs == null) || (newSubs == null)) { 2774 return null; 2775 } 2776 2777 if (oldSubs.length != newSubs.length) { 2778 return s; 2779 } 2780 2781 for (int i = 0; i < oldSubs.length; i++) { 2782 s = replaceLast(s, oldSubs[i], newSubs[i]); 2783 } 2784 2785 return s; 2786 } 2787 2788 /** 2789 * Replaces all occurrences of the keywords found in the substring, defined 2790 * by the beginning and ending strings, with the new values. The result is 2791 * returned as a {@link StringBundler}. 2792 * 2793 * <p> 2794 * For example, with the following initialized variables: 2795 * </p> 2796 * 2797 * <p> 2798 * <pre> 2799 * <code> 2800 * String s = "http://www.example-url/${userId}"; 2801 * String begin = "${"; 2802 * String end = "}"; 2803 * Map<String, String> values = new HashMap<String, String>(); 2804 * values.put("userId", "jbloggs"); 2805 * </code> 2806 * </pre> 2807 * </p> 2808 * 2809 * <p> 2810 * <code>StringBundler sb = replaceToStringBundler(s, begin, end, 2811 * values)</code> <code>sb.toString()</code> returns 2812 * <code>"http://www.example-url/jbloggs"</code> 2813 * </p> 2814 * 2815 * @param s the original string 2816 * @param begin the string preceding the substring to be modified. This 2817 * string is excluded from the result. 2818 * @param end the string following the substring to be modified. This 2819 * string is excluded from the result. 2820 * @param values the key-value map values 2821 * @return a string bundler representing the original string with all 2822 * occurrences of the keywords found in the substring, replaced with 2823 * the new values. <code>null</code> is returned if the original 2824 * string, the beginning string, the ending string, or the key-map 2825 * values are <code>null</code>. 2826 * @see #replace(String, String, String, Map) 2827 */ 2828 public static StringBundler replaceToStringBundler( 2829 String s, String begin, String end, Map<String, String> values) { 2830 2831 if (Validator.isBlank(s) || Validator.isBlank(begin) || 2832 Validator.isBlank(end) || MapUtil.isEmpty(values)) { 2833 2834 return new StringBundler(s); 2835 } 2836 2837 StringBundler sb = new StringBundler(values.size() * 2 + 1); 2838 2839 int pos = 0; 2840 2841 while (true) { 2842 int x = s.indexOf(begin, pos); 2843 int y = s.indexOf(end, x + begin.length()); 2844 2845 if ((x == -1) || (y == -1)) { 2846 sb.append(s.substring(pos)); 2847 2848 break; 2849 } 2850 else { 2851 sb.append(s.substring(pos, x)); 2852 2853 String oldValue = s.substring(x + begin.length(), y); 2854 2855 String newValue = values.get(oldValue); 2856 2857 if (newValue == null) { 2858 newValue = oldValue; 2859 } 2860 2861 sb.append(newValue); 2862 2863 pos = y + end.length(); 2864 } 2865 } 2866 2867 return sb; 2868 } 2869 2870 /** 2871 * Replaces all occurrences of the keywords found in the substring, defined 2872 * by the beginning and ending strings, with the new values. The result is 2873 * returned as a {@link StringBundler}. 2874 * 2875 * @param s the original string 2876 * @param begin the string preceding the substring to be modified. This 2877 * string is removed from the result. 2878 * @param end the string following the substring to be modified. This 2879 * string is removed from the result. 2880 * @param values the key-value map values, which has string keys and {@link 2881 * StringBundler} values 2882 * @return a string bundler representing the original string with all 2883 * occurrences of the keywords found in the substring, replaced with 2884 * the new values. <code>null</code> is returned if the original 2885 * string, the beginning string, the ending string, or the key-map 2886 * values are <code>null</code>. 2887 */ 2888 public static StringBundler replaceWithStringBundler( 2889 String s, String begin, String end, Map<String, StringBundler> values) { 2890 2891 if (Validator.isBlank(s) || Validator.isBlank(begin) || 2892 Validator.isBlank(end) || MapUtil.isEmpty(values)) { 2893 2894 return new StringBundler(s); 2895 } 2896 2897 int size = values.size() + 1; 2898 2899 for (StringBundler valueSB : values.values()) { 2900 size += valueSB.index(); 2901 } 2902 2903 StringBundler sb = new StringBundler(size); 2904 2905 int pos = 0; 2906 2907 while (true) { 2908 int x = s.indexOf(begin, pos); 2909 int y = s.indexOf(end, x + begin.length()); 2910 2911 if ((x == -1) || (y == -1)) { 2912 sb.append(s.substring(pos)); 2913 2914 break; 2915 } 2916 else { 2917 sb.append(s.substring(pos, x)); 2918 2919 String oldValue = s.substring(x + begin.length(), y); 2920 2921 StringBundler newValue = values.get(oldValue); 2922 2923 if (newValue == null) { 2924 sb.append(oldValue); 2925 } 2926 else { 2927 sb.append(newValue); 2928 } 2929 2930 pos = y + end.length(); 2931 } 2932 } 2933 2934 return sb; 2935 } 2936 2937 /** 2938 * Reverses the order of the characters of the string. 2939 * 2940 * @param s the original string 2941 * @return a string representing the original string with characters in 2942 * reverse order 2943 */ 2944 public static String reverse(String s) { 2945 if (s == null) { 2946 return null; 2947 } 2948 2949 char[] chars = s.toCharArray(); 2950 char[] reverse = new char[chars.length]; 2951 2952 for (int i = 0; i < chars.length; i++) { 2953 reverse[i] = chars[chars.length - i - 1]; 2954 } 2955 2956 return new String(reverse); 2957 } 2958 2959 /** 2960 * Replaces all double slashes of the string with single slashes. 2961 * 2962 * <p> 2963 * Example: 2964 * </p> 2965 * 2966 * <p> 2967 * <pre> 2968 * <code> 2969 * safePath("http://www.liferay.com") returns "http:/www.liferay.com" 2970 * </code> 2971 * </pre> 2972 * </p> 2973 * 2974 * @param path the original string 2975 * @return a string representing the original string with all double slashes 2976 * replaced with single slashes 2977 */ 2978 public static String safePath(String path) { 2979 return replace(path, StringPool.DOUBLE_SLASH, StringPool.SLASH); 2980 } 2981 2982 /** 2983 * Returns a string representing the original string appended with suffix 2984 * "..." and then shortened to 20 characters. 2985 * 2986 * <p> 2987 * The suffix is only added if the original string exceeds 20 characters. If 2988 * the original string exceeds 20 characters and it contains whitespace, the 2989 * string is shortened at the first whitespace character. 2990 * </p> 2991 * 2992 * <p> 2993 * Examples: 2994 * </p> 2995 * 2996 * <p> 2997 * <pre> 2998 * <code> 2999 * shorten("12345678901234567890xyz") returns "12345678901234567..." 3000 * shorten("1 345678901234567890xyz") returns "1..." 3001 * shorten(" 2345678901234567890xyz") returns "..." 3002 * shorten("12345678901234567890") returns "12345678901234567890" 3003 * shorten(" 2345678901234567890") returns " 2345678901234567890" 3004 * </code> 3005 * </pre> 3006 * </p> 3007 * 3008 * @param s the original string 3009 * @return a string representing the original string shortened to 20 3010 * characters, with suffix "..." appended to it 3011 */ 3012 public static String shorten(String s) { 3013 return shorten(s, 20); 3014 } 3015 3016 /** 3017 * Returns a string representing the original string appended with suffix 3018 * "..." and then shortened to the specified length. 3019 * 3020 * <p> 3021 * The suffix is only added if the original string exceeds the specified 3022 * length. If the original string exceeds the specified length and it 3023 * contains whitespace, the string is shortened at the first whitespace 3024 * character. 3025 * </p> 3026 * 3027 * <p> 3028 * Examples: 3029 * </p> 3030 * 3031 * <p> 3032 * <pre> 3033 * <code> 3034 * shorten("123456789", 8) returns "12345..." 3035 * shorten("1 3456789", 8) returns "1..." 3036 * shorten(" 23456789", 8) returns "..." 3037 * shorten("12345678", 8) returns "12345678" 3038 * shorten(" 1234567", 8) returns " 1234567" 3039 * </code> 3040 * </pre> 3041 * </p> 3042 * 3043 * @param s the original string 3044 * @param length the number of characters to limit from the original string 3045 * @return a string representing the original string shortened to the 3046 * specified length, with suffix "..." appended to it 3047 */ 3048 public static String shorten(String s, int length) { 3049 return shorten(s, length, "..."); 3050 } 3051 3052 /** 3053 * Returns a string representing the original string appended with the 3054 * specified suffix and then shortened to the specified length. 3055 * 3056 * <p> 3057 * The suffix is only added if the original string exceeds the specified 3058 * length. If the original string exceeds the specified length and it 3059 * contains whitespace, the string is shortened at the first whitespace 3060 * character. 3061 * </p> 3062 * 3063 * <p> 3064 * Examples: 3065 * </p> 3066 * 3067 * <p> 3068 * <pre> 3069 * <code> 3070 * shorten("12345678901234", 13, "... etc.") returns "12345... etc." 3071 * shorten("1 345678901234", 13, "... etc.") returns "1... etc." 3072 * shorten(" 2345678901234", 13, "... etc.") returns "... etc." 3073 * shorten("1234567890123", 13, "... etc.") returns "1234567890123" 3074 * shorten(" 123456789012", 13, "... etc.") returns " 123456789012" 3075 * </code> 3076 * </pre> 3077 * </p> 3078 * 3079 * @param s the original string 3080 * @param length the number of characters to limit from the original string 3081 * @param suffix the suffix to append 3082 * @return a string representing the original string shortened to the 3083 * specified length, with the specified suffix appended to it 3084 */ 3085 public static String shorten(String s, int length, String suffix) { 3086 if ((s == null) || (suffix == null)) { 3087 return null; 3088 } 3089 3090 if (s.length() <= length) { 3091 return s; 3092 } 3093 3094 if (length < suffix.length()) { 3095 return s.substring(0, length); 3096 } 3097 3098 int curLength = length; 3099 3100 for (int j = (curLength - suffix.length()); j >= 0; j--) { 3101 if (Character.isWhitespace(s.charAt(j))) { 3102 curLength = j; 3103 3104 break; 3105 } 3106 } 3107 3108 if (curLength == length) { 3109 curLength = length - suffix.length(); 3110 } 3111 3112 String temp = s.substring(0, curLength); 3113 3114 return temp.concat(suffix); 3115 } 3116 3117 /** 3118 * Returns a string representing the original string appended with the 3119 * specified suffix and then shortened to 20 characters. 3120 * 3121 * <p> 3122 * The suffix is only added if the original string exceeds 20 characters. If 3123 * the original string exceeds 20 characters and it contains whitespace, the 3124 * string is shortened at the first whitespace character. 3125 * </p> 3126 * 3127 * <p> 3128 * Examples: 3129 * </p> 3130 * 3131 * <p> 3132 * <pre> 3133 * <code> 3134 * shorten("12345678901234567890xyz", "... etc.") returns "123456789012... etc." 3135 * shorten("1 345678901234567890xyz", "... etc.") returns "1... etc." 3136 * shorten(" 2345678901234567890xyz", "... etc.") returns "... etc." 3137 * shorten("12345678901234567890", "... etc.") returns "12345678901234567890" 3138 * shorten(" 2345678901234567890", "... etc.") returns " 2345678901234567890" 3139 * </code> 3140 * </pre> 3141 * </p> 3142 * 3143 * @param s the original string 3144 * @param suffix the suffix to append 3145 * @return a string representing the original string shortened to 20 3146 * characters, with the specified suffix appended to it 3147 */ 3148 public static String shorten(String s, String suffix) { 3149 return shorten(s, 20, suffix); 3150 } 3151 3152 /** 3153 * Splits string <code>s</code> around comma characters. 3154 * 3155 * <p> 3156 * Example: 3157 * </p> 3158 * 3159 * <p> 3160 * <pre> 3161 * <code> 3162 * split("Alice,Bob,Charlie") returns {"Alice", "Bob", "Charlie"} 3163 * split("Alice, Bob, Charlie") returns {"Alice", " Bob", " Charlie"} 3164 * </code> 3165 * </pre> 3166 * </p> 3167 * 3168 * @param s the string to split 3169 * @return the array of strings resulting from splitting string 3170 * <code>s</code> around comma characters, or an empty string array 3171 * if <code>s</code> is <code>null</code> or <code>s</code> is empty 3172 */ 3173 public static String[] split(String s) { 3174 return split(s, CharPool.COMMA); 3175 } 3176 3177 /** 3178 * Splits the string <code>s</code> around comma characters returning the 3179 * boolean values of the substrings. 3180 * 3181 * @param s the string to split 3182 * @param x the default value to use for a substring in case an exception 3183 * occurs in getting the boolean value for that substring 3184 * @return the array of boolean values resulting from splitting string 3185 * <code>s</code> around comma characters, or an empty array if 3186 * <code>s</code> is <code>null</code> 3187 */ 3188 public static boolean[] split(String s, boolean x) { 3189 return split(s, StringPool.COMMA, x); 3190 } 3191 3192 /** 3193 * Splits the string <code>s</code> around the specified delimiter. 3194 * 3195 * <p> 3196 * Example: 3197 * </p> 3198 * 3199 * <p> 3200 * <pre> 3201 * <code> 3202 * splitLines("First;Second;Third", ';') returns {"First","Second","Third"} 3203 * </code> 3204 * </pre> 3205 * </p> 3206 * 3207 * @param s the string to split 3208 * @param delimiter the delimiter 3209 * @return the array of strings resulting from splitting string 3210 * <code>s</code> around the specified delimiter character, or an 3211 * empty string array if <code>s</code> is <code>null</code> or if 3212 * <code>s</code> is empty 3213 */ 3214 public static String[] split(String s, char delimiter) { 3215 if (Validator.isNull(s)) { 3216 return _emptyStringArray; 3217 } 3218 3219 s = s.trim(); 3220 3221 if (s.length() == 0) { 3222 return _emptyStringArray; 3223 } 3224 3225 if ((delimiter == CharPool.RETURN) || 3226 (delimiter == CharPool.NEW_LINE)) { 3227 3228 return splitLines(s); 3229 } 3230 3231 List<String> nodeValues = new ArrayList<>(); 3232 3233 int offset = 0; 3234 int pos = s.indexOf(delimiter, offset); 3235 3236 while (pos != -1) { 3237 nodeValues.add(s.substring(offset, pos)); 3238 3239 offset = pos + 1; 3240 pos = s.indexOf(delimiter, offset); 3241 } 3242 3243 if (offset < s.length()) { 3244 nodeValues.add(s.substring(offset)); 3245 } 3246 3247 return nodeValues.toArray(new String[nodeValues.size()]); 3248 } 3249 3250 /** 3251 * Splits the string <code>s</code> around comma characters returning the 3252 * double-precision decimal values of the substrings. 3253 * 3254 * @param s the string to split 3255 * @param x the default value to use for a substring in case an exception 3256 * occurs in getting the double-precision decimal value for that 3257 * substring 3258 * @return the array of double-precision decimal values resulting from 3259 * splitting string <code>s</code> around comma characters, or an 3260 * empty array if <code>s</code> is <code>null</code> 3261 */ 3262 public static double[] split(String s, double x) { 3263 return split(s, StringPool.COMMA, x); 3264 } 3265 3266 /** 3267 * Splits the string <code>s</code> around comma characters returning the 3268 * decimal values of the substrings. 3269 * 3270 * @param s the string to split 3271 * @param x the default value to use for a substring in case an exception 3272 * occurs in getting the decimal value for that substring 3273 * @return the array of decimal values resulting from splitting string 3274 * <code>s</code> around comma characters, or an empty array if 3275 * <code>s</code> is <code>null</code> 3276 */ 3277 public static float[] split(String s, float x) { 3278 return split(s, StringPool.COMMA, x); 3279 } 3280 3281 /** 3282 * Splits the string <code>s</code> around comma characters returning the 3283 * integer values of the substrings. 3284 * 3285 * @param s the string to split 3286 * @param x the default value to use for a substring in case an exception 3287 * occurs in getting the integer value for that substring 3288 * @return the array of integer values resulting from splitting string 3289 * <code>s</code> around comma characters, or an empty array if 3290 * <code>s</code> is <code>null</code> 3291 */ 3292 public static int[] split(String s, int x) { 3293 return split(s, StringPool.COMMA, x); 3294 } 3295 3296 /** 3297 * Splits the string <code>s</code> around comma characters returning the 3298 * long integer values of the substrings. 3299 * 3300 * @param s the string to split 3301 * @param x the default value to use for a substring in case an exception 3302 * occurs in getting the long integer value for that substring 3303 * @return the array of long integer values resulting from splitting string 3304 * <code>s</code> around comma characters, or an empty array if 3305 * <code>s</code> is <code>null</code> 3306 */ 3307 public static long[] split(String s, long x) { 3308 return split(s, StringPool.COMMA, x); 3309 } 3310 3311 /** 3312 * Splits the string <code>s</code> around comma characters returning the 3313 * short integer values of the substrings. 3314 * 3315 * @param s the string to split 3316 * @param x the default value to use for a substring in case an exception 3317 * occurs in getting the short integer value for that substring 3318 * @return the array of short integer values resulting from splitting string 3319 * <code>s</code> around comma characters, or an empty array if 3320 * <code>s</code> is <code>null</code> 3321 */ 3322 public static short[] split(String s, short x) { 3323 return split(s, StringPool.COMMA, x); 3324 } 3325 3326 /** 3327 * Splits the string <code>s</code> around the specified delimiter string. 3328 * 3329 * <p> 3330 * Example: 3331 * </p> 3332 * 3333 * <p> 3334 * <pre> 3335 * <code> 3336 * splitLines("oneandtwoandthreeandfour", "and") returns {"one","two","three","four"} 3337 * </code> 3338 * </pre> 3339 * </p> 3340 * 3341 * @param s the string to split 3342 * @param delimiter the delimiter 3343 * @return the array of strings resulting from splitting string 3344 * <code>s</code> around the specified delimiter string, or an empty 3345 * string array if <code>s</code> is <code>null</code> or equals the 3346 * delimiter 3347 */ 3348 public static String[] split(String s, String delimiter) { 3349 if (Validator.isNull(s) || (delimiter == null) || 3350 delimiter.equals(StringPool.BLANK)) { 3351 3352 return _emptyStringArray; 3353 } 3354 3355 s = s.trim(); 3356 3357 if (s.equals(delimiter)) { 3358 return _emptyStringArray; 3359 } 3360 3361 if (delimiter.length() == 1) { 3362 return split(s, delimiter.charAt(0)); 3363 } 3364 3365 List<String> nodeValues = new ArrayList<>(); 3366 3367 int offset = 0; 3368 int pos = s.indexOf(delimiter, offset); 3369 3370 while (pos != -1) { 3371 nodeValues.add(s.substring(offset, pos)); 3372 3373 offset = pos + delimiter.length(); 3374 pos = s.indexOf(delimiter, offset); 3375 } 3376 3377 if (offset < s.length()) { 3378 nodeValues.add(s.substring(offset)); 3379 } 3380 3381 return nodeValues.toArray(new String[nodeValues.size()]); 3382 } 3383 3384 /** 3385 * Splits the string <code>s</code> around the specified delimiter returning 3386 * the boolean values of the substrings. 3387 * 3388 * @param s the string to split 3389 * @param delimiter the delimiter 3390 * @param x the default value to use for a substring in case an exception 3391 * occurs in getting the boolean value for that substring 3392 * @return the array of booleans resulting from splitting string 3393 * <code>s</code> around the specified delimiter string, or an empty 3394 * array if <code>s</code> is <code>null</code> 3395 */ 3396 public static boolean[] split(String s, String delimiter, boolean x) { 3397 String[] array = split(s, delimiter); 3398 boolean[] newArray = new boolean[array.length]; 3399 3400 for (int i = 0; i < array.length; i++) { 3401 boolean value = x; 3402 3403 try { 3404 value = Boolean.valueOf(array[i]).booleanValue(); 3405 } 3406 catch (Exception e) { 3407 } 3408 3409 newArray[i] = value; 3410 } 3411 3412 return newArray; 3413 } 3414 3415 /** 3416 * Splits the string <code>s</code> around the specified delimiter returning 3417 * the double-precision decimal values of the substrings. 3418 * 3419 * @param s the string to split 3420 * @param delimiter the delimiter 3421 * @param x the default value to use for a substring in case an exception 3422 * occurs in getting the double-precision decimal value for that 3423 * substring 3424 * @return the array of double-precision decimal values resulting from 3425 * splitting string <code>s</code> around the specified delimiter 3426 * string, or an empty array if <code>s</code> is <code>null</code> 3427 */ 3428 public static double[] split(String s, String delimiter, double x) { 3429 String[] array = split(s, delimiter); 3430 double[] newArray = new double[array.length]; 3431 3432 for (int i = 0; i < array.length; i++) { 3433 double value = x; 3434 3435 try { 3436 value = Double.parseDouble(array[i]); 3437 } 3438 catch (Exception e) { 3439 } 3440 3441 newArray[i] = value; 3442 } 3443 3444 return newArray; 3445 } 3446 3447 /** 3448 * Splits the string <code>s</code> around the specified delimiter returning 3449 * the decimal values of the substrings. 3450 * 3451 * @param s the string to split 3452 * @param delimiter the delimiter 3453 * @param x the default value to use for a substring in case an exception 3454 * occurs in getting the decimal value for that substring 3455 * @return the array of decimal values resulting from splitting string 3456 * <code>s</code> around the specified delimiter string, or an empty 3457 * array if <code>s</code> is <code>null</code> 3458 */ 3459 public static float[] split(String s, String delimiter, float x) { 3460 String[] array = split(s, delimiter); 3461 float[] newArray = new float[array.length]; 3462 3463 for (int i = 0; i < array.length; i++) { 3464 float value = x; 3465 3466 try { 3467 value = Float.parseFloat(array[i]); 3468 } 3469 catch (Exception e) { 3470 } 3471 3472 newArray[i] = value; 3473 } 3474 3475 return newArray; 3476 } 3477 3478 /** 3479 * Splits the string <code>s</code> around the specified delimiter returning 3480 * the integer values of the substrings. 3481 * 3482 * @param s the string to split 3483 * @param delimiter the delimiter 3484 * @param x the default value to use for a substring in case an exception 3485 * occurs in getting the integer value for that substring 3486 * @return the array of integer values resulting from splitting string 3487 * <code>s</code> around the specified delimiter string, or an empty 3488 * array if <code>s</code> is <code>null</code> 3489 */ 3490 public static int[] split(String s, String delimiter, int x) { 3491 String[] array = split(s, delimiter); 3492 int[] newArray = new int[array.length]; 3493 3494 for (int i = 0; i < array.length; i++) { 3495 int value = x; 3496 3497 try { 3498 value = Integer.parseInt(array[i]); 3499 } 3500 catch (Exception e) { 3501 } 3502 3503 newArray[i] = value; 3504 } 3505 3506 return newArray; 3507 } 3508 3509 /** 3510 * Splits the string <code>s</code> around the specified delimiter returning 3511 * the long integer values of the substrings. 3512 * 3513 * @param s the string to split 3514 * @param delimiter the delimiter 3515 * @param x the default value to use for a substring in case an exception 3516 * occurs in getting the long integer value for that substring 3517 * @return the array of long integer values resulting from splitting string 3518 * <code>s</code> around the specified delimiter string, or an empty 3519 * array if <code>s</code> is <code>null</code> 3520 */ 3521 public static long[] split(String s, String delimiter, long x) { 3522 String[] array = split(s, delimiter); 3523 long[] newArray = new long[array.length]; 3524 3525 for (int i = 0; i < array.length; i++) { 3526 long value = x; 3527 3528 try { 3529 value = Long.parseLong(array[i]); 3530 } 3531 catch (Exception e) { 3532 } 3533 3534 newArray[i] = value; 3535 } 3536 3537 return newArray; 3538 } 3539 3540 /** 3541 * Splits the string <code>s</code> around the specified delimiter returning 3542 * the short integer values of the substrings. 3543 * 3544 * @param s the string to split 3545 * @param delimiter the delimiter 3546 * @param x the default value to use for a substring in case an exception 3547 * occurs in getting the short integer value for that substring 3548 * @return the array of short integer values resulting from splitting string 3549 * <code>s</code> around the specified delimiter string, or an empty 3550 * array if <code>s</code> is <code>null</code> 3551 */ 3552 public static short[] split(String s, String delimiter, short x) { 3553 String[] array = split(s, delimiter); 3554 short[] newArray = new short[array.length]; 3555 3556 for (int i = 0; i < array.length; i++) { 3557 short value = x; 3558 3559 try { 3560 value = Short.parseShort(array[i]); 3561 } 3562 catch (Exception e) { 3563 } 3564 3565 newArray[i] = value; 3566 } 3567 3568 return newArray; 3569 } 3570 3571 /** 3572 * Splits string <code>s</code> around return and newline characters. 3573 * 3574 * <p> 3575 * Example: 3576 * </p> 3577 * 3578 * <p> 3579 * <pre> 3580 * <code> 3581 * splitLines("Red\rBlue\nGreen") returns {"Red","Blue","Green"} 3582 * </code> 3583 * </pre> 3584 * </p> 3585 * 3586 * @param s the string to split 3587 * @return the array of strings resulting from splitting string 3588 * <code>s</code> around return and newline characters, or an empty 3589 * string array if string <code>s</code> is <code>null</code> 3590 */ 3591 public static String[] splitLines(String s) { 3592 if (Validator.isNull(s)) { 3593 return _emptyStringArray; 3594 } 3595 3596 s = s.trim(); 3597 3598 List<String> lines = new ArrayList<>(); 3599 3600 int lastIndex = 0; 3601 3602 while (true) { 3603 int returnIndex = s.indexOf(CharPool.RETURN, lastIndex); 3604 int newLineIndex = s.indexOf(CharPool.NEW_LINE, lastIndex); 3605 3606 if ((returnIndex == -1) && (newLineIndex == -1)) { 3607 break; 3608 } 3609 3610 if (returnIndex == -1) { 3611 lines.add(s.substring(lastIndex, newLineIndex)); 3612 3613 lastIndex = newLineIndex + 1; 3614 } 3615 else if (newLineIndex == -1) { 3616 lines.add(s.substring(lastIndex, returnIndex)); 3617 3618 lastIndex = returnIndex + 1; 3619 } 3620 else if (newLineIndex < returnIndex) { 3621 lines.add(s.substring(lastIndex, newLineIndex)); 3622 3623 lastIndex = newLineIndex + 1; 3624 } 3625 else { 3626 lines.add(s.substring(lastIndex, returnIndex)); 3627 3628 lastIndex = returnIndex + 1; 3629 3630 if (lastIndex == newLineIndex) { 3631 lastIndex++; 3632 } 3633 } 3634 } 3635 3636 if (lastIndex < s.length()) { 3637 lines.add(s.substring(lastIndex)); 3638 } 3639 3640 return lines.toArray(new String[lines.size()]); 3641 } 3642 3643 /** 3644 * Returns <code>true</code> if, ignoring case, the string starts with the 3645 * specified character. 3646 * 3647 * @param s the string 3648 * @param begin the character against which the initial character of the 3649 * string is to be compared 3650 * @return <code>true</code> if, ignoring case, the string starts with the 3651 * specified character; <code>false</code> otherwise 3652 */ 3653 public static boolean startsWith(String s, char begin) { 3654 return startsWith(s, (Character.valueOf(begin)).toString()); 3655 } 3656 3657 /** 3658 * Returns <code>true</code> if, ignoring case, the string starts with the 3659 * specified start string. 3660 * 3661 * @param s the original string 3662 * @param start the string against which the beginning of string 3663 * <code>s</code> are to be compared 3664 * @return <code>true</code> if, ignoring case, the string starts with the 3665 * specified start string; <code>false</code> otherwise 3666 */ 3667 public static boolean startsWith(String s, String start) { 3668 if ((s == null) || (start == null)) { 3669 return false; 3670 } 3671 3672 if (start.length() > s.length()) { 3673 return false; 3674 } 3675 3676 String temp = s.substring(0, start.length()); 3677 3678 if (equalsIgnoreCase(temp, start)) { 3679 return true; 3680 } 3681 else { 3682 return false; 3683 } 3684 } 3685 3686 /** 3687 * Returns the number of starting characters that <code>s1</code> and 3688 * <code>s2</code> have in common before their characters deviate. 3689 * 3690 * @param s1 string 1 3691 * @param s2 string 2 3692 * @return the number of starting characters that <code>s1</code> and 3693 * <code>s2</code> have in common before their characters deviate 3694 */ 3695 public static int startsWithWeight(String s1, String s2) { 3696 if ((s1 == null) || (s2 == null)) { 3697 return 0; 3698 } 3699 3700 char[] chars1 = s1.toCharArray(); 3701 char[] chars2 = s2.toCharArray(); 3702 3703 int i = 0; 3704 3705 for (; (i < chars1.length) && (i < chars2.length); i++) { 3706 if (chars1[i] != chars2[i]) { 3707 break; 3708 } 3709 } 3710 3711 return i; 3712 } 3713 3714 /** 3715 * Returns a string representing the string <code>s</code> with all 3716 * occurrences of the specified character removed. 3717 * 3718 * <p> 3719 * Example: 3720 * </p> 3721 * 3722 * <p> 3723 * <pre> 3724 * <code> 3725 * strip("Mississipi", 'i') returns "Mssssp" 3726 * </code> 3727 * </pre> 3728 * </p> 3729 * 3730 * @param s the string from which to strip all occurrences of the character 3731 * @param remove the character to strip from the string 3732 * @return a string representing the string <code>s</code> with all 3733 * occurrences of the specified character removed, or 3734 * <code>null</code> if <code>s</code> is <code>null</code> 3735 */ 3736 public static String strip(String s, char remove) { 3737 if (s == null) { 3738 return null; 3739 } 3740 3741 int x = s.indexOf(remove); 3742 3743 if (x < 0) { 3744 return s; 3745 } 3746 3747 int y = 0; 3748 3749 StringBundler sb = new StringBundler(s.length()); 3750 3751 while (x >= 0) { 3752 sb.append(s.subSequence(y, x)); 3753 3754 y = x + 1; 3755 3756 x = s.indexOf(remove, y); 3757 } 3758 3759 sb.append(s.substring(y)); 3760 3761 return sb.toString(); 3762 } 3763 3764 /** 3765 * Returns a string representing the string <code>s</code> with all 3766 * occurrences of the specified characters removed. 3767 * 3768 * <p> 3769 * Example: 3770 * </p> 3771 * 3772 * <p> 3773 * <pre> 3774 * <code> 3775 * strip("Hello World", {' ', 'l', 'd'}) returns "HeoWor" 3776 * </code> 3777 * </pre> 3778 * </p> 3779 * 3780 * @param s the string from which to strip all occurrences the characters 3781 * @param remove the characters to strip from the string 3782 * @return a string representing the string <code>s</code> with all 3783 * occurrences of the specified characters removed, or 3784 * <code>null</code> if <code>s</code> is <code>null</code> 3785 */ 3786 public static String strip(String s, char[] remove) { 3787 for (char c : remove) { 3788 s = strip(s, c); 3789 } 3790 3791 return s; 3792 } 3793 3794 /** 3795 * Returns a string representing the combination of the substring of 3796 * <code>s</code> up to but not including the string <code>begin</code> 3797 * concatenated with the substring of <code>s</code> after but not including 3798 * the string <code>end</code>. 3799 * 3800 * <p> 3801 * Example: 3802 * </p> 3803 * 3804 * <p> 3805 * <pre> 3806 * <code> 3807 * stripBetween("One small step for man, one giant leap for mankind", "step", "giant ") returns "One small leap for mankind" 3808 * </code> 3809 * </pre> 3810 * </p> 3811 * 3812 * @param s the string from which to strip a substring 3813 * @param begin the beginning characters of the substring to be removed 3814 * @param end the ending characters of the substring to be removed 3815 * @return a string representing the combination of the substring of 3816 * <code>s</code> up to but not including the string 3817 * <code>begin</code> concatenated with the substring of 3818 * <code>s</code> after but not including the string 3819 * <code>end</code>, or the original string if the value of 3820 * <code>s</code>, <code>begin</code>, or <code>end</code> are 3821 * <code>null</code> 3822 */ 3823 public static String stripBetween(String s, String begin, String end) { 3824 if (Validator.isBlank(s) || Validator.isBlank(begin) || 3825 Validator.isBlank(end)) { 3826 3827 return s; 3828 } 3829 3830 StringBundler sb = new StringBundler(s.length()); 3831 3832 int pos = 0; 3833 3834 while (true) { 3835 int x = s.indexOf(begin, pos); 3836 int y = s.indexOf(end, x + begin.length()); 3837 3838 if ((x == -1) || (y == -1)) { 3839 sb.append(s.substring(pos)); 3840 3841 break; 3842 } 3843 else { 3844 sb.append(s.substring(pos, x)); 3845 3846 pos = y + end.length(); 3847 } 3848 } 3849 3850 return sb.toString(); 3851 } 3852 3853 /** 3854 * Returns a string representing the string <code>s</code> with its 3855 * <code><![CDATA[]]></code> wrapper removed. 3856 * 3857 * <p> 3858 * Example: 3859 * </p> 3860 * 3861 * <p> 3862 * <pre> 3863 * <code> 3864 * stripCDATA("<![CDATA[One small step for man]]>") returns "One small step for man" 3865 * </code> 3866 * </pre> 3867 * </p> 3868 * 3869 * @param s the string from which to strip its CDATA wrapper 3870 * @return a string representing the string <code>s</code> with its 3871 * <code><![CDATA[]]></code> wrapper removed, or 3872 * <code>null</code> if <code>s</code> is <code>null</code> 3873 */ 3874 public static String stripCDATA(String s) { 3875 if (s == null) { 3876 return s; 3877 } 3878 3879 if (s.startsWith(StringPool.CDATA_OPEN) && 3880 s.endsWith(StringPool.CDATA_CLOSE)) { 3881 3882 s = s.substring( 3883 StringPool.CDATA_OPEN.length(), 3884 s.length() - StringPool.CDATA_CLOSE.length()); 3885 } 3886 3887 return s; 3888 } 3889 3890 /** 3891 * Returns a string representing the string <code>s</code> without an 3892 * appended parenthetical suffix. If there is not a space directly before 3893 * the opening parenthesis, the parenthetical suffix is not stripped. 3894 * 3895 * <p> 3896 * Example: 3897 * </p> 3898 * 3899 * <p> 3900 * <pre> 3901 * <code> 3902 * stripParentheticalSuffix("file") returns "file" 3903 * stripParentheticalSuffix("file (0)") returns "file" 3904 * stripParentheticalSuffix("file (0 0)") returns "file" 3905 * stripParentheticalSuffix("file(0)") returns "file(0)" 3906 * </code> 3907 * </pre> 3908 * </p> 3909 * 3910 * @param s the string from which to strip its parenthetical suffix 3911 * @return a string representing the string <code>s</code> without an 3912 * appended parenthetical suffix 3913 */ 3914 public static String stripParentheticalSuffix(String s) { 3915 int x = s.lastIndexOf(StringPool.OPEN_PARENTHESIS); 3916 int y = s.lastIndexOf(StringPool.CLOSE_PARENTHESIS); 3917 3918 if ((x == -1) || (y == -1)) { 3919 return s; 3920 } 3921 3922 if ((x > y) || !s.endsWith(StringPool.CLOSE_PARENTHESIS)) { 3923 return s; 3924 } 3925 3926 if (s.charAt(x - 1) != CharPool.SPACE) { 3927 return s; 3928 } 3929 3930 return s.substring(0, x - 1).concat(s.substring(y + 1, s.length())); 3931 } 3932 3933 /** 3934 * Returns a string representing the Unicode character codes of the 3935 * characters comprising the string <code>s</code>. 3936 * 3937 * <p> 3938 * Example: 3939 * </p> 3940 * 3941 * <p> 3942 * <pre> 3943 * <code> 3944 * toCharCode("a") returns "97" 3945 * toCharCode("b") returns "98" 3946 * toCharCode("c") returns "99" 3947 * toCharCode("What's for lunch?") returns "87104971163911532102111114321081171109910463" 3948 * </code> 3949 * </pre> 3950 * </p> 3951 * 3952 * @param s the string whose character codes are to be represented 3953 * @return a string representing the Unicode character codes of the 3954 * characters comprising the string <code>s</code> 3955 */ 3956 public static String toCharCode(String s) { 3957 StringBundler sb = new StringBundler(s.length()); 3958 3959 for (int i = 0; i < s.length(); i++) { 3960 sb.append(s.codePointAt(i)); 3961 } 3962 3963 return sb.toString(); 3964 } 3965 3966 /** 3967 * Returns a string representing the hexidecimal character code of the 3968 * integer. 3969 * 3970 * <p> 3971 * Example: 3972 * </p> 3973 * 3974 * <p> 3975 * <pre> 3976 * <code> 3977 * toHexString(10) returns "a" 3978 * toHexString(15) returns "f" 3979 * toHexString(10995) returns "2af3" 3980 * </code> 3981 * </pre> 3982 * </p> 3983 * 3984 * @param i the integer to convert 3985 * @return a string representing the hexidecimal character code of the 3986 * integer 3987 */ 3988 public static String toHexString(int i) { 3989 char[] buffer = new char[8]; 3990 3991 int index = 8; 3992 3993 do { 3994 buffer[--index] = HEX_DIGITS[i & 15]; 3995 3996 i >>>= 4; 3997 } 3998 while (i != 0); 3999 4000 return new String(buffer, index, 8 - index); 4001 } 4002 4003 /** 4004 * Returns a string representing the hexidecimal character code of the long 4005 * integer. 4006 * 4007 * <p> 4008 * Example: 4009 * </p> 4010 * 4011 * <p> 4012 * <pre> 4013 * <code> 4014 * toHexString(12345678910L) returns "2dfdc1c3e" 4015 * </code> 4016 * </pre> 4017 * </p> 4018 * 4019 * @param l the long integer to convert 4020 * @return a string representing the hexidecimal character code of the long 4021 * integer 4022 */ 4023 public static String toHexString(long l) { 4024 char[] buffer = new char[16]; 4025 4026 int index = 16; 4027 4028 do { 4029 buffer[--index] = HEX_DIGITS[(int) (l & 15)]; 4030 4031 l >>>= 4; 4032 } 4033 while (l != 0); 4034 4035 return new String(buffer, index, 16 - index); 4036 } 4037 4038 /** 4039 * Returns a string representing the hexidecimal character code of the 4040 * <code>Integer</code> or <code>Long</code> object type. If the object is 4041 * not an instance of these types, the object's original value is returned. 4042 * 4043 * @param obj the object to convert 4044 * @return a string representing the hexidecimal character code of the 4045 * object 4046 */ 4047 public static String toHexString(Object obj) { 4048 if (obj instanceof Integer) { 4049 return toHexString(((Integer)obj).intValue()); 4050 } 4051 else if (obj instanceof Long) { 4052 return toHexString(((Long)obj).longValue()); 4053 } 4054 else { 4055 return String.valueOf(obj); 4056 } 4057 } 4058 4059 /** 4060 * Converts all of the characters in the string to lower case, based on the 4061 * portal instance's default locale. 4062 * 4063 * @param s the string to convert 4064 * @return the string, converted to lower case, or <code>null</code> if the 4065 * string is <code>null</code> 4066 */ 4067 public static String toLowerCase(String s) { 4068 return toLowerCase(s, null); 4069 } 4070 4071 /** 4072 * Converts all of the characters in the string to lower case, based on the 4073 * locale. 4074 * 4075 * @param s the string to convert 4076 * @param locale apply this locale's rules 4077 * @return the string, converted to lower case, or <code>null</code> if the 4078 * string is <code>null</code> 4079 */ 4080 public static String toLowerCase(String s, Locale locale) { 4081 if (s == null) { 4082 return null; 4083 } 4084 4085 StringBuilder sb = null; 4086 4087 for (int i = 0; i < s.length(); i++) { 4088 char c = s.charAt(i); 4089 4090 if (c > 127) { 4091 4092 // Found non-ascii char, fallback to the slow unicode detection 4093 4094 if (locale == null) { 4095 locale = LocaleUtil.getDefault(); 4096 } 4097 4098 return s.toLowerCase(locale); 4099 } 4100 4101 if ((c >= 'A') && (c <= 'Z')) { 4102 if (sb == null) { 4103 sb = new StringBuilder(s); 4104 } 4105 4106 sb.setCharAt(i, (char)(c + 32)); 4107 } 4108 } 4109 4110 if (sb == null) { 4111 return s; 4112 } 4113 4114 return sb.toString(); 4115 } 4116 4117 /** 4118 * Converts all of the characters in the string to upper case, based on the 4119 * portal instance's default locale. 4120 * 4121 * @param s the string to convert 4122 * @return the string, converted to upper case, or <code>null</code> if the 4123 * string is <code>null</code> 4124 */ 4125 public static String toUpperCase(String s) { 4126 return toUpperCase(s, null); 4127 } 4128 4129 /** 4130 * Converts all of the characters in the string to upper case, based on the 4131 * locale. 4132 * 4133 * @param s the string to convert 4134 * @param locale apply this locale's rules 4135 * @return the string, converted to upper case, or <code>null</code> if the 4136 * string is <code>null</code> 4137 */ 4138 public static String toUpperCase(String s, Locale locale) { 4139 if (s == null) { 4140 return null; 4141 } 4142 4143 StringBuilder sb = null; 4144 4145 for (int i = 0; i < s.length(); i++) { 4146 char c = s.charAt(i); 4147 4148 if (c > 127) { 4149 4150 // Found non-ascii char, fallback to the slow unicode detection 4151 4152 if (locale == null) { 4153 locale = LocaleUtil.getDefault(); 4154 } 4155 4156 return s.toUpperCase(locale); 4157 } 4158 4159 if ((c >= 'a') && (c <= 'z')) { 4160 if (sb == null) { 4161 sb = new StringBuilder(s); 4162 } 4163 4164 sb.setCharAt(i, (char)(c - 32)); 4165 } 4166 } 4167 4168 if (sb == null) { 4169 return s; 4170 } 4171 4172 return sb.toString(); 4173 } 4174 4175 /** 4176 * Trims all leading and trailing whitespace from the string. 4177 * 4178 * @param s the original string 4179 * @return a string representing the original string with all leading and 4180 * trailing whitespace removed 4181 */ 4182 public static String trim(String s) { 4183 if (s == null) { 4184 return null; 4185 } 4186 4187 if (s.length() == 0) { 4188 return s; 4189 } 4190 4191 int len = s.length(); 4192 4193 int x = len; 4194 4195 for (int i = 0; i < len; i++) { 4196 char c = s.charAt(i); 4197 4198 if (!Character.isWhitespace(c)) { 4199 x = i; 4200 4201 break; 4202 } 4203 } 4204 4205 if (x == len) { 4206 return StringPool.BLANK; 4207 } 4208 4209 int y = x + 1; 4210 4211 for (int i = len - 1; i > x; i--) { 4212 char c = s.charAt(i); 4213 4214 if (!Character.isWhitespace(c)) { 4215 y = i + 1; 4216 4217 break; 4218 } 4219 } 4220 4221 if ((x == 0) && (y == len)) { 4222 return s; 4223 } 4224 4225 return s.substring(x, y); 4226 } 4227 4228 /** 4229 * Trims leading and trailing whitespace from the string, up to but not 4230 * including the whitespace character specified by <code>c</code>. 4231 * 4232 * <p> 4233 * Examples: 4234 * </p> 4235 * 4236 * <p> 4237 * <pre> 4238 * <code> 4239 * trim(" \tHey\t ", '\t') returns "\tHey\t" 4240 * trim(" \t Hey \t ", '\t') returns "\t Hey \t" 4241 * </code> 4242 * </pre> 4243 * </p> 4244 * 4245 * @param s the original string 4246 * @param c the whitespace character to limit trimming 4247 * @return a string representing the original string with leading and 4248 * trailing whitespace removed, up to but not including the 4249 * whitespace character specified by <code>c</code> 4250 */ 4251 public static String trim(String s, char c) { 4252 return trim(s, new char[] {c}); 4253 } 4254 4255 /** 4256 * Trims leading and trailing whitespace from the string, up to but not 4257 * including the whitespace characters specified by <code>exceptions</code>. 4258 * 4259 * @param s the original string 4260 * @param exceptions the whitespace characters to limit trimming 4261 * @return a string representing the original string with leading and 4262 * trailing whitespace removed, up to but not including the 4263 * whitespace characters specified by <code>exceptions</code> 4264 */ 4265 public static String trim(String s, char[] exceptions) { 4266 if (s == null) { 4267 return null; 4268 } 4269 4270 if (s.length() == 0) { 4271 return s; 4272 } 4273 4274 if (ArrayUtil.isEmpty(exceptions)) { 4275 return trim(s); 4276 } 4277 4278 int len = s.length(); 4279 int x = len; 4280 4281 for (int i = 0; i < len; i++) { 4282 char c = s.charAt(i); 4283 4284 if (!_isTrimable(c, exceptions)) { 4285 x = i; 4286 4287 break; 4288 } 4289 } 4290 4291 if (x == len) { 4292 return StringPool.BLANK; 4293 } 4294 4295 int y = x + 1; 4296 4297 for (int i = len - 1; i > x; i--) { 4298 char c = s.charAt(i); 4299 4300 if (!_isTrimable(c, exceptions)) { 4301 y = i + 1; 4302 4303 break; 4304 } 4305 } 4306 4307 if ((x == 0) && (y == len)) { 4308 return s; 4309 } 4310 else { 4311 return s.substring(x, y); 4312 } 4313 } 4314 4315 /** 4316 * Trims all leading whitespace from the string. 4317 * 4318 * @param s the original string 4319 * @return a string representing the original string with all leading 4320 * whitespace removed 4321 */ 4322 public static String trimLeading(String s) { 4323 if (s == null) { 4324 return null; 4325 } 4326 4327 if (s.length() == 0) { 4328 return s; 4329 } 4330 4331 int len = s.length(); 4332 int x = len; 4333 4334 for (int i = 0; i < len; i++) { 4335 char c = s.charAt(i); 4336 4337 if (!Character.isWhitespace(c)) { 4338 x = i; 4339 4340 break; 4341 } 4342 } 4343 4344 if (x == len) { 4345 return StringPool.BLANK; 4346 } 4347 else if (x == 0) { 4348 return s; 4349 } 4350 else { 4351 return s.substring(x); 4352 } 4353 } 4354 4355 /** 4356 * Trims leading whitespace from the string, up to but not including the 4357 * whitespace character specified by <code>c</code>. 4358 * 4359 * @param s the original string 4360 * @param c the whitespace character to limit trimming 4361 * @return a string representing the original string with leading whitespace 4362 * removed, up to but not including the whitespace character 4363 * specified by <code>c</code> 4364 */ 4365 public static String trimLeading(String s, char c) { 4366 return trimLeading(s, new char[] {c}); 4367 } 4368 4369 /** 4370 * Trims leading whitespace from the string, up to but not including the 4371 * whitespace characters specified by <code>exceptions</code>. 4372 * 4373 * @param s the original string 4374 * @param exceptions the whitespace characters to limit trimming 4375 * @return a string representing the original string with leading whitespace 4376 * removed, up to but not including the whitespace characters 4377 * specified by <code>exceptions</code> 4378 */ 4379 public static String trimLeading(String s, char[] exceptions) { 4380 if (s == null) { 4381 return null; 4382 } 4383 4384 if (s.length() == 0) { 4385 return s; 4386 } 4387 4388 if (ArrayUtil.isEmpty(exceptions)) { 4389 return trimLeading(s); 4390 } 4391 4392 int len = s.length(); 4393 int x = len; 4394 4395 for (int i = 0; i < len; i++) { 4396 char c = s.charAt(i); 4397 4398 if (!_isTrimable(c, exceptions)) { 4399 x = i; 4400 4401 break; 4402 } 4403 } 4404 4405 if (x == len) { 4406 return StringPool.BLANK; 4407 } 4408 else if (x == 0) { 4409 return s; 4410 } 4411 else { 4412 return s.substring(x); 4413 } 4414 } 4415 4416 /** 4417 * Trims all trailing whitespace from the string. 4418 * 4419 * @param s the original string 4420 * @return a string representing the original string with all trailing 4421 * whitespace removed 4422 */ 4423 public static String trimTrailing(String s) { 4424 if (s == null) { 4425 return null; 4426 } 4427 4428 if (s.length() == 0) { 4429 return s; 4430 } 4431 4432 int len = s.length(); 4433 int x = 0; 4434 4435 for (int i = len - 1; i >= 0; i--) { 4436 char c = s.charAt(i); 4437 4438 if (!Character.isWhitespace(c)) { 4439 x = i + 1; 4440 4441 break; 4442 } 4443 } 4444 4445 if (x == 0) { 4446 return StringPool.BLANK; 4447 } 4448 else if (x == len) { 4449 return s; 4450 } 4451 else { 4452 return s.substring(0, x); 4453 } 4454 } 4455 4456 /** 4457 * Trims trailing whitespace from the string, up to but not including the 4458 * whitespace character specified by <code>c</code>. 4459 * 4460 * @param s the original string 4461 * @param c the whitespace character to limit trimming 4462 * @return a string representing the original string with trailing 4463 * whitespace removed, up to but not including the whitespace 4464 * character specified by <code>c</code> 4465 */ 4466 public static String trimTrailing(String s, char c) { 4467 return trimTrailing(s, new char[] {c}); 4468 } 4469 4470 /** 4471 * Trims trailing whitespace from the string, up to but not including the 4472 * whitespace characters specified by <code>exceptions</code>. 4473 * 4474 * @param s the original string 4475 * @param exceptions the whitespace characters to limit trimming 4476 * @return a string representing the original string with trailing 4477 * whitespace removed, up to but not including the whitespace 4478 * characters specified by <code>exceptions</code> 4479 */ 4480 public static String trimTrailing(String s, char[] exceptions) { 4481 if (s == null) { 4482 return null; 4483 } 4484 4485 if (s.length() == 0) { 4486 return s; 4487 } 4488 4489 if (ArrayUtil.isEmpty(exceptions)) { 4490 return trimTrailing(s); 4491 } 4492 4493 int len = s.length(); 4494 int x = 0; 4495 4496 for (int i = len - 1; i >= 0; i--) { 4497 char c = s.charAt(i); 4498 4499 if (!_isTrimable(c, exceptions)) { 4500 x = i + 1; 4501 4502 break; 4503 } 4504 } 4505 4506 if (x == 0) { 4507 return StringPool.BLANK; 4508 } 4509 else if (x == len) { 4510 return s; 4511 } 4512 else { 4513 return s.substring(0, x); 4514 } 4515 } 4516 4517 /** 4518 * Removes leading and trailing double and single quotation marks from the 4519 * string. 4520 * 4521 * @param s the original string 4522 * @return a string representing the original string with leading and 4523 * trailing double and single quotation marks removed, or the 4524 * original string if the original string is a <code>null</code> or 4525 * empty 4526 */ 4527 public static String unquote(String s) { 4528 if (Validator.isNull(s)) { 4529 return s; 4530 } 4531 4532 if ((s.charAt(0) == CharPool.APOSTROPHE) && 4533 (s.charAt(s.length() - 1) == CharPool.APOSTROPHE)) { 4534 4535 return s.substring(1, s.length() - 1); 4536 } 4537 else if ((s.charAt(0) == CharPool.QUOTE) && 4538 (s.charAt(s.length() - 1) == CharPool.QUOTE)) { 4539 4540 return s.substring(1, s.length() - 1); 4541 } 4542 4543 return s; 4544 } 4545 4546 /** 4547 * Converts all of the characters in the string to upper case. 4548 * 4549 * @param s the string to convert 4550 * @return the string, converted to upper-case, or <code>null</code> if the 4551 * string is <code>null</code> 4552 * @see String#toUpperCase() 4553 */ 4554 public static String upperCase(String s) { 4555 return toUpperCase(s); 4556 } 4557 4558 /** 4559 * Converts the first character of the string to upper case. 4560 * 4561 * @param s the string whose first character is to be converted 4562 * @return the string, with its first character converted to upper-case 4563 */ 4564 public static String upperCaseFirstLetter(String s) { 4565 char[] chars = s.toCharArray(); 4566 4567 if ((chars[0] >= 97) && (chars[0] <= 122)) { 4568 chars[0] = (char)(chars[0] - 32); 4569 } 4570 4571 return new String(chars); 4572 } 4573 4574 /** 4575 * Returns the string value of the object. 4576 * 4577 * @param obj the object whose string value is to be returned 4578 * @return the string value of the object 4579 * @see String#valueOf(Object obj) 4580 */ 4581 public static String valueOf(Object obj) { 4582 return String.valueOf(obj); 4583 } 4584 4585 /** 4586 * Returns <code>true</code> if the string matches the wildcard pattern. 4587 * 4588 * <p> 4589 * For example, with the following initialized variables: 4590 * </p> 4591 * 4592 * <p> 4593 * <pre> 4594 * <code> 4595 * String s = "*master"; 4596 * String wildcard = "/*m?st*"; 4597 * char singleWildcardCharacter = '?'; 4598 * char multipleWildcardCharacter = '*'; 4599 * char escapeWildcardCharacter = '/'; 4600 * boolean caseSensitive = false; 4601 * </code> 4602 * </pre> 4603 * </p> 4604 * 4605 * <p> 4606 * <code>wildcardMatches(s, wildcard, singleWildcardCharacter, 4607 * multipleWildcardCharacter, escapeWildcardCharacter, caseSensitive)</code> 4608 * returns <code>true</code> 4609 * </p> 4610 * 4611 * @param s the string to be checked 4612 * @param wildcard the wildcard pattern to match 4613 * @param singleWildcardCharacter the char used to match exactly one 4614 * character 4615 * @param multipleWildcardCharacter the char used to match <code>0</code> 4616 * or more characters 4617 * @param escapeWildcardCharacter the char placed in front of a wildcard 4618 * character to indicate that it should be interpreted as a regular 4619 * character 4620 * @param caseSensitive whether to use case sensitivity 4621 * @return <code>true</code> if the string matches the wildcard pattern; 4622 * <code>false</code> otherwise 4623 */ 4624 public static boolean wildcardMatches( 4625 String s, String wildcard, char singleWildcardCharacter, 4626 char multipleWildcardCharacter, char escapeWildcardCharacter, 4627 boolean caseSensitive) { 4628 4629 if (!caseSensitive) { 4630 s = toLowerCase(s); 4631 wildcard = toLowerCase(wildcard); 4632 } 4633 4634 // Update the wildcard, single whildcard character, and multiple 4635 // wildcard character so that they no longer have escaped wildcard 4636 // characters 4637 4638 int index = wildcard.indexOf(escapeWildcardCharacter); 4639 4640 if (index != -1) { 4641 4642 // Search for safe wildcard replacement 4643 4644 char newSingleWildcardCharacter = 0; 4645 4646 while (wildcard.indexOf(newSingleWildcardCharacter) != -1) { 4647 newSingleWildcardCharacter++; 4648 } 4649 4650 char newMultipleWildcardCharacter = 4651 (char)(newSingleWildcardCharacter + 1); 4652 4653 while (wildcard.indexOf(newMultipleWildcardCharacter) != -1) { 4654 newMultipleWildcardCharacter++; 4655 } 4656 4657 // Purify 4658 4659 StringBuilder sb = new StringBuilder(wildcard); 4660 4661 for (int i = 0; i < sb.length(); i++) { 4662 char c = sb.charAt(i); 4663 4664 if (c == escapeWildcardCharacter) { 4665 sb.deleteCharAt(i); 4666 } 4667 else if (c == singleWildcardCharacter) { 4668 sb.setCharAt(i, newSingleWildcardCharacter); 4669 } 4670 else if (c == multipleWildcardCharacter) { 4671 sb.setCharAt(i, newMultipleWildcardCharacter); 4672 } 4673 } 4674 4675 wildcard = sb.toString(); 4676 4677 singleWildcardCharacter = newSingleWildcardCharacter; 4678 multipleWildcardCharacter = newMultipleWildcardCharacter; 4679 } 4680 4681 // Align head 4682 4683 for (index = 0; index < s.length(); index++) { 4684 if (index >= wildcard.length()) { 4685 return false; 4686 } 4687 4688 char c = wildcard.charAt(index); 4689 4690 if (c == multipleWildcardCharacter) { 4691 break; 4692 } 4693 4694 if ((s.charAt(index) != c) && (c != singleWildcardCharacter)) { 4695 return false; 4696 } 4697 } 4698 4699 // Match body 4700 4701 int sIndex = index; 4702 int wildcardIndex = index; 4703 4704 int matchPoint = 0; 4705 int comparePoint = 0; 4706 4707 while (sIndex < s.length()) { 4708 if (wildcardIndex == wildcard.length()) { 4709 4710 // Wildcard exhausted before s 4711 4712 return false; 4713 } 4714 4715 char c = wildcard.charAt(wildcardIndex); 4716 4717 if (c == multipleWildcardCharacter) { 4718 if (++wildcardIndex == wildcard.length()) { 4719 return true; 4720 } 4721 4722 matchPoint = wildcardIndex; 4723 comparePoint = sIndex + 1; 4724 } 4725 else if ((c == s.charAt(sIndex)) || 4726 (c == singleWildcardCharacter)) { 4727 4728 sIndex++; 4729 wildcardIndex++; 4730 } 4731 else { 4732 wildcardIndex = matchPoint; 4733 sIndex = comparePoint++; 4734 } 4735 } 4736 4737 // Match tail 4738 4739 while (wildcardIndex < wildcard.length()) { 4740 if (wildcard.charAt(wildcardIndex) != multipleWildcardCharacter) { 4741 break; 4742 } 4743 4744 wildcardIndex++; 4745 } 4746 4747 if (wildcardIndex == wildcard.length()) { 4748 return true; 4749 } 4750 else { 4751 return false; 4752 } 4753 } 4754 4755 /** 4756 * Wraps the text when it exceeds the <code>80</code> column width limit, 4757 * using a {@link StringPool#NEW_LINE} to break each wrapped line. 4758 * 4759 * @param text the text to wrap 4760 * @return the wrapped text following the column width limit, or 4761 * <code>null</code> if the text is <code>null</code> 4762 */ 4763 public static String wrap(String text) { 4764 return wrap(text, 80, StringPool.NEW_LINE); 4765 } 4766 4767 /** 4768 * Wraps the text when it exceeds the column width limit, using the line 4769 * separator to break each wrapped line. 4770 * 4771 * @param text the text to wrap 4772 * @param width the column width limit for the text 4773 * @param lineSeparator the string to use in breaking each wrapped line 4774 * @return the wrapped text and line separators, following the column width 4775 * limit, or <code>null</code> if the text is <code>null</code> 4776 */ 4777 public static String wrap(String text, int width, String lineSeparator) { 4778 try { 4779 return _wrap(text, width, lineSeparator); 4780 } 4781 catch (IOException ioe) { 4782 _log.error(ioe.getMessage()); 4783 4784 return text; 4785 } 4786 } 4787 4788 protected static final char[] HEX_DIGITS = { 4789 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 4790 'e', 'f' 4791 }; 4792 4793 /** 4794 * Returns <code>false</code> if the character is not whitespace or is equal 4795 * to any of the exception characters. 4796 * 4797 * @param c the character whose trim-ability is to be determined 4798 * @param exceptions the whitespace characters to exclude from trimming 4799 * @return <code>false</code> if the character is not whitespace or is equal 4800 * to any of the exception characters; <code>true</code> otherwise 4801 */ 4802 private static boolean _isTrimable(char c, char[] exceptions) { 4803 for (char exception : exceptions) { 4804 if (c == exception) { 4805 return false; 4806 } 4807 } 4808 4809 return Character.isWhitespace(c); 4810 } 4811 4812 private static String _wrap(String text, int width, String lineSeparator) 4813 throws IOException { 4814 4815 if (text == null) { 4816 return null; 4817 } 4818 4819 StringBundler sb = new StringBundler(); 4820 4821 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader( 4822 new UnsyncStringReader(text)); 4823 4824 String s = StringPool.BLANK; 4825 4826 while ((s = unsyncBufferedReader.readLine()) != null) { 4827 if (s.length() == 0) { 4828 sb.append(lineSeparator); 4829 4830 continue; 4831 } 4832 4833 int lineLength = 0; 4834 4835 String[] tokens = s.split(StringPool.SPACE); 4836 4837 for (String token : tokens) { 4838 if ((lineLength + token.length() + 1) > width) { 4839 if (lineLength > 0) { 4840 sb.append(lineSeparator); 4841 } 4842 4843 if (token.length() > width) { 4844 int pos = token.indexOf(CharPool.OPEN_PARENTHESIS); 4845 4846 if (pos != -1) { 4847 sb.append(token.substring(0, pos + 1)); 4848 sb.append(lineSeparator); 4849 4850 token = token.substring(pos + 1); 4851 4852 sb.append(token); 4853 4854 lineLength = token.length(); 4855 } 4856 else { 4857 sb.append(token); 4858 4859 lineLength = token.length(); 4860 } 4861 } 4862 else { 4863 sb.append(token); 4864 4865 lineLength = token.length(); 4866 } 4867 } 4868 else { 4869 if (lineLength > 0) { 4870 sb.append(StringPool.SPACE); 4871 4872 lineLength++; 4873 } 4874 4875 sb.append(token); 4876 4877 lineLength += token.length(); 4878 } 4879 } 4880 4881 sb.append(lineSeparator); 4882 } 4883 4884 return sb.toString(); 4885 } 4886 4887 private static final char[] _RANDOM_STRING_CHAR_TABLE = { 4888 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 4889 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 4890 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 4891 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 4892 'u', 'v', 'w', 'x', 'y', 'z' 4893 }; 4894 4895 private static final Log _log = LogFactoryUtil.getLog(StringUtil.class); 4896 4897 private static final String[] _emptyStringArray = new String[0]; 4898 4899 }