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