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