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