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