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