|
31 | 31 | import org.apache.calcite.sql.util.SqlBasicVisitor; |
32 | 32 |
|
33 | 33 | import com.google.common.base.Preconditions; |
| 34 | +import com.google.common.base.Strings; |
34 | 35 | import com.google.common.base.Throwables; |
35 | 36 | import com.google.common.cache.CacheBuilder; |
36 | 37 | import com.google.common.cache.CacheLoader; |
@@ -642,6 +643,106 @@ public static String replace( |
642 | 643 | return sb.toString(); |
643 | 644 | } |
644 | 645 |
|
| 646 | + /** Right-pads a string with {@code padChar} until it reaches {@code size}. |
| 647 | + * |
| 648 | + * <p>Equivalent to {@code org.apache.commons.lang3.StringUtils#rightPad(String, int, char)} |
| 649 | + * for non-null inputs. |
| 650 | + */ |
| 651 | + public static String rightPad(String s, int size, char padChar) { |
| 652 | + return Strings.padEnd(s, size, padChar); |
| 653 | + } |
| 654 | + |
| 655 | + /** Joins {@code parts} using {@code sep}. |
| 656 | + * |
| 657 | + * <p>Null elements are treated as empty strings. |
| 658 | + */ |
| 659 | + public static String joinNullable(Iterable<? extends @Nullable Object> parts, String sep) { |
| 660 | + final List<String> strings = new ArrayList<>(); |
| 661 | + for (Object o : parts) { |
| 662 | + strings.add(o == null ? "" : o.toString()); |
| 663 | + } |
| 664 | + return String.join(sep, strings); |
| 665 | + } |
| 666 | + |
| 667 | + /** Returns whether the current runtime is Windows. |
| 668 | + * |
| 669 | + * <p>Derived from system property {@code os.name}, using case-insensitive |
| 670 | + * prefix match against {@code "Windows"}. |
| 671 | + * |
| 672 | + * <p>This method is intended to replace commons-lang3's |
| 673 | + * {@code SystemUtils#IS_OS_WINDOWS}. |
| 674 | + */ |
| 675 | + public static boolean isWindows() { |
| 676 | + final String osName = System.getProperty("os.name"); |
| 677 | + return osName != null |
| 678 | + && osName.regionMatches(true, 0, "Windows", 0, "Windows".length()); |
| 679 | + } |
| 680 | + |
| 681 | + /** Replaces characters in {@code s} according to {@code search}/{@code replacement} mapping. |
| 682 | + * |
| 683 | + * <p>Semantics are aligned with {@code org.apache.commons.lang3.StringUtils#replaceChars}: |
| 684 | + * characters found in {@code search} are replaced by the character in the same position in |
| 685 | + * {@code replacement}; if {@code replacement} is shorter, remaining matches are removed. |
| 686 | + */ |
| 687 | + public static @PolyNull String replaceChars(@PolyNull String s, @Nullable String search, |
| 688 | + @Nullable String replacement) { |
| 689 | + if (s == null || s.isEmpty() || search == null || search.isEmpty()) { |
| 690 | + return s; |
| 691 | + } |
| 692 | + final String repl = replacement == null ? "" : replacement; |
| 693 | + boolean modified = false; |
| 694 | + final StringBuilder b = new StringBuilder(s.length()); |
| 695 | + for (int i = 0; i < s.length(); i++) { |
| 696 | + final char ch = s.charAt(i); |
| 697 | + final int j = search.indexOf(ch); |
| 698 | + if (j >= 0) { |
| 699 | + modified = true; |
| 700 | + if (j < repl.length()) { |
| 701 | + b.append(repl.charAt(j)); |
| 702 | + } |
| 703 | + // else: delete character |
| 704 | + } else { |
| 705 | + b.append(ch); |
| 706 | + } |
| 707 | + } |
| 708 | + return modified ? b.toString() : s; |
| 709 | + } |
| 710 | + |
| 711 | + /** Case-insensitive replace of all occurrences of {@code search} in {@code s}. |
| 712 | + * |
| 713 | + * <p>Equivalent to commons-lang's {@code StringUtils.replaceIgnoreCase}, but only supports |
| 714 | + * non-null inputs. |
| 715 | + */ |
| 716 | + public static String replaceIgnoreCase(String s, String search, String replacement) { |
| 717 | + if (search.isEmpty()) { |
| 718 | + return s; |
| 719 | + } |
| 720 | + final int replLength = search.length(); |
| 721 | + int start = 0; |
| 722 | + int end = indexOfIgnoreCase(s, search, start); |
| 723 | + if (end < 0) { |
| 724 | + return s; |
| 725 | + } |
| 726 | + final StringBuilder out = new StringBuilder(s.length()); |
| 727 | + while (end >= 0) { |
| 728 | + out.append(s, start, end).append(replacement); |
| 729 | + start = end + replLength; |
| 730 | + end = indexOfIgnoreCase(s, search, start); |
| 731 | + } |
| 732 | + out.append(s, start, s.length()); |
| 733 | + return out.toString(); |
| 734 | + } |
| 735 | + |
| 736 | + private static int indexOfIgnoreCase(String str, String search, int fromIndex) { |
| 737 | + final int max = str.length() - search.length(); |
| 738 | + for (int i = Math.max(0, fromIndex); i <= max; i++) { |
| 739 | + if (str.regionMatches(true, i, search, 0, search.length())) { |
| 740 | + return i; |
| 741 | + } |
| 742 | + } |
| 743 | + return -1; |
| 744 | + } |
| 745 | + |
645 | 746 | /** |
646 | 747 | * Creates a file-protocol URL for the given file. |
647 | 748 | */ |
|
0 commit comments