001 /** 002 * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved. 003 * 004 * The contents of this file are subject to the terms of the Liferay Enterprise 005 * Subscription License ("License"). You may not use this file except in 006 * compliance with the License. You can obtain a copy of the License by 007 * contacting Liferay, Inc. See the License for the specific language governing 008 * permissions and limitations under the License, including but not limited to 009 * distribution rights of the Software. 010 * 011 * 012 * 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 022 import java.io.IOException; 023 import java.io.InputStream; 024 import java.io.InputStreamReader; 025 026 import java.net.URL; 027 028 import java.util.ArrayList; 029 import java.util.Collection; 030 import java.util.Enumeration; 031 import java.util.List; 032 import java.util.Map; 033 import java.util.StringTokenizer; 034 import java.util.regex.Matcher; 035 import java.util.regex.Pattern; 036 037 /** 038 * The String utility class. 039 * 040 * @author Brian Wing Shun Chan 041 * @author Sandeep Soni 042 * @author Ganesh Ram 043 * @author Shuyang Zhou 044 */ 045 public class StringUtil { 046 047 /** 048 * Adds string <code>add</code> to string <code>s</code> resulting in a 049 * comma delimited list of strings, disallowing duplicate strings in the 050 * list. 051 * 052 * <p> 053 * The resulting string ends with a comma even if the original string does 054 * not. 055 * </p> 056 * 057 * @param s the original string, representing a comma delimited list of 058 * strings 059 * @param add the string to add to the original, representing the string to 060 * add to the list 061 * @return a string that represents the original string and the added string 062 * separated by a comma, or <code>null</code> if the string to add 063 * is <code>null</code> 064 */ 065 public static String add(String s, String add) { 066 return add(s, add, StringPool.COMMA); 067 } 068 069 /** 070 * Adds string <code>add</code> to string <code>s</code> that represents a 071 * delimited list of strings, using a specified delimiter and disallowing 072 * duplicate words. 073 * 074 * <p> 075 * The returned string ends with the delimiter even if the original string 076 * does not. 077 * </p> 078 * 079 * @param s the original string, representing a delimited list of strings 080 * @param add the string to add to the original, representing the string to 081 * add to the list 082 * @param delimiter the delimiter used to separate strings in the list 083 * @return a string that represents the original string and the added string 084 * separated by the delimiter, or <code>null</code> if the string to 085 * add or the delimiter string is <code>null</code> 086 */ 087 public static String add(String s, String add, String delimiter) { 088 return add(s, add, delimiter, false); 089 } 090 091 /** 092 * Adds string <code>add</code> to string <code>s</code> that represents a 093 * delimited list of strings, using a specified delimiter and optionally 094 * allowing duplicate words. 095 * 096 * <p> 097 * The returned string ends with the delimiter even if the original string 098 * does not. 099 * </p> 100 * 101 * @param s the original string, representing a delimited list of strings 102 * @param add the string to add to the original, representing the string to 103 * add to the list 104 * @param delimiter the delimiter used to separate strings in the list 105 * @param allowDuplicates whether to allow duplicate strings 106 * @return a string that represents the original string and the added string 107 * separated by the delimiter, or <code>null</code> if the string to 108 * add or the delimiter string is <code>null</code> 109 */ 110 public static String add( 111 String s, String add, String delimiter, boolean allowDuplicates) { 112 113 if ((add == null) || (delimiter == null)) { 114 return null; 115 } 116 117 if (s == null) { 118 s = StringPool.BLANK; 119 } 120 121 if (allowDuplicates || !contains(s, add, delimiter)) { 122 StringBundler sb = new StringBundler(); 123 124 sb.append(s); 125 126 if (Validator.isNull(s) || s.endsWith(delimiter)) { 127 sb.append(add); 128 sb.append(delimiter); 129 } 130 else { 131 sb.append(delimiter); 132 sb.append(add); 133 sb.append(delimiter); 134 } 135 136 s = sb.toString(); 137 } 138 139 return s; 140 } 141 142 /** 143 * Returns the original string with an appended space followed by the string 144 * value of the suffix surrounded by parentheses. 145 * 146 * <p> 147 * If the original string ends with a numerical parenthetical suffix having 148 * an integer value equal to <code>suffix - 1</code>, then the existing 149 * parenthetical suffix is replaced by the new one. 150 * </p> 151 * 152 * <p> 153 * Examples: 154 * </p> 155 * 156 * <pre> 157 * <code> 158 * appendParentheticalSuffix("file", 0) returns "file (0)" 159 * appendParentheticalSuffix("file (0)", 0) returns "file (0) (0)" 160 * appendParentheticalSuffix("file (0)", 1) returns "file (1)" 161 * appendParentheticalSuffix("file (0)", 2) returns "file (0) (2)" 162 * </code> 163 * </p> 164 * 165 * @param s the original string 166 * @param suffix the suffix to be appended 167 * @return the resultant string whose characters equal those of the original 168 * string, followed by a space, followed by the specified suffix 169 * enclosed in parentheses, or, if the difference between the 170 * provided suffix and the existing suffix is 1, the existing suffix 171 * is incremented by 1 172 */ 173 public static String appendParentheticalSuffix(String s, int suffix) { 174 if (Pattern.matches(".* \\(" + String.valueOf(suffix - 1) + "\\)", s)) { 175 int pos = s.lastIndexOf(" ("); 176 177 s = s.substring(0, pos); 178 } 179 180 return appendParentheticalSuffix(s, String.valueOf(suffix)); 181 } 182 183 /** 184 * Returns the original string with an appended space followed by the suffix 185 * surrounded by parentheses. 186 * 187 * <p> 188 * Example: 189 * </p> 190 * 191 * <pre> 192 * <code> 193 * appendParentheticalSuffix("Java", "EE") returns "Java (EE)" 194 * </code> 195 * </pre> 196 * 197 * @param s the original string 198 * @param suffix the suffix to be appended 199 * @return a string that represents the original string, followed by a 200 * space, followed by the suffix enclosed in parentheses 201 */ 202 public static String appendParentheticalSuffix(String s, String suffix) { 203 StringBundler sb = new StringBundler(5); 204 205 sb.append(s); 206 sb.append(StringPool.SPACE); 207 sb.append(StringPool.OPEN_PARENTHESIS); 208 sb.append(suffix); 209 sb.append(StringPool.CLOSE_PARENTHESIS); 210 211 return sb.toString(); 212 } 213 214 /** 215 * Converts an array of bytes to a string representing the bytes in 216 * hexadecimal form. 217 * 218 * @param bytes the array of bytes to be converted 219 * @return the string representing the bytes in hexadecimal form 220 */ 221 public static String bytesToHexString(byte[] bytes) { 222 StringBundler sb = new StringBundler(bytes.length * 2); 223 224 for (byte b : bytes) { 225 String hex = Integer.toHexString( 226 0x0100 + (b & 0x00FF)).substring(1); 227 228 if (hex.length() < 2) { 229 sb.append("0"); 230 } 231 232 sb.append(hex); 233 } 234 235 return sb.toString(); 236 } 237 238 /** 239 * Returns <code>true</code> if the string contains the text as a comma 240 * delimited list entry. 241 * 242 * <p> 243 * Example: 244 * </p> 245 * 246 * <pre> 247 * <code> 248 * contains("application", "app") returns true 249 * </code> 250 * </pre> 251 * 252 * @param s the string in which to search 253 * @param text the text to search for in the string 254 * @return <code>true</code> if the string contains the text as a comma 255 * delimited list entry; <code>false</code> otherwise 256 */ 257 public static boolean contains(String s, String text) { 258 return contains(s, text, StringPool.COMMA); 259 } 260 261 /** 262 * Returns <code>true</code> if the string contains the text as a delimited 263 * list entry. 264 * 265 * <p> 266 * Examples: 267 * </p> 268 * 269 * <pre> 270 * <code> 271 * contains("three...two...one", "two", "...") returns true 272 * contains("three...two...one", "thr", "...") returns false 273 * </code> 274 * </pre> 275 * 276 * @param s the string in which to search 277 * @param text the text to search for in the string 278 * @param delimiter the delimiter 279 * @return <code>true</code> if the string contains the text as a delimited 280 * list entry; <code>false</code> otherwise 281 */ 282 public static boolean contains(String s, String text, String delimiter) { 283 if ((s == null) || (text == null) || (delimiter == null)) { 284 return false; 285 } 286 287 if (!s.endsWith(delimiter)) { 288 s = s.concat(delimiter); 289 } 290 291 String dtd = delimiter.concat(text).concat(delimiter); 292 293 int pos = s.indexOf(dtd); 294 295 if (pos == -1) { 296 String td = text.concat(delimiter); 297 298 if (s.startsWith(td)) { 299 return true; 300 } 301 302 return false; 303 } 304 305 return true; 306 } 307 308 /** 309 * Returns the number of times the text appears in the string. 310 * 311 * @param s the string in which to search 312 * @param text the text to search for in the string 313 * @return the number of times the text appears in the string 314 */ 315 public static int count(String s, String text) { 316 if ((s == null) || (s.length() == 0) || (text == null) || 317 (text.length() == 0)) { 318 319 return 0; 320 } 321 322 int count = 0; 323 324 int pos = s.indexOf(text); 325 326 while (pos != -1) { 327 pos = s.indexOf(text, pos + text.length()); 328 329 count++; 330 } 331 332 return count; 333 } 334 335 /** 336 * Returns <code>true</code> if the string ends with the specified 337 * character. 338 * 339 * @param s the string in which to search 340 * @param end the character to search for at the end of the string 341 * @return <code>true</code> if the string ends with the specified 342 * character; <code>false</code> otherwise 343 */ 344 public static boolean endsWith(String s, char end) { 345 return endsWith(s, (new Character(end)).toString()); 346 } 347 348 /** 349 * Returns <code>true</code> if the string ends with the string 350 * <code>end</code>. 351 * 352 * @param s the string in which to search 353 * @param end the string to check for at the end of the string 354 * @return <code>true</code> if the string ends with the string 355 * <code>end</code>; <code>false</code> otherwise 356 */ 357 public static boolean endsWith(String s, String end) { 358 if ((s == null) || (end == null)) { 359 return false; 360 } 361 362 if (end.length() > s.length()) { 363 return false; 364 } 365 366 String temp = s.substring(s.length() - end.length()); 367 368 if (temp.equalsIgnoreCase(end)) { 369 return true; 370 } 371 else { 372 return false; 373 } 374 } 375 376 /** 377 * Returns the substring of each character instance in string <code>s</code> 378 * that is found in the character array <code>chars</code>. The substring of 379 * characters returned maintain their original order. 380 * 381 * @param s the string from which to extract characters 382 * @param chars the characters to extract from the string 383 * @return the substring of each character instance in string <code>s</code> 384 * that is found in the character array <code>chars</code>, or an 385 * empty string if the given string is <code>null</code> 386 */ 387 public static String extract(String s, char[] chars) { 388 if (s == null) { 389 return StringPool.BLANK; 390 } 391 392 StringBundler sb = new StringBundler(); 393 394 for (char c1 : s.toCharArray()) { 395 for (char c2 : chars) { 396 if (c1 == c2) { 397 sb.append(c1); 398 399 break; 400 } 401 } 402 } 403 404 return sb.toString(); 405 } 406 407 /** 408 * Returns the substring of English characters from the string. 409 * 410 * @param s the string from which to extract characters 411 * @return the substring of English characters from the string, or an empty 412 * string if the given string is <code>null</code> 413 */ 414 public static String extractChars(String s) { 415 if (s == null) { 416 return StringPool.BLANK; 417 } 418 419 StringBundler sb = new StringBundler(); 420 421 char[] chars = s.toCharArray(); 422 423 for (char c : chars) { 424 if (Validator.isChar(c)) { 425 sb.append(c); 426 } 427 } 428 429 return sb.toString(); 430 } 431 432 /** 433 * Returns a string consisting of all of the digits extracted from the 434 * string. 435 * 436 * @param s the string from which to extract digits 437 * @return a string consisting of all of the digits extracted from the 438 * string 439 */ 440 public static String extractDigits(String s) { 441 if (s == null) { 442 return StringPool.BLANK; 443 } 444 445 StringBundler sb = new StringBundler(); 446 447 char[] chars = s.toCharArray(); 448 449 for (char c : chars) { 450 if (Validator.isDigit(c)) { 451 sb.append(c); 452 } 453 } 454 455 return sb.toString(); 456 } 457 458 /** 459 * Returns the substring of <code>s</code> up to but not including the first 460 * occurrence of the delimiter. 461 * 462 * @param s the string from which to extract a substring 463 * @param delimiter the character whose index in the string marks where to 464 * end the substring 465 * @return the substring of <code>s</code> up to but not including the first 466 * occurrence of the delimiter, <code>null</code> if the string is 467 * <code>null</code> or the delimiter does not occur in the string 468 */ 469 public static String extractFirst(String s, char delimiter) { 470 if (s == null) { 471 return null; 472 } 473 else { 474 int index = s.indexOf(delimiter); 475 476 if (index < 0) { 477 return null; 478 } 479 else { 480 return s.substring(0, index); 481 } 482 } 483 } 484 485 /** 486 * Returns the substring of <code>s</code> up to but not including the first 487 * occurrence of the delimiter. 488 * 489 * @param s the string from which to extract a substring 490 * @param delimiter the smaller string whose index in the larger string 491 * marks where to end the substring 492 * @return the substring of <code>s</code> up to but not including the first 493 * occurrence of the delimiter, <code>null</code> if the string is 494 * <code>null</code> or the delimiter does not occur in the string 495 */ 496 public static String extractFirst(String s, String delimiter) { 497 if (s == null) { 498 return null; 499 } 500 else { 501 int index = s.indexOf(delimiter); 502 503 if (index < 0) { 504 return null; 505 } 506 else { 507 return s.substring(0, index); 508 } 509 } 510 } 511 512 /** 513 * Returns the substring of <code>s</code> after but not including the last 514 * occurrence of the delimiter. 515 * 516 * @param s the string from which to extract the substring 517 * @param delimiter the character whose last index in the string marks 518 * where to begin the substring 519 * @return the substring of <code>s</code> after but not including the last 520 * occurrence of the delimiter, <code>null</code> if the string is 521 * <code>null</code> or the delimiter does not occur in the string 522 */ 523 public static String extractLast(String s, char delimiter) { 524 if (s == null) { 525 return null; 526 } 527 else { 528 int index = s.lastIndexOf(delimiter); 529 530 if (index < 0) { 531 return null; 532 } 533 else { 534 return s.substring(index + 1); 535 } 536 } 537 } 538 539 /** 540 * Returns the substring of <code>s</code> after but not including the last 541 * occurrence of the delimiter. 542 * 543 * @param s the string from which to extract the substring 544 * @param delimiter the string whose last index in the string marks where 545 * to begin the substring 546 * @return the substring of <code>s</code> after but not including the last 547 * occurrence of the delimiter, <code>null</code> if the string is 548 * <code>null</code> or the delimiter does not occur in the string 549 */ 550 public static String extractLast(String s, String delimiter) { 551 if (s == null) { 552 return null; 553 } 554 else { 555 int index = s.lastIndexOf(delimiter); 556 557 if (index < 0) { 558 return null; 559 } 560 else { 561 return s.substring(index + delimiter.length()); 562 } 563 } 564 } 565 566 public static String extractLeadingDigits(String s) { 567 if (s == null) { 568 return StringPool.BLANK; 569 } 570 571 StringBundler sb = new StringBundler(); 572 573 char[] chars = s.toCharArray(); 574 575 for (char c : chars) { 576 if (Validator.isDigit(c)) { 577 sb.append(c); 578 } 579 else { 580 return sb.toString(); 581 } 582 } 583 584 return sb.toString(); 585 } 586 587 /** 588 * @deprecated 589 */ 590 public static String highlight(String s, String keywords) { 591 return highlight(s, keywords, "<span class=\"highlight\">", "</span>"); 592 } 593 594 /** 595 * @deprecated 596 */ 597 public static String highlight( 598 String s, String keywords, String highlight1, String highlight2) { 599 600 if (Validator.isNull(s) || Validator.isNull(keywords)) { 601 return s; 602 } 603 604 Pattern pattern = Pattern.compile( 605 Pattern.quote(keywords), Pattern.CASE_INSENSITIVE); 606 607 return _highlight(s, pattern, highlight1, highlight2); 608 } 609 610 public static String highlight(String s, String[] queryTerms) { 611 return highlight( 612 s, queryTerms, "<span class=\"highlight\">", "</span>"); 613 } 614 615 public static String highlight( 616 String s, String[] queryTerms, String highlight1, String highlight2) { 617 618 if (Validator.isNull(s) || Validator.isNull(queryTerms)) { 619 return s; 620 } 621 622 if (queryTerms.length == 0) { 623 return StringPool.BLANK; 624 } 625 626 StringBundler sb = new StringBundler(2 * queryTerms.length - 1); 627 628 for (int i = 0; i < queryTerms.length; i++) { 629 sb.append(Pattern.quote(queryTerms[i].trim())); 630 631 if ((i + 1) < queryTerms.length) { 632 sb.append(StringPool.PIPE); 633 } 634 } 635 636 int flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE; 637 638 Pattern pattern = Pattern.compile(sb.toString(), flags); 639 640 return _highlight(s, pattern, highlight1, highlight2); 641 } 642 643 /** 644 * Inserts one string into the other at the specified offset index. 645 * 646 * @param s the original string 647 * @param insert the string to be inserted into the original string 648 * @param offset the index of the original string where the insertion 649 * should take place 650 * @return a string representing the original string with the other string 651 * inserted at the specified offset index, or <code>null</code> if 652 * the original string is <code>null</code> 653 */ 654 public static String insert(String s, String insert, int offset) { 655 if (s == null) { 656 return null; 657 } 658 659 if (insert == null) { 660 return s; 661 } 662 663 if (offset > s.length()) { 664 return s.concat(insert); 665 } 666 else { 667 String prefix = s.substring(0, offset); 668 String postfix = s.substring(offset); 669 670 return prefix.concat(insert).concat(postfix); 671 } 672 } 673 674 /** 675 * Converts all of the characters in the string to lower case. 676 * 677 * @param s the string to convert 678 * @return the string, converted to lowercase, or <code>null</code> if the 679 * string is <code>null</code> 680 * @see {@link String#toLowerCase()} 681 */ 682 public static String lowerCase(String s) { 683 if (s == null) { 684 return null; 685 } 686 else { 687 return s.toLowerCase(); 688 } 689 } 690 691 /** 692 * Returns <code>true</code> if the specified pattern occurs at any position 693 * in the string. 694 * 695 * @param s the string 696 * @param pattern the pattern to search for in the string 697 * @return <code>true</code> if the specified pattern occurs at any position 698 * in the string 699 */ 700 public static boolean matches(String s, String pattern) { 701 String[] array = pattern.split("\\*"); 702 703 for (String element : array) { 704 int pos = s.indexOf(element); 705 706 if (pos == -1) { 707 return false; 708 } 709 710 s = s.substring(pos + element.length()); 711 } 712 713 return true; 714 } 715 716 /** 717 * Returns <code>true</code> if the specified pattern occurs at any position 718 * in the string, ignoring case. 719 * 720 * @param s the string 721 * @param pattern the pattern to search for in the string 722 * @return <code>true</code> if the specified pattern occurs at any position 723 * in the string 724 */ 725 public static boolean matchesIgnoreCase(String s, String pattern) { 726 return matches(lowerCase(s), lowerCase(pattern)); 727 } 728 729 /** 730 * Merges the elements of the boolean array into a string representing a 731 * comma delimited list of its values. 732 * 733 * @param array the boolean values to merge 734 * @return a string representing a comma delimited list of the values of the 735 * boolean array, an empty string if the array is empty, or 736 * <code>null</code> if the array is <code>null</code> 737 */ 738 public static String merge(boolean[] array) { 739 return merge(array, StringPool.COMMA); 740 } 741 742 /** 743 * Merges the elements of the boolean array into a string representing a 744 * delimited list of its values. 745 * 746 * @param array the boolean values to merge 747 * @param delimiter the delimiter 748 * @return a string representing a comma delimited list of the values of the 749 * boolean array, an empty string if the array is empty, or 750 * <code>null</code> if the array is <code>null</code> 751 */ 752 public static String merge(boolean[] array, String delimiter) { 753 if (array == null) { 754 return null; 755 } 756 757 if (array.length == 0) { 758 return StringPool.BLANK; 759 } 760 761 StringBundler sb = new StringBundler(2 * array.length - 1); 762 763 for (int i = 0; i < array.length; i++) { 764 sb.append(String.valueOf(array[i]).trim()); 765 766 if ((i + 1) != array.length) { 767 sb.append(delimiter); 768 } 769 } 770 771 return sb.toString(); 772 } 773 774 /** 775 * Merges the elements of the character array into a string representing a 776 * comma delimited list of its values. 777 * 778 * @param array the characters to merge 779 * @return a string representing a comma delimited list of the values of the 780 * character array, an empty string if the array is empty, or 781 * <code>null</code> if the array is <code>null</code> 782 */ 783 public static String merge(char[] array) { 784 return merge(array, StringPool.COMMA); 785 } 786 787 /** 788 * Merges the elements of the character array into a string representing a 789 * delimited list of its values. 790 * 791 * @param array the characters to merge 792 * @param delimiter the delimiter 793 * @return a string representing a delimited list of the values of the 794 * character array, an empty string if the array is empty, or 795 * <code>null</code> if the array is <code>null</code> 796 */ 797 public static String merge(char[] array, String delimiter) { 798 if (array == null) { 799 return null; 800 } 801 802 if (array.length == 0) { 803 return StringPool.BLANK; 804 } 805 806 StringBundler sb = new StringBundler(2 * array.length - 1); 807 808 for (int i = 0; i < array.length; i++) { 809 sb.append(String.valueOf(array[i]).trim()); 810 811 if ((i + 1) != array.length) { 812 sb.append(delimiter); 813 } 814 } 815 816 return sb.toString(); 817 } 818 819 public static String merge(Collection<?> col) { 820 return merge(col, StringPool.COMMA); 821 } 822 823 public static String merge(Collection<?> col, String delimiter) { 824 if (col == null) { 825 return null; 826 } 827 828 return merge(col.toArray(new Object[col.size()]), delimiter); 829 } 830 831 /** 832 * Merges the elements of an array of double-precision decimal numbers by 833 * returning a string representing a comma delimited list of its values. 834 * 835 * @param array the doubles to merge 836 * @return a string representing a comma delimited list of the values of the 837 * array of double-precision decimal numbers, an empty string if the 838 * array is empty, or <code>null</code> if the array is 839 * <code>null</code> 840 */ 841 public static String merge(double[] array) { 842 return merge(array, StringPool.COMMA); 843 } 844 845 /** 846 * Merges the elements of an array of double-precision decimal numbers by 847 * returning a string representing a delimited list of its values. 848 * 849 * @param array the doubles to merge 850 * @param delimiter the delimiter 851 * @return a string representing a delimited list of the values of the array 852 * of double-precision decimal numbers, an empty string if the array 853 * is empty, or <code>null</code> if the array is <code>null</code> 854 */ 855 public static String merge(double[] array, String delimiter) { 856 if (array == null) { 857 return null; 858 } 859 860 if (array.length == 0) { 861 return StringPool.BLANK; 862 } 863 864 StringBundler sb = new StringBundler(2 * array.length - 1); 865 866 for (int i = 0; i < array.length; i++) { 867 sb.append(String.valueOf(array[i]).trim()); 868 869 if ((i + 1) != array.length) { 870 sb.append(delimiter); 871 } 872 } 873 874 return sb.toString(); 875 } 876 877 /** 878 * Merges the elements of an array of decimal numbers into a string 879 * representing a comma delimited list of its values. 880 * 881 * @param array the floats to merge 882 * @return a string representing a comma delimited list of the values of the 883 * array of decimal numbers, an empty string if the array is empty, 884 * or <code>null</code> if the array is <code>null</code> 885 */ 886 public static String merge(float[] array) { 887 return merge(array, StringPool.COMMA); 888 } 889 890 /** 891 * Merges the elements of an array of decimal numbers into a string 892 * representing a delimited list of its values. 893 * 894 * @param array the floats to merge 895 * @param delimiter the delimiter 896 * @return a string representing a delimited list of the values of the array 897 * of decimal numbers, an empty string if the array is empty, or 898 * <code>null</code> if the array is <code>null</code> 899 */ 900 public static String merge(float[] array, String delimiter) { 901 if (array == null) { 902 return null; 903 } 904 905 if (array.length == 0) { 906 return StringPool.BLANK; 907 } 908 909 StringBundler sb = new StringBundler(2 * array.length - 1); 910 911 for (int i = 0; i < array.length; i++) { 912 sb.append(String.valueOf(array[i]).trim()); 913 914 if ((i + 1) != array.length) { 915 sb.append(delimiter); 916 } 917 } 918 919 return sb.toString(); 920 } 921 922 /** 923 * Merges the elements of an array of integers into a string representing a 924 * comma delimited list of its values. 925 * 926 * @param array the integers to merge 927 * @return a string representing a comma delimited list of the values of the 928 * array of integers, an empty string if the array is empty, or 929 * <code>null</code> if the array is <code>null</code> 930 */ 931 public static String merge(int[] array) { 932 return merge(array, StringPool.COMMA); 933 } 934 935 /** 936 * Merges the elements of an array of integers into a string representing a 937 * delimited list of its values. 938 * 939 * @param array the integers to merge 940 * @param delimiter the delimiter 941 * @return a string representing a delimited list of the values of the array 942 * of integers, an empty string if the array is empty, or 943 * <code>null</code> if the array is <code>null</code> 944 */ 945 public static String merge(int[] array, String delimiter) { 946 if (array == null) { 947 return null; 948 } 949 950 if (array.length == 0) { 951 return StringPool.BLANK; 952 } 953 954 StringBundler sb = new StringBundler(2 * array.length - 1); 955 956 for (int i = 0; i < array.length; i++) { 957 sb.append(String.valueOf(array[i]).trim()); 958 959 if ((i + 1) != array.length) { 960 sb.append(delimiter); 961 } 962 } 963 964 return sb.toString(); 965 } 966 967 /** 968 * Merges the elements of an array of long integers by returning a string 969 * representing a comma delimited list of its values. 970 * 971 * @param array the long integers to merge 972 * @return a string representing a comma delimited list of the values of the 973 * array of long integers, an empty string if the array is empty, or 974 * <code>null</code> if the array is <code>null</code> 975 */ 976 public static String merge(long[] array) { 977 return merge(array, StringPool.COMMA); 978 } 979 980 /** 981 * Merges the elements of an array of long integers by returning a string 982 * representing a delimited list of its values. 983 * 984 * @param array the long integers to merge 985 * @param delimiter the delimiter 986 * @return a string representing a delimited list of the values of the array 987 * of long integers, an empty string if the array is empty, or 988 * <code>null</code> if the array is <code>null</code> 989 */ 990 public static String merge(long[] array, String delimiter) { 991 if (array == null) { 992 return null; 993 } 994 995 if (array.length == 0) { 996 return StringPool.BLANK; 997 } 998 999 StringBundler sb = new StringBundler(2 * array.length - 1); 1000 1001 for (int i = 0; i < array.length; i++) { 1002 sb.append(String.valueOf(array[i]).trim()); 1003 1004 if ((i + 1) != array.length) { 1005 sb.append(delimiter); 1006 } 1007 } 1008 1009 return sb.toString(); 1010 } 1011 1012 /** 1013 * Merges the elements of an array of objects into a string representing a 1014 * comma delimited list of the objects. 1015 * 1016 * @param array the objects to merge 1017 * @return a string representing a comma delimited list of the objects, an 1018 * empty string if the array is empty, or <code>null</code> if the 1019 * array is <code>null</code> 1020 */ 1021 public static String merge(Object[] array) { 1022 return merge(array, StringPool.COMMA); 1023 } 1024 1025 /** 1026 * Merges the elements of an array of objects into a string representing a 1027 * delimited list of the objects. 1028 * 1029 * @param array the objects to merge 1030 * @param delimiter the delimiter 1031 * @return a string representing a delimited list of the objects, an empty 1032 * string if the array is empty, or <code>null</code> if the array 1033 * is <code>null</code> 1034 */ 1035 public static String merge(Object[] array, String delimiter) { 1036 if (array == null) { 1037 return null; 1038 } 1039 1040 if (array.length == 0) { 1041 return StringPool.BLANK; 1042 } 1043 1044 StringBundler sb = new StringBundler(2 * array.length - 1); 1045 1046 for (int i = 0; i < array.length; i++) { 1047 sb.append(String.valueOf(array[i]).trim()); 1048 1049 if ((i + 1) != array.length) { 1050 sb.append(delimiter); 1051 } 1052 } 1053 1054 return sb.toString(); 1055 } 1056 1057 /** 1058 * Merges the elements of an array of short integers by returning a string 1059 * representing a comma delimited list of its values. 1060 * 1061 * @param array the short integers to merge 1062 * @return a string representing a comma delimited list of the values of the 1063 * array of short integers, an empty string if the array is empty, 1064 * or <code>null</code> if the array is <code>null</code> 1065 */ 1066 public static String merge(short[] array) { 1067 return merge(array, StringPool.COMMA); 1068 } 1069 1070 /** 1071 * Merges the elements of an array of short integers by returning a string 1072 * representing a delimited list of its values. 1073 * 1074 * @param array the short integers to merge 1075 * @param delimiter the delimiter 1076 * @return a string representing a delimited list of the values of the array 1077 * of short integers, an empty string if the array is empty, or 1078 * <code>null</code> if the array is <code>null</code> 1079 */ 1080 public static String merge(short[] array, String delimiter) { 1081 if (array == null) { 1082 return null; 1083 } 1084 1085 if (array.length == 0) { 1086 return StringPool.BLANK; 1087 } 1088 1089 StringBundler sb = new StringBundler(2 * array.length - 1); 1090 1091 for (int i = 0; i < array.length; i++) { 1092 sb.append(String.valueOf(array[i]).trim()); 1093 1094 if ((i + 1) != array.length) { 1095 sb.append(delimiter); 1096 } 1097 } 1098 1099 return sb.toString(); 1100 } 1101 1102 /** 1103 * Returns the string enclosed by apostrophes. 1104 * 1105 * <p> 1106 * Example: 1107 * </p> 1108 * 1109 * <pre> 1110 * <code> 1111 * quote("Hello, World!") returns "'Hello, World!'" 1112 * </code> 1113 * </pre> 1114 * 1115 * @param s the string to enclose in apostrophes 1116 * @return the string enclosed by apostrophes, or <code>null</code> if the 1117 * string is <code>null</code> 1118 */ 1119 public static String quote(String s) { 1120 return quote(s, CharPool.APOSTROPHE); 1121 } 1122 1123 /** 1124 * Returns the string enclosed by the quote character. 1125 * 1126 * <p> 1127 * Example: 1128 * </p> 1129 * 1130 * <pre> 1131 * <code> 1132 * quote("PATH", '%') returns "%PATH%" 1133 * </code> 1134 * </pre> 1135 * 1136 * @param s the string to enclose in quotes 1137 * @param quote the character to insert to insert to the beginning of and 1138 * append to the end of the string 1139 * @return the string enclosed in the quote characters, or <code>null</code> 1140 * if the string is <code>null</code> 1141 */ 1142 public static String quote(String s, char quote) { 1143 if (s == null) { 1144 return null; 1145 } 1146 1147 return quote(s, String.valueOf(quote)); 1148 } 1149 1150 /** 1151 * Returns the string enclosed by the quote strings. 1152 * 1153 * <p> 1154 * Example: 1155 * </p> 1156 * 1157 * <pre> 1158 * <code> 1159 * quote("WARNING", "!!!") returns "!!!WARNING!!!" 1160 * </code> 1161 * </pre> 1162 * 1163 * @param s the string to enclose in quotes 1164 * @param quote the quote string to insert to insert to the beginning of 1165 * and append to the end of the string 1166 * @return the string enclosed in the quote strings, or <code>null</code> if 1167 * the string is <code>null</code> 1168 */ 1169 public static String quote(String s, String quote) { 1170 if (s == null) { 1171 return null; 1172 } 1173 1174 return quote.concat(s).concat(quote); 1175 } 1176 1177 /** 1178 * Pseudorandomly permutes the characters of the string. 1179 * 1180 * @param s the string whose characters are to be randomized 1181 * @return a string of the same length as the string whose characters 1182 * represent a pseudorandom permutation of the characters of the 1183 * string 1184 */ 1185 public static String randomize(String s) { 1186 return Randomizer.getInstance().randomize(s); 1187 } 1188 1189 public static String read(ClassLoader classLoader, String name) 1190 throws IOException { 1191 1192 return read(classLoader, name, false); 1193 } 1194 1195 public static String read(ClassLoader classLoader, String name, boolean all) 1196 throws IOException { 1197 1198 if (all) { 1199 StringBundler sb = new StringBundler(); 1200 1201 Enumeration<URL> enu = classLoader.getResources(name); 1202 1203 while (enu.hasMoreElements()) { 1204 URL url = enu.nextElement(); 1205 1206 InputStream is = url.openStream(); 1207 1208 if (is == null) { 1209 throw new IOException( 1210 "Unable to open resource at " + url.toString()); 1211 } 1212 1213 String s = read(is); 1214 1215 if (s != null) { 1216 sb.append(s); 1217 sb.append(StringPool.NEW_LINE); 1218 } 1219 1220 is.close(); 1221 } 1222 1223 return sb.toString().trim(); 1224 } 1225 else { 1226 InputStream is = classLoader.getResourceAsStream(name); 1227 1228 if (is == null) { 1229 throw new IOException( 1230 "Unable to open resource in class loader " + name); 1231 } 1232 1233 String s = read(is); 1234 1235 is.close(); 1236 1237 return s; 1238 } 1239 } 1240 1241 public static String read(InputStream is) throws IOException { 1242 StringBundler sb = new StringBundler(); 1243 1244 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader( 1245 new InputStreamReader(is)); 1246 1247 String line = null; 1248 1249 while ((line = unsyncBufferedReader.readLine()) != null) { 1250 sb.append(line); 1251 sb.append(CharPool.NEW_LINE); 1252 } 1253 1254 unsyncBufferedReader.close(); 1255 1256 return sb.toString().trim(); 1257 } 1258 1259 public static void readLines(InputStream is, Collection<String> lines) 1260 throws IOException { 1261 1262 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader( 1263 new InputStreamReader(is)); 1264 1265 String line = null; 1266 1267 while ((line = unsyncBufferedReader.readLine()) != null) { 1268 lines.add(line); 1269 } 1270 1271 unsyncBufferedReader.close(); 1272 } 1273 1274 /** 1275 * Removes the <code>remove</code> string from string <code>s</code> that 1276 * represents a list of comma delimited strings. 1277 * 1278 * <p> 1279 * The resulting string ends with a comma even if the original string does 1280 * not. 1281 * </p> 1282 * 1283 * <p> 1284 * Examples: 1285 * </p> 1286 * 1287 * <pre> 1288 * <code> 1289 * remove("red,blue,green,yellow", "blue") returns "red,green,yellow," 1290 * remove("blue", "blue") returns "" 1291 * remove("blue,", "blue") returns "" 1292 * </code> 1293 * </pre> 1294 * 1295 * @param s the string representing the list of comma delimited strings 1296 * @param remove the string to remove 1297 * @return a string representing the list of comma delimited strings with 1298 * the <code>remove</code> string removed, or <code>null</code> if 1299 * the original string, the string to remove, or the delimiter is 1300 * <code>null</code> 1301 */ 1302 public static String remove(String s, String remove) { 1303 return remove(s, remove, StringPool.COMMA); 1304 } 1305 1306 /** 1307 * Removes the <code>remove</code> string from string <code>s</code> that 1308 * represents a list of delimited strings. 1309 * 1310 * <p> 1311 * The resulting string ends with the delimiter even if the original string 1312 * does not. 1313 * </p> 1314 * 1315 * <p> 1316 * Examples: 1317 * </p> 1318 * 1319 * <pre> 1320 * <code> 1321 * remove("red;blue;green;yellow", "blue") returns "red,green,yellow;" 1322 * remove("blue", "blue") returns "" 1323 * remove("blue;", "blue") returns "" 1324 * </code> 1325 * </pre> 1326 * 1327 * @param s the string representing the list of delimited strings 1328 * @param remove the string to remove 1329 * @param delimiter the delimiter 1330 * @return a string representing the list of delimited strings with the 1331 * <code>remove</code> string removed, or <code>null</code> if the 1332 * original string, the string to remove, or the delimiter is 1333 * <code>null</code> 1334 */ 1335 public static String remove(String s, String remove, String delimiter) { 1336 if ((s == null) || (remove == null) || (delimiter == null)) { 1337 return null; 1338 } 1339 1340 if (Validator.isNotNull(s) && !s.endsWith(delimiter)) { 1341 s += delimiter; 1342 } 1343 1344 String drd = delimiter.concat(remove).concat(delimiter); 1345 1346 String rd = remove.concat(delimiter); 1347 1348 while (contains(s, remove, delimiter)) { 1349 int pos = s.indexOf(drd); 1350 1351 if (pos == -1) { 1352 if (s.startsWith(rd)) { 1353 int x = remove.length() + delimiter.length(); 1354 int y = s.length(); 1355 1356 s = s.substring(x, y); 1357 } 1358 } 1359 else { 1360 int x = pos + remove.length() + delimiter.length(); 1361 int y = s.length(); 1362 1363 String temp = s.substring(0, pos); 1364 1365 s = temp.concat(s.substring(x, y)); 1366 } 1367 } 1368 1369 return s; 1370 } 1371 1372 /** 1373 * Replaces all occurrences of the character with the new character. 1374 * 1375 * @param s the original string 1376 * @param oldSub the character to be searched for and replaced in the 1377 * original string 1378 * @param newSub the character with which to replace the 1379 * <code>oldSub</code> character 1380 * @return a string representing the original string with all occurrences of 1381 * the <code>oldSub</code> character replaced with the 1382 * <code>newSub</code> character, or <code>null</code> if the 1383 * original string is <code>null</code> 1384 */ 1385 public static String replace(String s, char oldSub, char newSub) { 1386 if (s == null) { 1387 return null; 1388 } 1389 1390 return s.replace(oldSub, newSub); 1391 } 1392 1393 /** 1394 * Replaces all occurrences of the character with the new string. 1395 * 1396 * @param s the original string 1397 * @param oldSub the character to be searched for and replaced in the 1398 * original string 1399 * @param newSub the string with which to replace the <code>oldSub</code> 1400 * character 1401 * @return a string representing the original string with all occurrences of 1402 * the <code>oldSub</code> character replaced with the string 1403 * <code>newSub</code>, or <code>null</code> if the original string 1404 * is <code>null</code> 1405 */ 1406 public static String replace(String s, char oldSub, String newSub) { 1407 if ((s == null) || (newSub == null)) { 1408 return null; 1409 } 1410 1411 // The number 5 is arbitrary and is used as extra padding to reduce 1412 // buffer expansion 1413 1414 StringBundler sb = new StringBundler(s.length() + 5 * newSub.length()); 1415 1416 char[] chars = s.toCharArray(); 1417 1418 for (char c : chars) { 1419 if (c == oldSub) { 1420 sb.append(newSub); 1421 } 1422 else { 1423 sb.append(c); 1424 } 1425 } 1426 1427 return sb.toString(); 1428 } 1429 1430 /** 1431 * Replaces all occurrences of the string with the new string. 1432 * 1433 * @param s the original string 1434 * @param oldSub the string to be searched for and replaced in the original 1435 * string 1436 * @param newSub the string with which to replace the <code>oldSub</code> 1437 * string 1438 * @return a string representing the original string with all occurrences of 1439 * the <code>oldSub</code> string replaced with the string 1440 * <code>newSub</code>, or <code>null</code> if the original string 1441 * is <code>null</code> 1442 */ 1443 public static String replace(String s, String oldSub, String newSub) { 1444 return replace(s, oldSub, newSub, 0); 1445 } 1446 1447 /** 1448 * Replaces all occurrences of the string with the new string, starting from 1449 * the specified index. 1450 * 1451 * @param s the original string 1452 * @param oldSub the string to be searched for and replaced in the original 1453 * string 1454 * @param newSub the string with which to replace the <code>oldSub</code> 1455 * string 1456 * @param fromIndex the index of the original string from which to begin 1457 * searching 1458 * @return a string representing the original string with all occurrences of 1459 * the <code>oldSub</code> string occurring after the specified 1460 * index replaced with the string <code>newSub</code>, or 1461 * <code>null</code> if the original string is <code>null</code> 1462 */ 1463 public static String replace( 1464 String s, String oldSub, String newSub, int fromIndex) { 1465 1466 if (s == null) { 1467 return null; 1468 } 1469 1470 if ((oldSub == null) || oldSub.equals(StringPool.BLANK)) { 1471 return s; 1472 } 1473 1474 if (newSub == null) { 1475 newSub = StringPool.BLANK; 1476 } 1477 1478 int y = s.indexOf(oldSub, fromIndex); 1479 1480 if (y >= 0) { 1481 StringBundler sb = new StringBundler(); 1482 1483 int length = oldSub.length(); 1484 int x = 0; 1485 1486 while (x <= y) { 1487 sb.append(s.substring(x, y)); 1488 sb.append(newSub); 1489 1490 x = y + length; 1491 y = s.indexOf(oldSub, x); 1492 } 1493 1494 sb.append(s.substring(x)); 1495 1496 return sb.toString(); 1497 } 1498 else { 1499 return s; 1500 } 1501 } 1502 1503 public static String replace( 1504 String s, String begin, String end, Map<String, String> values) { 1505 1506 StringBundler sb = replaceToStringBundler(s, begin, end, values); 1507 1508 return sb.toString(); 1509 } 1510 1511 /** 1512 * Replaces all occurrences of the elements of the string array with the 1513 * corresponding elements of the new string array. 1514 * 1515 * @param s the original string 1516 * @param oldSubs the strings to be searched for and replaced in the 1517 * original string 1518 * @param newSubs the strings with which to replace the 1519 * <code>oldSubs</code> strings 1520 * @return a string representing the original string with all occurrences of 1521 * the <code>oldSubs</code> strings replaced with the corresponding 1522 * <code>newSubs</code> strings, or <code>null</code> if the 1523 * original string, the <code>oldSubs</code> array, or the 1524 * <code>newSubs</code> is <code>null</code> 1525 */ 1526 public static String replace(String s, String[] oldSubs, String[] newSubs) { 1527 if ((s == null) || (oldSubs == null) || (newSubs == null)) { 1528 return null; 1529 } 1530 1531 if (oldSubs.length != newSubs.length) { 1532 return s; 1533 } 1534 1535 for (int i = 0; i < oldSubs.length; i++) { 1536 s = replace(s, oldSubs[i], newSubs[i]); 1537 } 1538 1539 return s; 1540 } 1541 1542 /** 1543 * Replaces all occurrences of the elements of the string array with the 1544 * corresponding elements of the new string array, optionally replacing only 1545 * substrings that are surrounded by word boundaries. 1546 * 1547 * <p> 1548 * Examples: 1549 * </p> 1550 * 1551 * <pre> 1552 * <code> 1553 * replace("redorangeyellow", {"red", "orange", "yellow"}, {"RED","ORANGE", "YELLOW"}, false) returns "REDORANGEYELLOW" 1554 * replace("redorangeyellow", {"red", "orange", "yellow"}, {"RED","ORANGE", "YELLOW"}, true) returns "redorangeyellow" 1555 * replace("redorange yellow", {"red", "orange", "yellow"}, {"RED","ORANGE", "YELLOW"}, false) returns "REDORANGE YELLOW" 1556 * replace("redorange yellow", {"red", "orange", "yellow"}, {"RED","ORANGE", "YELLOW"}, true) returns "redorange YELLOW" 1557 * replace("red orange yellow", {"red", "orange", "yellow"}, {"RED","ORANGE", "YELLOW"}, false) returns "RED ORANGE YELLOW" 1558 * replace("redorange.yellow", {"red", "orange", "yellow"}, {"RED","ORANGE", * "YELLOW"}, true) returns "redorange.YELLOW" 1559 * </code> 1560 * </pre> 1561 * 1562 * @param s the original string 1563 * @param oldSubs the strings to be searched for and replaced in the 1564 * original string 1565 * @param newSubs the strings with which to replace the 1566 * <code>oldSubs</code> strings 1567 * @param exactMatch whether or not to replace only substrings of 1568 * <code>s</code> that are surrounded by word boundaries 1569 * @return if <code>exactMatch</code> is <code>true</code>, a string 1570 * representing the original string with all occurrences of the 1571 * <code>oldSubs</code> strings that are surrounded by word 1572 * boundaries replaced with the corresponding <code>newSubs</code> 1573 * strings, or else a string representing the original string with 1574 * all occurrences of the <code>oldSubs</code> strings replaced with 1575 * the corresponding <code>newSubs</code> strings, or 1576 * <code>null</code> if the original string, the 1577 * <code>oldSubs</code> array, or the <code>newSubs</code is 1578 * <code>null</code> 1579 */ 1580 public static String replace( 1581 String s, String[] oldSubs, String[] newSubs, boolean exactMatch) { 1582 1583 if ((s == null) || (oldSubs == null) || (newSubs == null)) { 1584 return null; 1585 } 1586 1587 if (oldSubs.length != newSubs.length) { 1588 return s; 1589 } 1590 1591 if (!exactMatch) { 1592 return replace(s, oldSubs, newSubs); 1593 } 1594 1595 for (int i = 0; i < oldSubs.length; i++) { 1596 s = s.replaceAll("\\b" + oldSubs[i] + "\\b", newSubs[i]); 1597 } 1598 1599 return s; 1600 } 1601 1602 /** 1603 * Replaces the first occurrence of the character with the new character. 1604 * 1605 * @param s the original string 1606 * @param oldSub the character whose first occurrence in the original 1607 * string is to be searched for and replaced 1608 * @param newSub the character with which to replace the first occurrence 1609 * of the <code>oldSub</code> character 1610 * @return a string representing the original string except with the first 1611 * occurrence of the character <code>oldSub</code> replaced with the 1612 * character <code>newSub</code> 1613 */ 1614 public static String replaceFirst(String s, char oldSub, char newSub) { 1615 if (s == null) { 1616 return null; 1617 } 1618 1619 return replaceFirst(s, String.valueOf(oldSub), String.valueOf(newSub)); 1620 } 1621 1622 /** 1623 * Replaces the first occurrence of the character with the new string. 1624 * 1625 * @param s the original string 1626 * @param oldSub the character whose first occurrence in the original 1627 * string is to be searched for and replaced 1628 * @param newSub the string with which to replace the first occurrence of 1629 * the <code>oldSub</code> character 1630 * @return a string representing the original string except with the first 1631 * occurrence of the character <code>oldSub</code> replaced with the 1632 * string <code>newSub</code> 1633 */ 1634 public static String replaceFirst(String s, char oldSub, String newSub) { 1635 if ((s == null) || (newSub == null)) { 1636 return null; 1637 } 1638 1639 return replaceFirst(s, String.valueOf(oldSub), newSub); 1640 } 1641 1642 /** 1643 * Replaces the first occurrence of the string with the new string. 1644 * 1645 * @param s the original string 1646 * @param oldSub the string whose first occurrence in the original string 1647 * is to be searched for and replaced 1648 * @param newSub the string with which to replace the first occurrence of 1649 * the <code>oldSub</code> string 1650 * @return a string representing the original string except with the first 1651 * occurrence of the string <code>oldSub</code> replaced with the 1652 * string <code>newSub</code> 1653 */ 1654 public static String replaceFirst(String s, String oldSub, String newSub) { 1655 if ((s == null) || (oldSub == null) || (newSub == null)) { 1656 return null; 1657 } 1658 1659 if (oldSub.equals(newSub)) { 1660 return s; 1661 } 1662 1663 int y = s.indexOf(oldSub); 1664 1665 if (y >= 0) { 1666 return s.substring(0, y).concat(newSub).concat( 1667 s.substring(y + oldSub.length())); 1668 } 1669 else { 1670 return s; 1671 } 1672 } 1673 1674 /** 1675 * Replaces the first occurrences of the elements of the string array with 1676 * the corresponding elements of the new string array. 1677 * 1678 * @param s the original string 1679 * @param oldSubs the strings whose first occurrences are to be searched 1680 * for and replaced in the original string 1681 * @param newSubs the strings with which to replace the first occurrences 1682 * of the <code>oldSubs</code> strings 1683 * @return a string representing the original string with the first 1684 * occurrences of the <code>oldSubs</code> strings replaced with the 1685 * corresponding <code>newSubs</code> strings, or <code>null</code> 1686 * if the original string, the <code>oldSubs</code> array, or the 1687 * <code>newSubs</code is <code>null</code> 1688 */ 1689 public static String replaceFirst( 1690 String s, String[] oldSubs, String[] newSubs) { 1691 1692 if ((s == null) || (oldSubs == null) || (newSubs == null)) { 1693 return null; 1694 } 1695 1696 if (oldSubs.length != newSubs.length) { 1697 return s; 1698 } 1699 1700 for (int i = 0; i < oldSubs.length; i++) { 1701 s = replaceFirst(s, oldSubs[i], newSubs[i]); 1702 } 1703 1704 return s; 1705 } 1706 1707 /** 1708 * Replaces the last occurrence of the character with the new character. 1709 * 1710 * @param s the original string 1711 * @param oldSub the character whose last occurrence in the original string 1712 * is to be searched for and replaced 1713 * @param newSub the character with which to replace the last occurrence of 1714 * the <code>oldSub</code> character 1715 * @return a string representing the original string except with the first 1716 * occurrence of the character <code>oldSub</code> replaced with the 1717 * character <code>newSub</code> 1718 */ 1719 public static String replaceLast(String s, char oldSub, char newSub) { 1720 if (s == null) { 1721 return null; 1722 } 1723 1724 return replaceLast(s, String.valueOf(oldSub), String.valueOf(newSub)); 1725 } 1726 1727 /** 1728 * Replaces the last occurrence of the character with the new string. 1729 * 1730 * @param s the original string 1731 * @param oldSub the character whose last occurrence in the original string 1732 * is to be searched for and replaced 1733 * @param newSub the string with which to replace the last occurrence of 1734 * the <code>oldSub</code> character 1735 * @return a string representing the original string except with the last 1736 * occurrence of the character <code>oldSub</code> replaced with the 1737 * string <code>newSub</code> 1738 */ 1739 public static String replaceLast(String s, char oldSub, String newSub) { 1740 if ((s == null) || (newSub == null)) { 1741 return null; 1742 } 1743 1744 return replaceLast(s, String.valueOf(oldSub), newSub); 1745 } 1746 1747 /** 1748 * Replaces the last occurrence of the string <code>oldSub</code> in the 1749 * string <code>s</code> with the string <code>newSub</code>. 1750 * 1751 * @param s the original string 1752 * @param oldSub the string whose last occurrence in the original string is 1753 * to be searched for and replaced 1754 * @param newSub the string with which to replace the last occurrence of 1755 * the <code>oldSub</code> string 1756 * @return a string representing the original string except with the last 1757 * occurrence of the string <code>oldSub</code> replaced with the 1758 * string <code>newSub</code> 1759 */ 1760 public static String replaceLast(String s, String oldSub, String newSub) { 1761 if ((s == null) || (oldSub == null) || (newSub == null)) { 1762 return null; 1763 } 1764 1765 if (oldSub.equals(newSub)) { 1766 return s; 1767 } 1768 1769 int y = s.lastIndexOf(oldSub); 1770 1771 if (y >= 0) { 1772 return s.substring(0, y).concat(newSub).concat( 1773 s.substring(y + oldSub.length())); 1774 } 1775 else { 1776 return s; 1777 } 1778 } 1779 1780 /** 1781 * Replaces the last occurrences of the elements of the string array with 1782 * the corresponding elements of the new string array. 1783 * 1784 * @param s the original string 1785 * @param oldSubs the strings whose last occurrences are to be searched for 1786 * and replaced in the original string 1787 * @param newSubs the strings with which to replace the last occurrences of 1788 * the <code>oldSubs</code> strings 1789 * @return a string representing the original string with the last 1790 * occurrences of the <code>oldSubs</code> strings replaced with the 1791 * corresponding <code>newSubs</code> strings, or <code>null</code> 1792 * if the original string, the <code>oldSubs</code> array, or the 1793 * <code>newSubs</code is <code>null</code> 1794 */ 1795 public static String replaceLast( 1796 String s, String[] oldSubs, String[] newSubs) { 1797 1798 if ((s == null) || (oldSubs == null) || (newSubs == null)) { 1799 return null; 1800 } 1801 1802 if (oldSubs.length != newSubs.length) { 1803 return s; 1804 } 1805 1806 for (int i = 0; i < oldSubs.length; i++) { 1807 s = replaceLast(s, oldSubs[i], newSubs[i]); 1808 } 1809 1810 return s; 1811 } 1812 1813 public static StringBundler replaceToStringBundler( 1814 String s, String begin, String end, Map<String, String> values) { 1815 1816 if ((s == null) || (begin == null) || (end == null) || 1817 (values == null) || (values.size() == 0)) { 1818 1819 return new StringBundler(s); 1820 } 1821 1822 StringBundler sb = new StringBundler(values.size() * 2 + 1); 1823 1824 int pos = 0; 1825 1826 while (true) { 1827 int x = s.indexOf(begin, pos); 1828 int y = s.indexOf(end, x + begin.length()); 1829 1830 if ((x == -1) || (y == -1)) { 1831 sb.append(s.substring(pos)); 1832 1833 break; 1834 } 1835 else { 1836 sb.append(s.substring(pos, x)); 1837 1838 String oldValue = s.substring(x + begin.length(), y); 1839 1840 String newValue = values.get(oldValue); 1841 1842 if (newValue == null) { 1843 newValue = oldValue; 1844 } 1845 1846 sb.append(newValue); 1847 1848 pos = y + end.length(); 1849 } 1850 } 1851 1852 return sb; 1853 } 1854 1855 public static StringBundler replaceWithStringBundler( 1856 String s, String begin, String end, Map<String, StringBundler> values) { 1857 1858 if ((s == null) || (begin == null) || (end == null) || 1859 (values == null) || (values.size() == 0)) { 1860 1861 return new StringBundler(s); 1862 } 1863 1864 int size = values.size() + 1; 1865 1866 for (StringBundler valueSB : values.values()) { 1867 size += valueSB.index(); 1868 } 1869 1870 StringBundler sb = new StringBundler(size); 1871 1872 int pos = 0; 1873 1874 while (true) { 1875 int x = s.indexOf(begin, pos); 1876 int y = s.indexOf(end, x + begin.length()); 1877 1878 if ((x == -1) || (y == -1)) { 1879 sb.append(s.substring(pos)); 1880 1881 break; 1882 } 1883 else { 1884 sb.append(s.substring(pos, x)); 1885 1886 String oldValue = s.substring(x + begin.length(), y); 1887 1888 StringBundler newValue = values.get(oldValue); 1889 1890 if (newValue == null) { 1891 sb.append(oldValue); 1892 } 1893 else { 1894 sb.append(newValue); 1895 } 1896 1897 pos = y + end.length(); 1898 } 1899 } 1900 1901 return sb; 1902 } 1903 1904 /** 1905 * Reverses the order of the characters of the string. 1906 * 1907 * @param s the original string 1908 * @return a string representing the original string with characters in 1909 * reverse order 1910 */ 1911 public static String reverse(String s) { 1912 if (s == null) { 1913 return null; 1914 } 1915 1916 char[] chars = s.toCharArray(); 1917 char[] reverse = new char[chars.length]; 1918 1919 for (int i = 0; i < chars.length; i++) { 1920 reverse[i] = chars[chars.length - i - 1]; 1921 } 1922 1923 return new String(reverse); 1924 } 1925 1926 /** 1927 * Replaces all double slashes of the string with single slashes. 1928 * 1929 * <p> 1930 * Example: 1931 * </p> 1932 * 1933 * <pre> 1934 * <code> 1935 * safePath("http://www.liferay.com") returns "http:/www.liferay.com" 1936 * </code> 1937 * </pre> 1938 * 1939 * @param path the original string 1940 * @return a string representing the original string with all double slashes 1941 * replaced with single slashes 1942 */ 1943 public static String safePath(String path) { 1944 return replace(path, StringPool.DOUBLE_SLASH, StringPool.SLASH); 1945 } 1946 1947 /** 1948 * Returns a string representing the original string appended with suffix 1949 * "..." and then shortened to 20 characters. 1950 * 1951 * <p> 1952 * The suffix is only added if the original string exceeds 20 characters. If 1953 * the original string exceeds 20 characters and it contains whitespace, the 1954 * string is shortened at the first whitespace character. 1955 * </p> 1956 * 1957 * <p> 1958 * Examples: 1959 * </p> 1960 * 1961 * <pre> 1962 * <code> 1963 * shorten("12345678901234567890xyz") returns "12345678901234567..." 1964 * shorten("1 345678901234567890xyz") returns "1..." 1965 * shorten(" 2345678901234567890xyz") returns "..." 1966 * shorten("12345678901234567890") returns "12345678901234567890" 1967 * shorten(" 2345678901234567890") returns " 2345678901234567890" 1968 * </code> 1969 * </pre> 1970 * 1971 * @param s the original string 1972 * @return a string representing the original string shortened to 20 1973 * characters, with suffix "..." appended to it 1974 */ 1975 public static String shorten(String s) { 1976 return shorten(s, 20); 1977 } 1978 1979 /** 1980 * Returns a string representing the original string appended with suffix 1981 * "..." and then shortened to the specified length. 1982 * 1983 * <p> 1984 * The suffix is only added if the original string exceeds the specified 1985 * length. If the original string exceeds the specified length and it 1986 * contains whitespace, the string is shortened at the first whitespace 1987 * character. 1988 * </p> 1989 * 1990 * <p> 1991 * Examples: 1992 * </p> 1993 * 1994 * <pre> 1995 * <code> 1996 * shorten("123456789", 8) returns "12345..." 1997 * shorten("1 3456789", 8) returns "1..." 1998 * shorten(" 23456789", 8) returns "..." 1999 * shorten("12345678", 8) returns "12345678" 2000 * shorten(" 1234567", 8) returns " 1234567" 2001 * </code> 2002 * </pre> 2003 * 2004 * @param s the original string 2005 * @param length the number of characters to limit from the original string 2006 * @return a string representing the original string shortened to the 2007 * specified length, with suffix "..." appended to it 2008 */ 2009 public static String shorten(String s, int length) { 2010 return shorten(s, length, "..."); 2011 } 2012 2013 /** 2014 * Returns a string representing the original string appended with the 2015 * specified suffix and then shortened to the specified length. 2016 * 2017 * <p> 2018 * The suffix is only added if the original string exceeds the specified 2019 * length. If the original string exceeds the specified length and it 2020 * contains whitespace, the string is shortened at the first whitespace 2021 * character. 2022 * </p> 2023 * 2024 * <p> 2025 * Examples: 2026 * </p> 2027 * 2028 * <pre> 2029 * <code> 2030 * shorten("12345678901234", 13, "... etc.") returns "12345... etc." 2031 * shorten("1 345678901234", 13, "... etc.") returns "1... etc." 2032 * shorten(" 2345678901234", 13, "... etc.") returns "... etc." 2033 * shorten("1234567890123", 13, "... etc.") returns "1234567890123" 2034 * shorten(" 123456789012", 13, "... etc.") returns " 123456789012" 2035 * </code> 2036 * </pre> 2037 * 2038 * @param s the original string 2039 * @param length the number of characters to limit from the original string 2040 * @param suffix the suffix to append 2041 * @return a string representing the original string shortened to the 2042 * specified length, with the specified suffix appended to it 2043 */ 2044 public static String shorten(String s, int length, String suffix) { 2045 if ((s == null) || (suffix == null)) { 2046 return null; 2047 } 2048 2049 if (s.length() <= length) { 2050 return s; 2051 } 2052 2053 if (length < suffix.length()) { 2054 return s.substring(0, length); 2055 } 2056 2057 int curLength = length; 2058 2059 for (int j = (curLength - suffix.length()); j >= 0; j--) { 2060 if (Character.isWhitespace(s.charAt(j))) { 2061 curLength = j; 2062 2063 break; 2064 } 2065 } 2066 2067 if (curLength == length) { 2068 curLength = length - suffix.length(); 2069 } 2070 2071 String temp = s.substring(0, curLength); 2072 2073 return temp.concat(suffix); 2074 } 2075 2076 /** 2077 * Returns a string representing the original string appended with the 2078 * specified suffix and then shortened to 20 characters. 2079 * 2080 * <p> 2081 * The suffix is only added if the original string exceeds 20 characters. If 2082 * the original string exceeds 20 characters and it contains whitespace, the 2083 * string is shortened at the first whitespace character. 2084 * </p> 2085 * 2086 * <p> 2087 * Examples: 2088 * </p> 2089 * 2090 * <pre> 2091 * <code> 2092 * shorten("12345678901234567890xyz", "... etc.") returns "123456789012... etc." 2093 * shorten("1 345678901234567890xyz", "... etc.") returns "1... etc." 2094 * shorten(" 2345678901234567890xyz", "... etc.") returns "... etc." 2095 * shorten("12345678901234567890", "... etc.") returns "12345678901234567890" 2096 * shorten(" 2345678901234567890", "... etc.") returns " 2345678901234567890" 2097 * </code> 2098 * </pre> 2099 * 2100 * @param s the original string 2101 * @param suffix the suffix to append 2102 * @return a string representing the original string shortened to 20 2103 * characters, with the specified suffix appended to it 2104 */ 2105 public static String shorten(String s, String suffix) { 2106 return shorten(s, 20, suffix); 2107 } 2108 2109 /** 2110 * Splits string <code>s</code> around comma characters. 2111 * 2112 * <p> 2113 * Example: 2114 * </p> 2115 * 2116 * <pre> 2117 * <code> 2118 * split("Alice,Bob,Charlie") returns {"Alice", "Bob", "Charlie"} 2119 * split("Alice, Bob, Charlie") returns {"Alice", " Bob", " Charlie"} 2120 * </code> 2121 * </pre> 2122 * 2123 * @param s the string to split 2124 * @return the array of strings resulting from splitting string 2125 * <code>s</code> around comma characters, or an empty string array 2126 * if <code>s</code> is <code>null</code> or <code>s</code> is empty 2127 */ 2128 public static String[] split(String s) { 2129 return split(s, CharPool.COMMA); 2130 } 2131 2132 /** 2133 * Splits the string <code>s</code> around comma characters returning the 2134 * boolean values of the substrings. 2135 * 2136 * @param x the default value to use for a substring in case an exception 2137 * occurs in getting the boolean value for that substring 2138 * @return the array of boolean values resulting from splitting string 2139 * <code>s</code> around comma characters, or an empty array if 2140 * <code>s</code> is <code>null</code> 2141 */ 2142 public static boolean[] split(String s, boolean x) { 2143 return split(s, StringPool.COMMA, x); 2144 } 2145 2146 /** 2147 * Splits the string <code>s</code> around the specified delimiter. 2148 * 2149 * <p> 2150 * Example: 2151 * </p> 2152 * 2153 * <pre> 2154 * <code> 2155 * splitLines("First;Second;Third", ';') returns {"First","Second","Third"} 2156 * </code> 2157 * </pre> 2158 * 2159 * @param s the string to split 2160 * @param delimiter the delimiter 2161 * @return the array of strings resulting from splitting string 2162 * <code>s</code> around the specified delimiter character, or an 2163 * empty string array if <code>s</code> is <code>null</code> or if 2164 * <code>s</code> is empty 2165 */ 2166 public static String[] split(String s, char delimiter) { 2167 if (Validator.isNull(s)) { 2168 return _emptyStringArray; 2169 } 2170 2171 s = s.trim(); 2172 2173 if (s.length() == 0) { 2174 return _emptyStringArray; 2175 } 2176 2177 if ((delimiter == CharPool.RETURN) || 2178 (delimiter == CharPool.NEW_LINE)) { 2179 2180 return splitLines(s); 2181 } 2182 2183 List<String> nodeValues = new ArrayList<String>(); 2184 2185 int offset = 0; 2186 int pos = s.indexOf(delimiter, offset); 2187 2188 while (pos != -1) { 2189 nodeValues.add(s.substring(offset, pos)); 2190 2191 offset = pos + 1; 2192 pos = s.indexOf(delimiter, offset); 2193 } 2194 2195 if (offset < s.length()) { 2196 nodeValues.add(s.substring(offset)); 2197 } 2198 2199 return nodeValues.toArray(new String[nodeValues.size()]); 2200 } 2201 2202 /** 2203 * Splits the string <code>s</code> around comma characters returning the 2204 * double-precision decimal values of the substrings. 2205 * 2206 * @param x the default value to use for a substring in case an exception 2207 * occurs in getting the double-precision decimal value for that 2208 * substring 2209 * @return the array of double-precision decimal values resulting from 2210 * splitting string <code>s</code> around comma characters, or an 2211 * empty array if <code>s</code> is <code>null</code> 2212 */ 2213 public static double[] split(String s, double x) { 2214 return split(s, StringPool.COMMA, x); 2215 } 2216 2217 /** 2218 * Splits the string <code>s</code> around comma characters returning the 2219 * decimal values of the substrings. 2220 * 2221 * @param x the default value to use for a substring in case an exception 2222 * occurs in getting the decimal value for that substring 2223 * @return the array of decimal values resulting from splitting string 2224 * <code>s</code> around comma characters, or an empty array if 2225 * <code>s</code> is <code>null</code> 2226 */ 2227 public static float[] split(String s, float x) { 2228 return split(s, StringPool.COMMA, x); 2229 } 2230 2231 /** 2232 * Splits the string <code>s</code> around comma characters returning the 2233 * integer values of the substrings. 2234 * 2235 * @param x the default value to use for a substring in case an exception 2236 * occurs in getting the integer value for that substring 2237 * @return the array of integer values resulting from splitting string 2238 * <code>s</code> around comma characters, or an empty array if 2239 * <code>s</code> is <code>null</code> 2240 */ 2241 public static int[] split(String s, int x) { 2242 return split(s, StringPool.COMMA, x); 2243 } 2244 2245 /** 2246 * Splits the string <code>s</code> around comma characters returning the 2247 * long integer values of the substrings. 2248 * 2249 * @param x the default value to use for a substring in case an exception 2250 * occurs in getting the long integer value for that substring 2251 * @return the array of long integer values resulting from splitting string 2252 * <code>s</code> around comma characters, or an empty array if 2253 * <code>s</code> is <code>null</code> 2254 */ 2255 public static long[] split(String s, long x) { 2256 return split(s, StringPool.COMMA, x); 2257 } 2258 2259 /** 2260 * Splits the string <code>s</code> around comma characters returning the 2261 * short integer values of the substrings. 2262 * 2263 * @param x the default value to use for a substring in case an exception 2264 * occurs in getting the short integer value for that substring 2265 * @return the array of short integer values resulting from splitting string 2266 * <code>s</code> around comma characters, or an empty array if 2267 * <code>s</code> is <code>null</code> 2268 */ 2269 public static short[] split(String s, short x) { 2270 return split(s, StringPool.COMMA, x); 2271 } 2272 2273 /** 2274 * Splits the string <code>s</code> around the specified delimiter string. 2275 * 2276 * <p> 2277 * Example: 2278 * </p> 2279 * 2280 * <pre> 2281 * <code> 2282 * splitLines("oneandtwoandthreeandfour", "and") returns {"one","two","three","four"} 2283 * </code> 2284 * </pre> 2285 * 2286 * @param s the string to split 2287 * @param delimiter the delimiter 2288 * @return the array of strings resulting from splitting string 2289 * <code>s</code> around the specified delimiter string, or an empty 2290 * string array if <code>s</code> is <code>null</code> or equals the 2291 * delimiter 2292 */ 2293 public static String[] split(String s, String delimiter) { 2294 if (Validator.isNull(s) || (delimiter == null) || 2295 delimiter.equals(StringPool.BLANK)) { 2296 2297 return _emptyStringArray; 2298 } 2299 2300 s = s.trim(); 2301 2302 if (s.equals(delimiter)) { 2303 return _emptyStringArray; 2304 } 2305 2306 if (delimiter.length() == 1) { 2307 return split(s, delimiter.charAt(0)); 2308 } 2309 2310 List<String> nodeValues = new ArrayList<String>(); 2311 2312 int offset = 0; 2313 int pos = s.indexOf(delimiter, offset); 2314 2315 while (pos != -1) { 2316 nodeValues.add(s.substring(offset, pos)); 2317 2318 offset = pos + delimiter.length(); 2319 pos = s.indexOf(delimiter, offset); 2320 } 2321 2322 if (offset < s.length()) { 2323 nodeValues.add(s.substring(offset)); 2324 } 2325 2326 return nodeValues.toArray(new String[nodeValues.size()]); 2327 } 2328 2329 /** 2330 * Splits the string <code>s</code> around the specified delimiter returning 2331 * the boolean values of the substrings. 2332 * 2333 * @param s the string to split 2334 * @param delimiter the delimiter 2335 * @param x the default value to use for a substring in case an exception 2336 * occurs in getting the boolean value for that substring 2337 * @return the array of booleans resulting from splitting string 2338 * <code>s</code> around the specified delimiter string, or an empty 2339 * array if <code>s</code> is <code>null</code> 2340 */ 2341 public static boolean[] split(String s, String delimiter, boolean x) { 2342 String[] array = split(s, delimiter); 2343 boolean[] newArray = new boolean[array.length]; 2344 2345 for (int i = 0; i < array.length; i++) { 2346 boolean value = x; 2347 2348 try { 2349 value = Boolean.valueOf(array[i]).booleanValue(); 2350 } 2351 catch (Exception e) { 2352 } 2353 2354 newArray[i] = value; 2355 } 2356 2357 return newArray; 2358 } 2359 2360 /** 2361 * Splits the string <code>s</code> around the specified delimiter returning 2362 * the double-precision decimal values of the substrings. 2363 * 2364 * @param s the string to split 2365 * @param delimiter the delimiter 2366 * @param x the default value to use for a substring in case an exception 2367 * occurs in getting the double-precision decimal value for that 2368 * substring 2369 * @return the array of double-precision decimal values resulting from 2370 * splitting string <code>s</code> around the specified delimiter 2371 * string, or an empty array if <code>s</code> is <code>null</code> 2372 */ 2373 public static double[] split(String s, String delimiter, double x) { 2374 String[] array = split(s, delimiter); 2375 double[] newArray = new double[array.length]; 2376 2377 for (int i = 0; i < array.length; i++) { 2378 double value = x; 2379 2380 try { 2381 value = Double.parseDouble(array[i]); 2382 } 2383 catch (Exception e) { 2384 } 2385 2386 newArray[i] = value; 2387 } 2388 2389 return newArray; 2390 } 2391 2392 /** 2393 * Splits the string <code>s</code> around the specified delimiter returning 2394 * the decimal values of the substrings. 2395 * 2396 * @param s the string to split 2397 * @param delimiter the delimiter 2398 * @param x the default value to use for a substring in case an exception 2399 * occurs in getting the decimal value for that substring 2400 * @return the array of decimal values resulting from splitting string 2401 * <code>s</code> around the specified delimiter string, or an empty 2402 * array if <code>s</code> is <code>null</code> 2403 */ 2404 public static float[] split(String s, String delimiter, float x) { 2405 String[] array = split(s, delimiter); 2406 float[] newArray = new float[array.length]; 2407 2408 for (int i = 0; i < array.length; i++) { 2409 float value = x; 2410 2411 try { 2412 value = Float.parseFloat(array[i]); 2413 } 2414 catch (Exception e) { 2415 } 2416 2417 newArray[i] = value; 2418 } 2419 2420 return newArray; 2421 } 2422 2423 /** 2424 * Splits the string <code>s</code> around the specified delimiter returning 2425 * the integer values of the substrings. 2426 * 2427 * @param s the string to split 2428 * @param delimiter the delimiter 2429 * @param x the default value to use for a substring in case an exception 2430 * occurs in getting the integer value for that substring 2431 * @return the array of integer values resulting from splitting string 2432 * <code>s</code> around the specified delimiter string, or an empty 2433 * array if <code>s</code> is <code>null</code> 2434 */ 2435 public static int[] split(String s, String delimiter, int x) { 2436 String[] array = split(s, delimiter); 2437 int[] newArray = new int[array.length]; 2438 2439 for (int i = 0; i < array.length; i++) { 2440 int value = x; 2441 2442 try { 2443 value = Integer.parseInt(array[i]); 2444 } 2445 catch (Exception e) { 2446 } 2447 2448 newArray[i] = value; 2449 } 2450 2451 return newArray; 2452 } 2453 2454 /** 2455 * Splits the string <code>s</code> around the specified delimiter returning 2456 * the long integer values of the substrings. 2457 * 2458 * @param s the string to split 2459 * @param delimiter the delimiter 2460 * @param x the default value to use for a substring in case an exception 2461 * occurs in getting the long integer value for that substring 2462 * @return the array of long integer values resulting from splitting string 2463 * <code>s</code> around the specified delimiter string, or an empty 2464 * array if <code>s</code> is <code>null</code> 2465 */ 2466 public static long[] split(String s, String delimiter, long x) { 2467 String[] array = split(s, delimiter); 2468 long[] newArray = new long[array.length]; 2469 2470 for (int i = 0; i < array.length; i++) { 2471 long value = x; 2472 2473 try { 2474 value = Long.parseLong(array[i]); 2475 } 2476 catch (Exception e) { 2477 } 2478 2479 newArray[i] = value; 2480 } 2481 2482 return newArray; 2483 } 2484 2485 /** 2486 * Splits the string <code>s</code> around the specified delimiter returning 2487 * the short integer values of the substrings. 2488 * 2489 * @param s the string to split 2490 * @param delimiter the delimiter 2491 * @param x the default value to use for a substring in case an exception 2492 * occurs in getting the short integer value for that substring 2493 * @return the array of short integer values resulting from splitting string 2494 * <code>s</code> around the specified delimiter string, or an empty 2495 * array if <code>s</code> is <code>null</code> 2496 */ 2497 public static short[] split(String s, String delimiter, short x) { 2498 String[] array = split(s, delimiter); 2499 short[] newArray = new short[array.length]; 2500 2501 for (int i = 0; i < array.length; i++) { 2502 short value = x; 2503 2504 try { 2505 value = Short.parseShort(array[i]); 2506 } 2507 catch (Exception e) { 2508 } 2509 2510 newArray[i] = value; 2511 } 2512 2513 return newArray; 2514 } 2515 2516 /** 2517 * Splits string <code>s</code> around return and newline characters. 2518 * 2519 * <p> 2520 * Example: 2521 * </p> 2522 * 2523 * <pre> 2524 * <code> 2525 * splitLines("Red\rBlue\nGreen") returns {"Red","Blue","Green"} 2526 * </code> 2527 * </pre> 2528 * 2529 * @param s the string to split 2530 * @return the array of strings resulting from splitting string 2531 * <code>s</code> around return and newline characters, or an empty 2532 * string array if string <code>s</code> is <code>null</code> 2533 */ 2534 public static String[] splitLines(String s) { 2535 if (Validator.isNull(s)) { 2536 return _emptyStringArray; 2537 } 2538 2539 s = s.trim(); 2540 2541 List<String> lines = new ArrayList<String>(); 2542 2543 int lastIndex = 0; 2544 2545 while (true) { 2546 int returnIndex = s.indexOf(CharPool.RETURN, lastIndex); 2547 int newLineIndex = s.indexOf(CharPool.NEW_LINE, lastIndex); 2548 2549 if ((returnIndex == -1) && (newLineIndex == -1)) { 2550 break; 2551 } 2552 2553 if (returnIndex == -1) { 2554 lines.add(s.substring(lastIndex, newLineIndex)); 2555 2556 lastIndex = newLineIndex + 1; 2557 } 2558 else if (newLineIndex == -1) { 2559 lines.add(s.substring(lastIndex, returnIndex)); 2560 2561 lastIndex = returnIndex + 1; 2562 } 2563 else if (newLineIndex < returnIndex) { 2564 lines.add(s.substring(lastIndex, newLineIndex)); 2565 2566 lastIndex = newLineIndex + 1; 2567 } 2568 else { 2569 lines.add(s.substring(lastIndex, returnIndex)); 2570 2571 lastIndex = returnIndex + 1; 2572 2573 if (lastIndex == newLineIndex) { 2574 lastIndex++; 2575 } 2576 } 2577 } 2578 2579 if (lastIndex < s.length()) { 2580 lines.add(s.substring(lastIndex)); 2581 } 2582 2583 return lines.toArray(new String[lines.size()]); 2584 } 2585 2586 /** 2587 * Returns <code>true</code> if, ignoring case, the string starts with the 2588 * specified character. 2589 * 2590 * @param s the string 2591 * @param begin the character against which the initial character of the 2592 * string is to be compared 2593 * @return <code>true</code> if, ignoring case, the string starts with the 2594 * specified character; <code>false</code> otherwise 2595 */ 2596 public static boolean startsWith(String s, char begin) { 2597 return startsWith(s, (new Character(begin)).toString()); 2598 } 2599 2600 /** 2601 * Returns <code>true</code> if, ignoring case, the string starts with the 2602 * specified start string. 2603 * 2604 * @param s the original string 2605 * @param start the string against which the beginning of string 2606 * <code>s</code> are to be compared 2607 * @return <code>true</code> if, ignoring case, the string starts with the 2608 * specified start string; <code>false</code> otherwise 2609 */ 2610 public static boolean startsWith(String s, String start) { 2611 if ((s == null) || (start == null)) { 2612 return false; 2613 } 2614 2615 if (start.length() > s.length()) { 2616 return false; 2617 } 2618 2619 String temp = s.substring(0, start.length()); 2620 2621 if (temp.equalsIgnoreCase(start)) { 2622 return true; 2623 } 2624 else { 2625 return false; 2626 } 2627 } 2628 2629 /** 2630 * Returns the number of starting characters that <code>s1</code> and 2631 * <code>s2</code> have in common before their characters deviate. 2632 * 2633 * @param s1 string 1 2634 * @param s2 string 2 2635 * @return the number of starting characters that <code>s1</code> and 2636 * <code>s2</code> have in common before their characters deviate 2637 */ 2638 public static int startsWithWeight(String s1, String s2) { 2639 if ((s1 == null) || (s2 == null)) { 2640 return 0; 2641 } 2642 2643 char[] chars1 = s1.toCharArray(); 2644 char[] chars2 = s2.toCharArray(); 2645 2646 int i = 0; 2647 2648 for (; (i < chars1.length) && (i < chars2.length); i++) { 2649 if (chars1[i] != chars2[i]) { 2650 break; 2651 } 2652 } 2653 2654 return i; 2655 } 2656 2657 /** 2658 * Returns a string representing the string <code>s</code> with all 2659 * occurrences of the specified character removed. 2660 * 2661 * <p> 2662 * Example: 2663 * </p> 2664 * 2665 * <pre> 2666 * <code> 2667 * strip("Mississipi", 'i') returns "Mssssp" 2668 * </code> 2669 * </pre> 2670 * 2671 * @param s the string from which to strip all occurrences the character 2672 * @param remove the character to strip from the string 2673 * @return a string representing the string <code>s</code> with all 2674 * occurrences of the specified character removed, or 2675 * <code>null</code> if <code>s</code> is <code>null</code> 2676 */ 2677 public static String strip(String s, char remove) { 2678 if (s == null) { 2679 return null; 2680 } 2681 2682 int x = s.indexOf(remove); 2683 2684 if (x < 0) { 2685 return s; 2686 } 2687 2688 int y = 0; 2689 2690 StringBundler sb = new StringBundler(s.length()); 2691 2692 while (x >= 0) { 2693 sb.append(s.subSequence(y, x)); 2694 2695 y = x + 1; 2696 2697 x = s.indexOf(remove, y); 2698 } 2699 2700 sb.append(s.substring(y)); 2701 2702 return sb.toString(); 2703 } 2704 2705 /** 2706 * Returns a string representing the combination of the substring of 2707 * <code>s</code> up to but not including the string <code>begin</code> 2708 * concatenated with the substring of <code>s</code> after but not including 2709 * the string <code>end</code>. 2710 * 2711 * <p> 2712 * Example: 2713 * <p> 2714 * 2715 * <pre> 2716 * <code> 2717 * stripBetween("One small step for man, one giant leap for mankind", "step", "giant ") returns "One small leap for mankind" 2718 * </code> 2719 * </pre> 2720 * 2721 * @param s the from which to strip a substring 2722 * @param begin the beginning characters of the substring to be removed 2723 * @param end the ending characters of the substring to be removed 2724 * @return a string representing the combination of the substring of 2725 * <code>s</code> up to but not including the string 2726 * <code>begin</code> concatenated with the substring of 2727 * <code>s</code> after but not including the string 2728 * <code>end</code>, or the original string if the value of 2729 * <code>s</code>, <code>begin</code>, or <code>end</code> are 2730 * <code>null</code> 2731 */ 2732 public static String stripBetween(String s, String begin, String end) { 2733 if ((s == null) || (begin == null) || (end == null)) { 2734 return s; 2735 } 2736 2737 StringBundler sb = new StringBundler(s.length()); 2738 2739 int pos = 0; 2740 2741 while (true) { 2742 int x = s.indexOf(begin, pos); 2743 int y = s.indexOf(end, x + begin.length()); 2744 2745 if ((x == -1) || (y == -1)) { 2746 sb.append(s.substring(pos)); 2747 2748 break; 2749 } 2750 else { 2751 sb.append(s.substring(pos, x)); 2752 2753 pos = y + end.length(); 2754 } 2755 } 2756 2757 return sb.toString(); 2758 } 2759 2760 /** 2761 * Returns a string representing the Unicode character codes of the 2762 * characters comprising the string <code>s</code>. 2763 * 2764 * <p> 2765 * Example: 2766 * </p> 2767 * 2768 * <pre> 2769 * <code> 2770 * toCharCode("a") returns "97" 2771 * toCharCode("b") returns "98" 2772 * toCharCode("c") returns "99" 2773 * toCharCode("What's for lunch?") returns "87104971163911532102111114321081171109910463" 2774 * </code> 2775 * </p> 2776 * 2777 * @param s the string whose character codes are to be represented 2778 * @return a string representing the Unicode character codes of the 2779 * characters comprising the string <code>s</code> 2780 */ 2781 public static String toCharCode(String s) { 2782 StringBundler sb = new StringBundler(s.length()); 2783 2784 for (int i = 0; i < s.length(); i++) { 2785 sb.append(s.codePointAt(i)); 2786 } 2787 2788 return sb.toString(); 2789 } 2790 2791 public static String toHexString(int i) { 2792 char[] buffer = new char[8]; 2793 2794 int index = 8; 2795 2796 do { 2797 buffer[--index] = _HEX_DIGITS[i & 15]; 2798 2799 i >>>= 4; 2800 } 2801 while (i != 0); 2802 2803 return new String(buffer, index, 8 - index); 2804 } 2805 2806 public static String toHexString(long l) { 2807 char[] buffer = new char[16]; 2808 2809 int index = 16; 2810 2811 do { 2812 buffer[--index] = _HEX_DIGITS[(int) (l & 15)]; 2813 2814 l >>>= 4; 2815 } 2816 while (l != 0); 2817 2818 return new String(buffer, index, 16 - index); 2819 } 2820 2821 public static String toHexString(Object obj) { 2822 if (obj instanceof Integer) { 2823 return toHexString(((Integer)obj).intValue()); 2824 } 2825 else if (obj instanceof Long) { 2826 return toHexString(((Long)obj).longValue()); 2827 } 2828 else { 2829 return String.valueOf(obj); 2830 } 2831 } 2832 2833 /** 2834 * Trims all leading and trailing whitespace from the string. 2835 * 2836 * @param s the original string 2837 * @return a string representing the original string with all leading and 2838 * trailing whitespace removed 2839 */ 2840 public static String trim(String s) { 2841 return trim(s, null); 2842 } 2843 2844 /** 2845 * Trims leading and trailing whitespace from the string, up to but not 2846 * including the whitespace character specified by <code>c</code>. 2847 * 2848 * <p> 2849 * Examples: 2850 * </p> 2851 * 2852 * <pre> 2853 * <code> 2854 * trim(" \tHey\t ", '\t') returns "\tHey\t" 2855 * trim(" \t Hey \t ", '\t') returns "\t Hey \t" 2856 * </code> 2857 * </pre> 2858 * 2859 * @param s the original string 2860 * @param c the whitespace character to limit trimming 2861 * @return a string representing the original string with leading and 2862 * trailing whitespace removed, up to but not including the 2863 * whitespace character specified by <code>c</code> 2864 */ 2865 public static String trim(String s, char c) { 2866 return trim(s, new char[] {c}); 2867 } 2868 2869 /** 2870 * Trims leading and trailing whitespace from the string, up to but not 2871 * including the whitespace characters specified by <code>exceptions</code>. 2872 * 2873 * @param s the original string 2874 * @param exceptions the whitespace characters to limit trimming 2875 * @return a string representing the original string with leading and 2876 * trailing whitespace removed, up to but not including the 2877 * whitespace characters specified by <code>exceptions</code> 2878 */ 2879 public static String trim(String s, char[] exceptions) { 2880 if (s == null) { 2881 return null; 2882 } 2883 2884 char[] chars = s.toCharArray(); 2885 2886 int len = chars.length; 2887 2888 int x = 0; 2889 int y = chars.length; 2890 2891 for (int i = 0; i < len; i++) { 2892 char c = chars[i]; 2893 2894 if (_isTrimable(c, exceptions)) { 2895 x = i + 1; 2896 } 2897 else { 2898 break; 2899 } 2900 } 2901 2902 for (int i = len - 1; i >= 0; i--) { 2903 char c = chars[i]; 2904 2905 if (_isTrimable(c, exceptions)) { 2906 y = i; 2907 } 2908 else { 2909 break; 2910 } 2911 } 2912 2913 if ((x != 0) || (y != len)) { 2914 return s.substring(x, y); 2915 } 2916 else { 2917 return s; 2918 } 2919 } 2920 2921 /** 2922 * Trims all leading whitespace from the string. 2923 * 2924 * @param s the original string 2925 * @return a string representing the original string with all leading 2926 * whitespace removed 2927 */ 2928 public static String trimLeading(String s) { 2929 return trimLeading(s, null); 2930 } 2931 2932 /** 2933 * Trims leading whitespace from the string, up to but not including the 2934 * whitespace character specified by <code>c</code>. 2935 * 2936 * @param s the original string 2937 * @param c the whitespace character to limit trimming 2938 * @return a string representing the original string with leading whitespace 2939 * removed, up to but not including the whitespace character 2940 * specified by <code>c</code> 2941 */ 2942 public static String trimLeading(String s, char c) { 2943 return trimLeading(s, new char[] {c}); 2944 } 2945 2946 /** 2947 * Trims leading whitespace from the string, up to but not including the 2948 * whitespace characters specified by <code>exceptions</code>. 2949 * 2950 * @param s the original string 2951 * @param exceptions the whitespace characters to limit trimming 2952 * @return a string representing the original string with leading whitespace 2953 * removed, up to but not including the whitespace characters 2954 * specified by <code>exceptions</code> 2955 */ 2956 public static String trimLeading(String s, char[] exceptions) { 2957 if (s == null) { 2958 return null; 2959 } 2960 2961 char[] chars = s.toCharArray(); 2962 2963 int len = chars.length; 2964 2965 int x = 0; 2966 int y = chars.length; 2967 2968 for (int i = 0; i < len; i++) { 2969 char c = chars[i]; 2970 2971 if (_isTrimable(c, exceptions)) { 2972 x = i + 1; 2973 } 2974 else { 2975 break; 2976 } 2977 } 2978 2979 if ((x != 0) || (y != len)) { 2980 return s.substring(x, y); 2981 } 2982 else { 2983 return s; 2984 } 2985 } 2986 2987 /** 2988 * Trims all trailing whitespace from the string. 2989 * 2990 * @param s the original string 2991 * @return a string representing the original string with all trailing 2992 * whitespace removed 2993 */ 2994 public static String trimTrailing(String s) { 2995 return trimTrailing(s, null); 2996 } 2997 2998 /** 2999 * Trims trailing whitespace from the string, up to but not including the 3000 * whitespace character specified by <code>c</code>. 3001 * 3002 * @param s the original string 3003 * @param c the whitespace character to limit trimming 3004 * @return a string representing the original string with trailing 3005 * whitespace removed, up to but not including the whitespace 3006 * character specified by <code>c</code> 3007 */ 3008 public static String trimTrailing(String s, char c) { 3009 return trimTrailing(s, new char[] {c}); 3010 } 3011 3012 /** 3013 * Trims trailing whitespace from the string, up to but not including the 3014 * whitespace characters specified by <code>exceptions</code>. 3015 * 3016 * @param s the original string 3017 * @param exceptions the whitespace characters to limit trimming 3018 * @return a string representing the original string with trailing 3019 * whitespace removed, up to but not including the whitespace 3020 * characters specified by <code>exceptions</code> 3021 */ 3022 public static String trimTrailing(String s, char[] exceptions) { 3023 if (s == null) { 3024 return null; 3025 } 3026 3027 char[] chars = s.toCharArray(); 3028 3029 int len = chars.length; 3030 3031 int x = 0; 3032 int y = chars.length; 3033 3034 for (int i = len - 1; i >= 0; i--) { 3035 char c = chars[i]; 3036 3037 if (_isTrimable(c, exceptions)) { 3038 y = i; 3039 } 3040 else { 3041 break; 3042 } 3043 } 3044 3045 if ((x != 0) || (y != len)) { 3046 return s.substring(x, y); 3047 } 3048 else { 3049 return s; 3050 } 3051 } 3052 3053 /** 3054 * Removes leading and trailing double and single quotation marks from the 3055 * string. 3056 * 3057 * @param s the original string 3058 * @return a string representing the original string with leading and 3059 * trailing double and single quotation marks removed, or the 3060 * original string if the original string is a <code>null</code> or 3061 * empty 3062 */ 3063 public static String unquote(String s) { 3064 if (Validator.isNull(s)) { 3065 return s; 3066 } 3067 3068 if ((s.charAt(0) == CharPool.APOSTROPHE) && 3069 (s.charAt(s.length() - 1) == CharPool.APOSTROPHE)) { 3070 3071 return s.substring(1, s.length() - 1); 3072 } 3073 else if ((s.charAt(0) == CharPool.QUOTE) && 3074 (s.charAt(s.length() - 1) == CharPool.QUOTE)) { 3075 3076 return s.substring(1, s.length() - 1); 3077 } 3078 3079 return s; 3080 } 3081 3082 /** 3083 * Converts all of the characters in the string to upper case. 3084 * 3085 * @param s the string to convert 3086 * @return the string, converted to upper-case, or <code>null</code> if the 3087 * string is <code>null</code> 3088 * @see {@link String#toUpperCase()} 3089 */ 3090 public static String upperCase(String s) { 3091 if (s == null) { 3092 return null; 3093 } 3094 else { 3095 return s.toUpperCase(); 3096 } 3097 } 3098 3099 /** 3100 * Converts the first character of the string to upper case. 3101 * 3102 * @param s the string whose first character is to be converted 3103 * @return the string, with its first character converted to upper-case 3104 */ 3105 public static String upperCaseFirstLetter(String s) { 3106 char[] chars = s.toCharArray(); 3107 3108 if ((chars[0] >= 97) && (chars[0] <= 122)) { 3109 chars[0] = (char)(chars[0] - 32); 3110 } 3111 3112 return new String(chars); 3113 } 3114 3115 /** 3116 * Returns the string value of the object. 3117 * 3118 * @param obj the object whose string value is to be returned 3119 * @return the string value of the object 3120 * @see {@link String#valueOf(Object obj)} 3121 */ 3122 public static String valueOf(Object obj) { 3123 return String.valueOf(obj); 3124 } 3125 3126 public static String wrap(String text) { 3127 return wrap(text, 80, StringPool.NEW_LINE); 3128 } 3129 3130 public static String wrap(String text, int width, String lineSeparator) { 3131 try { 3132 return _wrap(text, width, lineSeparator); 3133 } 3134 catch (IOException ioe) { 3135 _log.error(ioe.getMessage()); 3136 3137 return text; 3138 } 3139 } 3140 3141 private static String _highlight( 3142 String s, Pattern pattern, String highlight1, String highlight2) { 3143 3144 StringTokenizer st = new StringTokenizer(s); 3145 3146 if (st.countTokens() == 0) { 3147 return StringPool.BLANK; 3148 } 3149 3150 StringBundler sb = new StringBundler(2 * st.countTokens() - 1); 3151 3152 while (st.hasMoreTokens()) { 3153 String token = st.nextToken(); 3154 3155 Matcher matcher = pattern.matcher(token); 3156 3157 if (matcher.find()) { 3158 StringBuffer hightlighted = new StringBuffer(); 3159 3160 do { 3161 matcher.appendReplacement( 3162 hightlighted, highlight1 + matcher.group() + 3163 highlight2); 3164 } 3165 while (matcher.find()); 3166 3167 matcher.appendTail(hightlighted); 3168 3169 sb.append(hightlighted); 3170 } 3171 else { 3172 sb.append(token); 3173 } 3174 3175 if (st.hasMoreTokens()) { 3176 sb.append(StringPool.SPACE); 3177 } 3178 } 3179 3180 return sb.toString(); 3181 } 3182 3183 /** 3184 * Returns <code>false</code> if the character is not whitespace or is equal 3185 * to any of the exception characters. 3186 * 3187 * @param c the character whose trim-ability is to be determined 3188 * @param exceptions the whitespace characters to exclude from trimming 3189 * @return <code>false</code> if the character is not whitespace or is equal 3190 * to any of the exception characters; <code>true</code> otherwise 3191 */ 3192 private static boolean _isTrimable(char c, char[] exceptions) { 3193 if ((exceptions != null) && (exceptions.length > 0)) { 3194 for (char exception : exceptions) { 3195 if (c == exception) { 3196 return false; 3197 } 3198 } 3199 } 3200 3201 return Character.isWhitespace(c); 3202 } 3203 3204 private static String _wrap(String text, int width, String lineSeparator) 3205 throws IOException { 3206 3207 if (text == null) { 3208 return null; 3209 } 3210 3211 StringBundler sb = new StringBundler(); 3212 3213 UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader( 3214 new UnsyncStringReader(text)); 3215 3216 String s = StringPool.BLANK; 3217 3218 while ((s = unsyncBufferedReader.readLine()) != null) { 3219 if (s.length() == 0) { 3220 sb.append(lineSeparator); 3221 3222 continue; 3223 } 3224 3225 int lineLength = 0; 3226 3227 String[] tokens = s.split(StringPool.SPACE); 3228 3229 for (String token : tokens) { 3230 if ((lineLength + token.length() + 1) > width) { 3231 if (lineLength > 0) { 3232 sb.append(lineSeparator); 3233 } 3234 3235 if (token.length() > width) { 3236 int pos = token.indexOf(CharPool.OPEN_PARENTHESIS); 3237 3238 if (pos != -1) { 3239 sb.append(token.substring(0, pos + 1)); 3240 sb.append(lineSeparator); 3241 3242 token = token.substring(pos + 1); 3243 3244 sb.append(token); 3245 3246 lineLength = token.length(); 3247 } 3248 else { 3249 sb.append(token); 3250 3251 lineLength = token.length(); 3252 } 3253 } 3254 else { 3255 sb.append(token); 3256 3257 lineLength = token.length(); 3258 } 3259 } 3260 else { 3261 if (lineLength > 0) { 3262 sb.append(StringPool.SPACE); 3263 3264 lineLength++; 3265 } 3266 3267 sb.append(token); 3268 3269 lineLength += token.length(); 3270 } 3271 } 3272 3273 sb.append(lineSeparator); 3274 } 3275 3276 return sb.toString(); 3277 } 3278 3279 private static final char[] _HEX_DIGITS = { 3280 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 3281 'e', 'f' 3282 }; 3283 3284 private static Log _log = LogFactoryUtil.getLog(StringUtil.class); 3285 3286 private static String[] _emptyStringArray = new String[0]; 3287 3288 }