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