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