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