| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.nifi.util; |
| |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.stream.Collectors; |
| |
| /** |
| * String Utils based on the Apache Commons Lang String Utils. |
| * These simple util methods here allow us to avoid a dependency in the core |
| */ |
| public class StringUtils { |
| |
| public static final String EMPTY = ""; |
| |
| public static boolean isBlank(final String str) { |
| if (str == null || str.isEmpty()) { |
| return true; |
| } |
| for (int i = 0; i < str.length(); i++) { |
| if (!Character.isWhitespace(str.charAt(i))) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| public static boolean isNotBlank(final String str) { |
| return !isBlank(str); |
| } |
| |
| public static boolean isEmpty(final String str) { |
| return str == null || str.isEmpty(); |
| } |
| |
| public static boolean isNotEmpty(final String str) { |
| return !isEmpty(str); |
| } |
| |
| public static boolean startsWith(final String str, final String prefix) { |
| if (str == null || prefix == null) { |
| return (str == null && prefix == null); |
| } |
| if (prefix.length() > str.length()) { |
| return false; |
| } |
| return str.regionMatches(false, 0, prefix, 0, prefix.length()); |
| } |
| |
| public static String substringAfter(final String str, final String separator) { |
| if (isEmpty(str)) { |
| return str; |
| } |
| if (separator == null) { |
| return EMPTY; |
| } |
| int pos = str.indexOf(separator); |
| if (pos == -1) { |
| return EMPTY; |
| } |
| return str.substring(pos + separator.length()); |
| } |
| |
| public static String join(final Collection<?> collection, String delimiter) { |
| if (collection == null || collection.isEmpty()) { |
| return EMPTY; |
| } |
| |
| if (collection.size() == 1) { |
| return String.valueOf(collection.iterator().next()); |
| } |
| |
| final StringBuilder sb = new StringBuilder(); |
| for (final Object element : collection) { |
| sb.append(element); |
| sb.append(delimiter); |
| } |
| |
| return sb.toString().substring(0, sb.lastIndexOf(delimiter)); |
| } |
| |
| /** |
| * <p>The maximum size to which the padding constant(s) can expand.</p> |
| */ |
| private static final int PAD_LIMIT = 8192; |
| |
| /** |
| * A String for a space character. |
| * |
| * @since 3.2 |
| */ |
| public static final String SPACE = " "; |
| |
| /** |
| * <p>Left pad a String with spaces (' ').</p> |
| * |
| * <p>The String is padded to the size of {@code size}.</p> |
| * |
| * <pre> |
| * StringUtils.leftPad(null, *) = null |
| * StringUtils.leftPad("", 3) = " " |
| * StringUtils.leftPad("bat", 3) = "bat" |
| * StringUtils.leftPad("bat", 5) = " bat" |
| * StringUtils.leftPad("bat", 1) = "bat" |
| * StringUtils.leftPad("bat", -1) = "bat" |
| * </pre> |
| * |
| * @param str the String to pad out, may be null |
| * @param size the size to pad to |
| * @return left padded String or original String if no padding is necessary, |
| * {@code null} if null String input |
| */ |
| public static String leftPad(final String str, final int size) { |
| return leftPad(str, size, ' '); |
| } |
| |
| /** |
| * <p>Left pad a String with a specified character.</p> |
| * |
| * <p>Pad to a size of {@code size}.</p> |
| * |
| * <pre> |
| * StringUtils.leftPad(null, *, *) = null |
| * StringUtils.leftPad("", 3, 'z') = "zzz" |
| * StringUtils.leftPad("bat", 3, 'z') = "bat" |
| * StringUtils.leftPad("bat", 5, 'z') = "zzbat" |
| * StringUtils.leftPad("bat", 1, 'z') = "bat" |
| * StringUtils.leftPad("bat", -1, 'z') = "bat" |
| * </pre> |
| * |
| * @param str the String to pad out, may be null |
| * @param size the size to pad to |
| * @param padChar the character to pad with |
| * @return left padded String or original String if no padding is necessary, |
| * {@code null} if null String input |
| * @since 2.0 |
| */ |
| public static String leftPad(final String str, final int size, final char padChar) { |
| if (str == null) { |
| return null; |
| } |
| final int pads = size - str.length(); |
| if (pads <= 0) { |
| return str; // returns original String when possible |
| } |
| if (pads > PAD_LIMIT) { |
| return leftPad(str, size, String.valueOf(padChar)); |
| } |
| return repeat(padChar, pads).concat(str); |
| } |
| |
| /** |
| * <p>Left pad a String with a specified String.</p> |
| * |
| * <p>Pad to a size of {@code size}.</p> |
| * |
| * <pre> |
| * StringUtils.leftPad(null, *, *) = null |
| * StringUtils.leftPad("", 3, "z") = "zzz" |
| * StringUtils.leftPad("bat", 3, "yz") = "bat" |
| * StringUtils.leftPad("bat", 5, "yz") = "yzbat" |
| * StringUtils.leftPad("bat", 8, "yz") = "yzyzybat" |
| * StringUtils.leftPad("bat", 1, "yz") = "bat" |
| * StringUtils.leftPad("bat", -1, "yz") = "bat" |
| * StringUtils.leftPad("bat", 5, null) = " bat" |
| * StringUtils.leftPad("bat", 5, "") = " bat" |
| * </pre> |
| * |
| * @param str the String to pad out, may be null |
| * @param size the size to pad to |
| * @param padStr the String to pad with, null or empty treated as single space |
| * @return left padded String or original String if no padding is necessary, |
| * {@code null} if null String input |
| */ |
| public static String leftPad(final String str, final int size, String padStr) { |
| if (str == null) { |
| return null; |
| } |
| if (isEmpty(padStr)) { |
| padStr = SPACE; |
| } |
| final int padLen = padStr.length(); |
| final int strLen = str.length(); |
| final int pads = size - strLen; |
| if (pads <= 0) { |
| return str; // returns original String when possible |
| } |
| if (padLen == 1 && pads <= PAD_LIMIT) { |
| return leftPad(str, size, padStr.charAt(0)); |
| } |
| |
| if (pads == padLen) { |
| return padStr.concat(str); |
| } else if (pads < padLen) { |
| return padStr.substring(0, pads).concat(str); |
| } else { |
| final char[] padding = new char[pads]; |
| final char[] padChars = padStr.toCharArray(); |
| for (int i = 0; i < pads; i++) { |
| padding[i] = padChars[i % padLen]; |
| } |
| return new String(padding).concat(str); |
| } |
| } |
| |
| /** |
| * <p>Right pad a String with spaces (' ').</p> |
| * |
| * <p>The String is padded to the size of {@code size}.</p> |
| * |
| * <pre> |
| * StringUtils.rightPad(null, *) = null |
| * StringUtils.rightPad("", 3) = " " |
| * StringUtils.rightPad("bat", 3) = "bat" |
| * StringUtils.rightPad("bat", 5) = "bat " |
| * StringUtils.rightPad("bat", 1) = "bat" |
| * StringUtils.rightPad("bat", -1) = "bat" |
| * </pre> |
| * |
| * @param str the String to pad out, may be null |
| * @param size the size to pad to |
| * @return right padded String or original String if no padding is necessary, |
| * {@code null} if null String input |
| */ |
| public static String rightPad(final String str, final int size) { |
| return rightPad(str, size, ' '); |
| } |
| |
| /** |
| * <p>Right pad a String with a specified character.</p> |
| * |
| * <p>The String is padded to the size of {@code size}.</p> |
| * |
| * <pre> |
| * StringUtils.rightPad(null, *, *) = null |
| * StringUtils.rightPad("", 3, 'z') = "zzz" |
| * StringUtils.rightPad("bat", 3, 'z') = "bat" |
| * StringUtils.rightPad("bat", 5, 'z') = "batzz" |
| * StringUtils.rightPad("bat", 1, 'z') = "bat" |
| * StringUtils.rightPad("bat", -1, 'z') = "bat" |
| * </pre> |
| * |
| * @param str the String to pad out, may be null |
| * @param size the size to pad to |
| * @param padChar the character to pad with |
| * @return right padded String or original String if no padding is necessary, |
| * {@code null} if null String input |
| * @since 2.0 |
| */ |
| public static String rightPad(final String str, final int size, final char padChar) { |
| if (str == null) { |
| return null; |
| } |
| final int pads = size - str.length(); |
| if (pads <= 0) { |
| return str; // returns original String when possible |
| } |
| if (pads > PAD_LIMIT) { |
| return rightPad(str, size, String.valueOf(padChar)); |
| } |
| return str.concat(repeat(padChar, pads)); |
| } |
| |
| /** |
| * <p>Right pad a String with a specified String.</p> |
| * |
| * <p>The String is padded to the size of {@code size}.</p> |
| * |
| * <pre> |
| * StringUtils.rightPad(null, *, *) = null |
| * StringUtils.rightPad("", 3, "z") = "zzz" |
| * StringUtils.rightPad("bat", 3, "yz") = "bat" |
| * StringUtils.rightPad("bat", 5, "yz") = "batyz" |
| * StringUtils.rightPad("bat", 8, "yz") = "batyzyzy" |
| * StringUtils.rightPad("bat", 1, "yz") = "bat" |
| * StringUtils.rightPad("bat", -1, "yz") = "bat" |
| * StringUtils.rightPad("bat", 5, null) = "bat " |
| * StringUtils.rightPad("bat", 5, "") = "bat " |
| * </pre> |
| * |
| * @param str the String to pad out, may be null |
| * @param size the size to pad to |
| * @param padStr the String to pad with, null or empty treated as single space |
| * @return right padded String or original String if no padding is necessary, |
| * {@code null} if null String input |
| */ |
| public static String rightPad(final String str, final int size, String padStr) { |
| if (str == null) { |
| return null; |
| } |
| if (isEmpty(padStr)) { |
| padStr = SPACE; |
| } |
| final int padLen = padStr.length(); |
| final int strLen = str.length(); |
| final int pads = size - strLen; |
| if (pads <= 0) { |
| return str; // returns original String when possible |
| } |
| if (padLen == 1 && pads <= PAD_LIMIT) { |
| return rightPad(str, size, padStr.charAt(0)); |
| } |
| |
| if (pads == padLen) { |
| return str.concat(padStr); |
| } else if (pads < padLen) { |
| return str.concat(padStr.substring(0, pads)); |
| } else { |
| final char[] padding = new char[pads]; |
| final char[] padChars = padStr.toCharArray(); |
| for (int i = 0; i < pads; i++) { |
| padding[i] = padChars[i % padLen]; |
| } |
| return str.concat(new String(padding)); |
| } |
| } |
| |
| /** |
| * <p>Returns padding using the specified delimiter repeated |
| * to a given length.</p> |
| * |
| * <pre> |
| * StringUtils.repeat('e', 0) = "" |
| * StringUtils.repeat('e', 3) = "eee" |
| * StringUtils.repeat('e', -2) = "" |
| * </pre> |
| * |
| * <p>Note: this method does not support padding with |
| * <a href="http://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a> |
| * as they require a pair of {@code char}s to be represented. |
| * If you are needing to support full I18N of your applications |
| * consider using {@link #repeat(String, int)} instead. |
| * </p> |
| * |
| * @param ch character to repeat |
| * @param repeat number of times to repeat char, negative treated as zero |
| * @return String with repeated character |
| * @see #repeat(String, int) |
| */ |
| public static String repeat(final char ch, final int repeat) { |
| if (repeat <= 0) { |
| return EMPTY; |
| } |
| final char[] buf = new char[repeat]; |
| for (int i = repeat - 1; i >= 0; i--) { |
| buf[i] = ch; |
| } |
| return new String(buf); |
| } |
| |
| // Padding |
| //----------------------------------------------------------------------- |
| /** |
| * <p>Repeat a String {@code repeat} times to form a |
| * new String.</p> |
| * |
| * <pre> |
| * StringUtils.repeat(null, 2) = null |
| * StringUtils.repeat("", 0) = "" |
| * StringUtils.repeat("", 2) = "" |
| * StringUtils.repeat("a", 3) = "aaa" |
| * StringUtils.repeat("ab", 2) = "abab" |
| * StringUtils.repeat("a", -2) = "" |
| * </pre> |
| * |
| * @param str the String to repeat, may be null |
| * @param repeat number of times to repeat str, negative treated as zero |
| * @return a new String consisting of the original String repeated, |
| * {@code null} if null String input |
| */ |
| public static String repeat(final String str, final int repeat) { |
| // Performance tuned for 2.0 (JDK1.4) |
| |
| if (str == null) { |
| return null; |
| } |
| if (repeat <= 0) { |
| return EMPTY; |
| } |
| final int inputLength = str.length(); |
| if (repeat == 1 || inputLength == 0) { |
| return str; |
| } |
| if (inputLength == 1 && repeat <= PAD_LIMIT) { |
| return repeat(str.charAt(0), repeat); |
| } |
| |
| final int outputLength = inputLength * repeat; |
| switch (inputLength) { |
| case 1 : |
| return repeat(str.charAt(0), repeat); |
| case 2 : |
| final char ch0 = str.charAt(0); |
| final char ch1 = str.charAt(1); |
| final char[] output2 = new char[outputLength]; |
| for (int i = repeat * 2 - 2; i >= 0; i--, i--) { |
| output2[i] = ch0; |
| output2[i + 1] = ch1; |
| } |
| return new String(output2); |
| default : |
| final StringBuilder buf = new StringBuilder(outputLength); |
| for (int i = 0; i < repeat; i++) { |
| buf.append(str); |
| } |
| return buf.toString(); |
| } |
| } |
| |
| /** |
| * <p>Repeat a String {@code repeat} times to form a |
| * new String, with a String separator injected each time. </p> |
| * |
| * <pre> |
| * StringUtils.repeat(null, null, 2) = null |
| * StringUtils.repeat(null, "x", 2) = null |
| * StringUtils.repeat("", null, 0) = "" |
| * StringUtils.repeat("", "", 2) = "" |
| * StringUtils.repeat("", "x", 3) = "xxx" |
| * StringUtils.repeat("?", ", ", 3) = "?, ?, ?" |
| * </pre> |
| * |
| * @param str the String to repeat, may be null |
| * @param separator the String to inject, may be null |
| * @param repeat number of times to repeat str, negative treated as zero |
| * @return a new String consisting of the original String repeated, |
| * {@code null} if null String input |
| * @since 2.5 |
| */ |
| public static String repeat(final String str, final String separator, final int repeat) { |
| if (str == null || separator == null) { |
| return repeat(str, repeat); |
| } |
| // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it |
| final String result = repeat(str + separator, repeat); |
| return removeEnd(result, separator); |
| } |
| |
| /** |
| * <p>Removes a substring only if it is at the end of a source string, |
| * otherwise returns the source string.</p> |
| * |
| * <p>A {@code null} source string will return {@code null}. |
| * An empty ("") source string will return the empty string. |
| * A {@code null} search string will return the source string.</p> |
| * |
| * <pre> |
| * StringUtils.removeEnd(null, *) = null |
| * StringUtils.removeEnd("", *) = "" |
| * StringUtils.removeEnd(*, null) = * |
| * StringUtils.removeEnd("www.domain.com", ".com.") = "www.domain.com" |
| * StringUtils.removeEnd("www.domain.com", ".com") = "www.domain" |
| * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com" |
| * StringUtils.removeEnd("abc", "") = "abc" |
| * </pre> |
| * |
| * @param str the source String to search, may be null |
| * @param remove the String to search for and remove, may be null |
| * @return the substring with the string removed if found, |
| * {@code null} if null String input |
| * @since 2.1 |
| */ |
| public static String removeEnd(final String str, final String remove) { |
| if (isEmpty(str) || isEmpty(remove)) { |
| return str; |
| } |
| if (str.endsWith(remove)) { |
| return str.substring(0, str.length() - remove.length()); |
| } |
| return str; |
| } |
| |
| /** |
| * Returns the string in "title case" (i.e. every word capitalized). If the input is {@code null} or blank, returns |
| * an empty string. Leading and trailing spaces are trimmed, and multiple internal spaces are condensed. |
| * |
| * Examples: |
| * |
| * this is a sentence -> This Is A Sentence |
| * allOneWord -> Alloneword |
| * PREVIOUSLY UPPERCASE -> Previously Uppercase |
| * multiple spaces -> Multiple Spaces |
| * |
| * @param input the input string |
| * @return the titlecased string |
| */ |
| public static String toTitleCase(String input) { |
| if (input == null || isBlank(input)) { |
| return ""; |
| } |
| List<String> elements = Arrays.asList(input.trim().toLowerCase().split("\\s")); |
| return elements.stream() |
| .filter(word -> !StringUtils.isBlank(word)) |
| .map(word -> Character.toTitleCase(word.charAt(0)) + word.substring(1)) |
| .collect(Collectors.joining(" ")); |
| } |
| } |