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