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