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