mirror of
https://github.com/shekhargulati/strman-java.git
synced 2026-09-24 10:54:05 +00:00
1106 lines
39 KiB
Java
1106 lines
39 KiB
Java
|
|
/*
|
|
*
|
|
* * The MIT License
|
|
* *
|
|
* * Copyright 2016 Shekhar Gulati <shekhargulati84@gmail.com>.
|
|
* *
|
|
* * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* * of this software and associated documentation files (the "Software"), to deal
|
|
* * in the Software without restriction, including without limitation the rights
|
|
* * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* * copies of the Software, and to permit persons to whom the Software is
|
|
* * furnished to do so, subject to the following conditions:
|
|
* *
|
|
* * The above copyright notice and this permission notice shall be included in
|
|
* * all copies or substantial portions of the Software.
|
|
* *
|
|
* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* * THE SOFTWARE.
|
|
*
|
|
*/
|
|
|
|
package strman;
|
|
|
|
import java.util.*;
|
|
import java.util.function.BiFunction;
|
|
import java.util.function.Predicate;
|
|
import java.util.function.Supplier;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
import java.util.stream.Stream;
|
|
|
|
import static java.util.stream.Collectors.joining;
|
|
|
|
/**
|
|
* A String manipulation library without any dependencies
|
|
*/
|
|
public abstract class Strman {
|
|
|
|
private static final Predicate<String> NULL_STRING_PREDICATE = str -> str == null;
|
|
private static final Supplier<String> NULL_STRING_MSG_SUPPLIER = () -> "'value' should be not null.";
|
|
|
|
private Strman() {
|
|
}
|
|
|
|
/**
|
|
* Appends Strings to value
|
|
*
|
|
* @param value initial String
|
|
* @param appends an array of strings to append
|
|
* @return full String
|
|
*/
|
|
public static String append(final String value, final String... appends) {
|
|
return appendArray(value, appends);
|
|
}
|
|
|
|
/**
|
|
* Append an array of String to value
|
|
*
|
|
* @param value initial String
|
|
* @param appends an array of strings to append
|
|
* @return full String
|
|
*/
|
|
public static String appendArray(final String value, final String[] appends) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
if (appends == null || appends.length == 0) {
|
|
return value;
|
|
}
|
|
StringJoiner joiner = new StringJoiner("");
|
|
for (String append : appends) {
|
|
joiner.add(append);
|
|
}
|
|
return value + joiner.toString();
|
|
}
|
|
|
|
/**
|
|
* Get the character at index. This method will take care of negative indexes.
|
|
* The valid value of index is between -(length-1) to (length-1).
|
|
* For values which don't fall under this range Optional.empty will be returned.
|
|
*
|
|
* @param value input value
|
|
* @param index location
|
|
* @return an Optional String if found else empty
|
|
*/
|
|
public static Optional<String> at(final String value, int index) {
|
|
if (value == null || value.isEmpty()) {
|
|
return Optional.empty();
|
|
}
|
|
int length = value.length();
|
|
if (index < 0) {
|
|
index = length + index;
|
|
}
|
|
return (index < length && index >= 0) ? Optional.of(String.valueOf(value.charAt(index))) : Optional.empty();
|
|
}
|
|
|
|
/**
|
|
* Returns an array with strings between start and end.
|
|
*
|
|
* @param value input
|
|
* @param start start
|
|
* @param end end
|
|
* @return Array containing different parts between start and end.
|
|
*/
|
|
|
|
public static String[] between(final String value, final String start, final String end) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
validate(start, NULL_STRING_PREDICATE, () -> "'start' should be not null.");
|
|
validate(end, NULL_STRING_PREDICATE, () -> "'end' should be not null.");
|
|
|
|
String[] parts = value.split(end);
|
|
return Arrays.stream(parts).map(subPart -> subPart.substring(subPart.indexOf(start) + start.length())).toArray(String[]::new);
|
|
}
|
|
|
|
/**
|
|
* Returns a String array consisting of the characters in the String.
|
|
*
|
|
* @param value input
|
|
* @return character array
|
|
*/
|
|
public static String[] chars(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return value.split("");
|
|
}
|
|
|
|
|
|
/**
|
|
* Replace consecutive whitespace characters with a single space.
|
|
*
|
|
* @param value input String
|
|
* @return collapsed String
|
|
*/
|
|
public static String collapseWhitespace(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return value.trim().replaceAll("\\s\\s+", " ");
|
|
}
|
|
|
|
|
|
/**
|
|
* Verifies that the needle is contained in the value. The search is case insensitive
|
|
*
|
|
* @param value to search
|
|
* @param needle to find
|
|
* @return true if found else false.
|
|
*/
|
|
public static boolean contains(final String value, final String needle) {
|
|
return contains(value, needle, false);
|
|
}
|
|
|
|
/**
|
|
* Verifies that the needle is contained in the value.
|
|
*
|
|
* @param value to search
|
|
* @param needle to find
|
|
* @param caseSensitive true or false
|
|
* @return true if found else false.
|
|
*/
|
|
public static boolean contains(final String value, final String needle, final boolean caseSensitive) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
if (caseSensitive) {
|
|
return value.contains(needle);
|
|
}
|
|
return value.toLowerCase().contains(needle.toLowerCase());
|
|
}
|
|
|
|
/**
|
|
* Verifies that all needles are contained in value. The search is case insensitive
|
|
*
|
|
* @param value input String to search
|
|
* @param needles needles to find
|
|
* @return true if all needles are found else false.
|
|
*/
|
|
public static boolean containsAll(final String value, final String[] needles) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return Arrays.stream(needles).allMatch(needle -> contains(value, needle, true));
|
|
}
|
|
|
|
/**
|
|
* Verifies that all needles are contained in value
|
|
*
|
|
* @param value input String to search
|
|
* @param needles needles to find
|
|
* @param caseSensitive true or false
|
|
* @return true if all needles are found else false.
|
|
*/
|
|
public static boolean containsAll(final String value, final String[] needles, final boolean caseSensitive) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return Arrays.stream(needles).allMatch(needle -> contains(value, needle, caseSensitive));
|
|
}
|
|
|
|
/**
|
|
* Verifies that one or more of needles are contained in value. This is case insensitive
|
|
*
|
|
* @param value input
|
|
* @param needles needles to search
|
|
* @return boolean true if any needle is found else false
|
|
*/
|
|
public static boolean containsAny(final String value, final String[] needles) {
|
|
return containsAny(value, needles, false);
|
|
}
|
|
|
|
/**
|
|
* Verifies that one or more of needles are contained in value.
|
|
*
|
|
* @param value input
|
|
* @param needles needles to search
|
|
* @param caseSensitive true or false
|
|
* @return boolean true if any needle is found else false
|
|
*/
|
|
public static boolean containsAny(final String value, final String[] needles, final boolean caseSensitive) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return Arrays.stream(needles).anyMatch(needle -> contains(value, needle, caseSensitive));
|
|
}
|
|
|
|
/**
|
|
* Count the number of times substr appears in value
|
|
*
|
|
* @param value input
|
|
* @param subStr to search
|
|
* @return count of times substring exists
|
|
*/
|
|
public static long countSubstr(final String value, final String subStr) {
|
|
return countSubstr(value, subStr, true, false);
|
|
}
|
|
|
|
/**
|
|
* Count the number of times substr appears in value
|
|
*
|
|
* @param value input
|
|
* @param subStr search string
|
|
* @param caseSensitive whether search should be case sensitive
|
|
* @param allowOverlapping boolean to take into account overlapping
|
|
* @return count of times substring exists
|
|
*/
|
|
public static long countSubstr(final String value, final String subStr, final boolean caseSensitive, boolean allowOverlapping) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return countSubstr(caseSensitive ? value : value.toLowerCase(), caseSensitive ? subStr : subStr.toLowerCase(), allowOverlapping, 0L);
|
|
}
|
|
|
|
/**
|
|
* Test if value ends with search. The search is case sensitive.
|
|
*
|
|
* @param value input string
|
|
* @param search string to search
|
|
* @return true or false
|
|
*/
|
|
public static boolean endsWith(final String value, final String search) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return endsWith(value, search, value.length(), true);
|
|
}
|
|
|
|
/**
|
|
* Test if value ends with search.
|
|
*
|
|
* @param value input string
|
|
* @param search string to search
|
|
* @param caseSensitive true or false
|
|
* @return true or false
|
|
*/
|
|
public static boolean endsWith(final String value, final String search, final boolean caseSensitive) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return endsWith(value, search, value.length(), caseSensitive);
|
|
}
|
|
|
|
/**
|
|
* Test if value ends with search.
|
|
*
|
|
* @param value input string
|
|
* @param search string to search
|
|
* @param position position till which you want to search.
|
|
* @param caseSensitive true or false
|
|
* @return true or false
|
|
*/
|
|
public static boolean endsWith(final String value, final String search, final int position, final boolean caseSensitive) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
int remainingLength = position - search.length();
|
|
if (caseSensitive) {
|
|
return value.indexOf(search, remainingLength) > -1;
|
|
}
|
|
return value.toLowerCase().indexOf(search.toLowerCase(), remainingLength) > -1;
|
|
}
|
|
|
|
/**
|
|
* Ensures that the value begins with prefix. If it doesn't exist, it's prepended. It is case sensitive.
|
|
*
|
|
* @param value input
|
|
* @param prefix prefix
|
|
* @return string with prefix if it was not present.
|
|
*/
|
|
public static String ensureLeft(final String value, final String prefix) {
|
|
return ensureLeft(value, prefix, true);
|
|
}
|
|
|
|
/**
|
|
* Ensures that the value begins with prefix. If it doesn't exist, it's prepended.
|
|
*
|
|
* @param value input
|
|
* @param prefix prefix
|
|
* @param caseSensitive true or false
|
|
* @return string with prefix if it was not present.
|
|
*/
|
|
public static String ensureLeft(final String value, final String prefix, final boolean caseSensitive) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
if (caseSensitive) {
|
|
return value.startsWith(prefix) ? value : prefix + value;
|
|
}
|
|
String _value = value.toLowerCase();
|
|
String _prefix = prefix.toLowerCase();
|
|
return _value.startsWith(_prefix) ? value : prefix + value;
|
|
}
|
|
|
|
/**
|
|
* Decodes data encoded with MIME base64
|
|
*
|
|
* @param value The data to decode
|
|
* @return decoded data
|
|
*/
|
|
public static String base64Decode(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return new String(Base64.getDecoder().decode(value));
|
|
}
|
|
|
|
/**
|
|
* Encodes data with MIME base64.
|
|
*
|
|
* @param value The data to encode
|
|
* @return The encoded String
|
|
*/
|
|
public static String base64Encode(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return Base64.getEncoder().encodeToString(value.getBytes());
|
|
}
|
|
|
|
/**
|
|
* Convert binary unicode (16 digits) string to string chars
|
|
*
|
|
* @param value The value to decode
|
|
* @return The decoded String
|
|
*/
|
|
public static String binDecode(final String value) {
|
|
return decode(value, 16, 2);
|
|
}
|
|
|
|
/**
|
|
* Convert string chars to binary unicode (16 digits)
|
|
*
|
|
* @param value The value to encode
|
|
* @return String in binary format
|
|
*/
|
|
public static String binEncode(final String value) {
|
|
return encode(value, 16, 2);
|
|
}
|
|
|
|
/**
|
|
* Convert decimal unicode (5 digits) string to string chars
|
|
*
|
|
* @param value The value to decode
|
|
* @return decoded String
|
|
*/
|
|
public static String decDecode(final String value) {
|
|
return decode(value, 5, 10);
|
|
}
|
|
|
|
/**
|
|
* Convert string chars to decimal unicode (5 digits)
|
|
*
|
|
* @param value The value to encode
|
|
* @return Encoded value
|
|
*/
|
|
public static String decEncode(final String value) {
|
|
return encode(value, 5, 10);
|
|
}
|
|
|
|
/**
|
|
* Ensures that the value ends with suffix. If it doesn't, it's appended. This operation is case sensitive.
|
|
*
|
|
* @param value The input String
|
|
* @param suffix The substr to be ensured to be right
|
|
* @return The string which is guarenteed to start with substr
|
|
*/
|
|
public static String ensureRight(final String value, final String suffix) {
|
|
return ensureRight(value, suffix, true);
|
|
}
|
|
|
|
/**
|
|
* Ensures that the value ends with suffix. If it doesn't, it's appended.
|
|
*
|
|
* @param value The input String
|
|
* @param suffix The substr to be ensured to be right
|
|
* @param caseSensitive Use case (in-)sensitive matching for determining if value already ends with suffix
|
|
* @return The string which is guarenteed to start with substr
|
|
*/
|
|
public static String ensureRight(final String value, final String suffix, boolean caseSensitive) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return endsWith(value, suffix, caseSensitive) ? value : append(value, suffix);
|
|
}
|
|
|
|
/**
|
|
* Returns the first n chars of String
|
|
*
|
|
* @param value The input String
|
|
* @param n Number of chars to return
|
|
* @return The first n chars
|
|
*/
|
|
public static String first(final String value, final int n) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return value.substring(0, n);
|
|
}
|
|
|
|
/**
|
|
* Return the first char of String
|
|
*
|
|
* @param value The input String
|
|
* @return The first char
|
|
*/
|
|
public static String head(final String value) {
|
|
return first(value, 1);
|
|
}
|
|
|
|
/**
|
|
* Formats a string using parameters
|
|
*
|
|
* @param value The value to be formatted
|
|
* @param params Parameters to be described in the string
|
|
* @return The formatted string
|
|
*/
|
|
public static String format(final String value, String... params) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
Pattern p = Pattern.compile("\\{(\\w+)\\}");
|
|
Matcher m = p.matcher(value);
|
|
String result = value;
|
|
while (m.find()) {
|
|
int paramNumber = Integer.parseInt(m.group(1));
|
|
if (params == null || paramNumber >= params.length) {
|
|
throw new IllegalArgumentException("params does not have value for " + m.group());
|
|
}
|
|
result = result.replace(m.group(), params[paramNumber]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Convert hexadecimal unicode (4 digits) string to string chars
|
|
*
|
|
* @param value The value to decode
|
|
* @return The decoded String
|
|
*/
|
|
public static String hexDecode(final String value) {
|
|
return decode(value, 4, 16);
|
|
}
|
|
|
|
/**
|
|
* Convert string chars to hexadecimal unicode (4 digits)
|
|
*
|
|
* @param value The value to encode
|
|
* @return String in hexadecimal format.
|
|
*/
|
|
public static String hexEncode(final String value) {
|
|
return encode(value, 4, 16);
|
|
}
|
|
|
|
/**
|
|
* The indexOf() method returns the index within the calling String of the first occurrence of the specified value, starting the search at fromIndex.
|
|
* Returns -1 if the value is not found.
|
|
*
|
|
* @param value The input String
|
|
* @param needle The search String
|
|
* @param offset The offset to start searching from.
|
|
* @param caseSensitive boolean to indicate whether search should be case sensitive
|
|
* @return Returns position of first occurrence of needle.
|
|
*/
|
|
public static int indexOf(final String value, final String needle, int offset, boolean caseSensitive) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
if (caseSensitive) {
|
|
return value.indexOf(needle, offset);
|
|
}
|
|
return value.toLowerCase().indexOf(needle.toLowerCase(), offset);
|
|
}
|
|
|
|
/**
|
|
* Tests if two Strings are inequal
|
|
*
|
|
* @param first The first String
|
|
* @param second The second String
|
|
* @return true if first and second are not equal false otherwise
|
|
*/
|
|
public static boolean inequal(final String first, final String second) {
|
|
return !Objects.equals(first, second);
|
|
}
|
|
|
|
/**
|
|
* Inserts 'substr' into the 'value' at the 'index' provided.
|
|
*
|
|
* @param value The input String
|
|
* @param substr The String to insert
|
|
* @param index The index to insert substr
|
|
* @return String with substr added
|
|
*/
|
|
public static String insert(final String value, final String substr, final int index) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
validate(substr, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
if (index > value.length()) {
|
|
return value;
|
|
}
|
|
return append(value.substring(0, index), substr, value.substring(index));
|
|
}
|
|
|
|
/**
|
|
* Verifies if String is uppercase
|
|
*
|
|
* @param value The input String
|
|
* @return true if String is uppercase false otherwise
|
|
*/
|
|
public static boolean isUpperCase(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return Objects.equals(value, value.toUpperCase());
|
|
}
|
|
|
|
/**
|
|
* Verifies if String is lower case
|
|
*
|
|
* @param value The input String
|
|
* @return true if String is lowercase false otherwise
|
|
*/
|
|
public static boolean isLowerCase(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return Objects.equals(value, value.toLowerCase());
|
|
}
|
|
|
|
/**
|
|
* Return the last n chars of String
|
|
*
|
|
* @param value The input String
|
|
* @param n Number of chars to return
|
|
* @return n Last characters
|
|
*/
|
|
public static String last(final String value, int n) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
if (n > value.length()) {
|
|
return value;
|
|
}
|
|
return value.substring(value.length() - n);
|
|
}
|
|
|
|
/**
|
|
* Returns a new string of a given length such that the beginning of the string is padded.
|
|
*
|
|
* @param value The input String
|
|
* @param pad The pad
|
|
* @param length Length of the String we want
|
|
* @return Padded String
|
|
*/
|
|
public static String leftPad(final String value, final String pad, final int length) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
validate(pad, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
if (value.length() > length) {
|
|
return value;
|
|
}
|
|
return append(repeat(pad, length - value.length()), value);
|
|
}
|
|
|
|
/**
|
|
* Checks whether Object is String
|
|
*
|
|
* @param value The input String
|
|
* @return true if Object is a String false otherwise
|
|
*/
|
|
public static boolean isString(final Object value) {
|
|
if (Objects.isNull(value)) {
|
|
throw new IllegalArgumentException("value can't be null");
|
|
}
|
|
return value instanceof String;
|
|
}
|
|
|
|
/**
|
|
* This method returns the index within the calling String object of the last occurrence of the specified value, searching backwards from the offset.
|
|
* Returns -1 if the value is not found. The search starts from the end and case sensitive.
|
|
*
|
|
* @param value The input String
|
|
* @param needle The search String
|
|
* @return Return position of the last occurrence of 'needle'.
|
|
*/
|
|
public static int lastIndexOf(final String value, final String needle) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return lastIndexOf(value, needle, value.length(), true);
|
|
}
|
|
|
|
/**
|
|
* This method returns the index within the calling String object of the last occurrence of the specified value, searching backwards from the offset.
|
|
* Returns -1 if the value is not found. The search starts from the end and case sensitive.
|
|
*
|
|
* @param value The input String
|
|
* @param needle The search String
|
|
* @return Return position of the last occurrence of 'needle'.
|
|
*/
|
|
public static int lastIndexOf(final String value, final String needle, boolean caseSensitive) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return lastIndexOf(value, needle, value.length(), caseSensitive);
|
|
}
|
|
|
|
/**
|
|
* This method returns the index within the calling String object of the last occurrence of the specified value, searching backwards from the offset.
|
|
* Returns -1 if the value is not found.
|
|
*
|
|
* @param value The input String
|
|
* @param needle The search String
|
|
* @param offset The index to start search from
|
|
* @param caseSensitive whether search should be case sensitive
|
|
* @return Return position of the last occurrence of 'needle'.
|
|
*/
|
|
public static int lastIndexOf(final String value, final String needle, final int offset, final boolean caseSensitive) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
validate(needle, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
if (caseSensitive) {
|
|
return value.lastIndexOf(needle, offset);
|
|
}
|
|
return value.toLowerCase().lastIndexOf(needle.toLowerCase(), offset);
|
|
}
|
|
|
|
/**
|
|
* Removes all spaces on left
|
|
*
|
|
* @param value The input String
|
|
* @return String without left border spaces
|
|
*/
|
|
public static String leftTrim(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return value.replaceAll("^\\s+", "");
|
|
}
|
|
|
|
/**
|
|
* Returns length of String. Delegates to java.lang.String length method.
|
|
*
|
|
* @param value The input String
|
|
* @return Length of the String
|
|
*/
|
|
public static int length(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return value.length();
|
|
}
|
|
|
|
/**
|
|
* Return a new String starting with prepends
|
|
*
|
|
* @param value The input String
|
|
* @param prepends Strings to prepend
|
|
* @return The prepended String
|
|
*/
|
|
public static String prepend(final String value, final String... prepends) {
|
|
return prependArray(value, prepends);
|
|
}
|
|
|
|
/**
|
|
* Return a new String starting with prepends
|
|
*
|
|
* @param value The input String
|
|
* @param prepends Strings to prepend
|
|
* @return The prepended String
|
|
*/
|
|
public static String prependArray(final String value, final String[] prepends) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
if (prepends == null || prepends.length == 0) {
|
|
return value;
|
|
}
|
|
StringJoiner joiner = new StringJoiner("");
|
|
for (String prepend : prepends) {
|
|
joiner.add(prepend);
|
|
}
|
|
return joiner.toString() + value;
|
|
}
|
|
|
|
/**
|
|
* Remove empty Strings from string array
|
|
*
|
|
* @param strings Array of String to be cleaned
|
|
* @return Array of String without empty Strings
|
|
*/
|
|
public static String[] removeEmptyStrings(String[] strings) {
|
|
if (Objects.isNull(strings)) {
|
|
throw new IllegalArgumentException("Input array should not be null");
|
|
}
|
|
return Arrays.stream(strings).filter(str -> str != null && !str.trim().isEmpty()).toArray(String[]::new);
|
|
}
|
|
|
|
/**
|
|
* Returns a new String with the prefix removed, if present. This is case sensitive.
|
|
*
|
|
* @param value The input String
|
|
* @param prefix String to remove on left
|
|
* @return The String without prefix
|
|
*/
|
|
public static String removeLeft(final String value, final String prefix) {
|
|
return removeLeft(value, prefix, true);
|
|
}
|
|
|
|
/**
|
|
* Returns a new String with the prefix removed, if present.
|
|
*
|
|
* @param value The input String
|
|
* @param prefix String to remove on left
|
|
* @param caseSensitive ensure case sensitivity
|
|
* @return The String without prefix
|
|
*/
|
|
public static String removeLeft(final String value, final String prefix, final boolean caseSensitive) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
validate(prefix, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
BiFunction<String, String, String> fx = (f, s) -> f.startsWith(s) ? f.replaceFirst(s, "") : f;
|
|
if (caseSensitive) {
|
|
return fx.apply(value, prefix);
|
|
}
|
|
return fx.apply(value.toLowerCase(), prefix.toLowerCase());
|
|
}
|
|
|
|
/**
|
|
* Remove all non word characters.
|
|
*
|
|
* @param value The input String
|
|
* @return String without non-word characters
|
|
*/
|
|
public static String removeNonWords(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return value.replaceAll("[^\\w]+", "");
|
|
}
|
|
|
|
/**
|
|
* Returns a new string with the 'suffix' removed, if present. Search is case sensitive.
|
|
*
|
|
* @param value The input String
|
|
* @param suffix The suffix to remove
|
|
* @return The String without suffix!
|
|
*/
|
|
public static String removeRight(final String value, final String suffix) {
|
|
return removeRight(value, suffix, true);
|
|
}
|
|
|
|
/**
|
|
* Returns a new string with the 'suffix' removed, if present.
|
|
*
|
|
* @param value The input String
|
|
* @param suffix The suffix to remove
|
|
* @param caseSensitive whether search should be case sensitive or not
|
|
* @return The String without suffix!
|
|
*/
|
|
public static String removeRight(final String value, final String suffix, final boolean caseSensitive) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
validate(suffix, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return endsWith(value, suffix, caseSensitive) ? value.substring(0, value.toLowerCase().lastIndexOf(suffix.toLowerCase())) : value;
|
|
}
|
|
|
|
/**
|
|
* Remove all spaces and replace for value.
|
|
*
|
|
* @param value The input String
|
|
* @return String without spaces
|
|
*/
|
|
public static String removeSpaces(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return value.replaceAll("\\s", "");
|
|
}
|
|
|
|
/**
|
|
* Returns a repeated string given a multiplier.
|
|
*
|
|
* @param value The input String
|
|
* @param multiplier Number of repeats
|
|
* @return The String repeated
|
|
*/
|
|
public static String repeat(final String value, final int multiplier) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return Stream.generate(() -> value).limit(multiplier).collect(joining());
|
|
}
|
|
|
|
/**
|
|
* Replace all occurrences of 'search' value to 'newvalue'. Uses String replace method.
|
|
*
|
|
* @param value The input
|
|
* @param search The String to search
|
|
* @param newValue The String to replace
|
|
* @param caseSensitive whether search should be case sensitive or not
|
|
* @return String replaced with 'newvalue'.
|
|
*/
|
|
public static String replace(final String value, final String search, final String newValue, final boolean caseSensitive) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
validate(search, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
if (caseSensitive) {
|
|
return value.replace(search, newValue);
|
|
}
|
|
return value.toLowerCase().replace(search.toLowerCase(), newValue);
|
|
}
|
|
|
|
/**
|
|
* Reverse the input String
|
|
*
|
|
* @param value The input String
|
|
* @return Reversed String
|
|
*/
|
|
public static String reverse(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return new StringBuilder(value).reverse().toString();
|
|
}
|
|
|
|
/**
|
|
* Returns a new string of a given length such that the ending of the string is padded.
|
|
*
|
|
* @param value The input String
|
|
* @param length Max length of String.
|
|
* @param pad Character to repeat
|
|
* @return Right padded String
|
|
*/
|
|
public static String rightPad(final String value, String pad, final int length) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
if (value.length() > length) {
|
|
return value;
|
|
}
|
|
return append(value, repeat(pad, length - value.length()));
|
|
}
|
|
|
|
/**
|
|
* Remove all spaces on right.
|
|
*
|
|
* @param value The String
|
|
* @return String without right boarders spaces.
|
|
*/
|
|
public static String rightTrim(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return value.replaceAll("\\s+$", "");
|
|
}
|
|
|
|
/**
|
|
* Truncate the string securely, not cutting a word in half. It always returns the last full word.
|
|
*
|
|
* @param value The input String
|
|
* @param length Max size of the truncated String
|
|
* @param filler String that will be added to the end of the return string. Example: '...'
|
|
* @return The truncated String
|
|
*/
|
|
public static String safeTruncate(final String value, final int length, final String filler) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
if (length == 0) {
|
|
return "";
|
|
}
|
|
if (length >= value.length()) {
|
|
return value;
|
|
}
|
|
|
|
String[] words = words(value);
|
|
StringJoiner result = new StringJoiner(" ");
|
|
int spaceCount = 0;
|
|
for (String word : words) {
|
|
if (result.length() + word.length() + filler.length() + spaceCount > length) {
|
|
break;
|
|
} else {
|
|
result.add(word);
|
|
spaceCount++;
|
|
}
|
|
}
|
|
return append(result.toString(), filler);
|
|
}
|
|
|
|
/**
|
|
* Alias to String split function. Defined only for completeness.
|
|
*
|
|
* @param value The input String
|
|
* @param regex The delimiting regular expression
|
|
* @return String Array
|
|
*/
|
|
public static String[] split(final String value, final String regex) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return value.split(regex);
|
|
}
|
|
|
|
/**
|
|
* Splits a String to words
|
|
*
|
|
* @param value The input String
|
|
* @return Words Array
|
|
*/
|
|
public static String[] words(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return value.split("\\W+");
|
|
}
|
|
|
|
/**
|
|
* Truncate the unsecured form string, cutting the independent string of required position.
|
|
*
|
|
* @param value Value will be truncated unsecurely.
|
|
* @param length Size of the returned string.
|
|
* @param filler Value that will be added to the end of the return string. Example: '...'
|
|
* @return String truncated unsafely.
|
|
*/
|
|
public static String truncate(final String value, final int length, final String filler) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
if (length == 0) {
|
|
return "";
|
|
}
|
|
if (length >= value.length()) {
|
|
return value;
|
|
}
|
|
return append(value.substring(0, length - filler.length()), filler);
|
|
}
|
|
|
|
/**
|
|
* Converts all HTML entities to applicable characters.
|
|
*
|
|
* @param encodedHtml The encoded HTML
|
|
* @return The decoded HTML
|
|
*/
|
|
public static String htmlDecode(final String encodedHtml) {
|
|
validate(encodedHtml, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
String[] entities = encodedHtml.split("&\\W+;");
|
|
return Arrays.stream(entities).map(e -> HtmlEntities.decodedEntities.get(e)).collect(joining());
|
|
}
|
|
|
|
/**
|
|
* Convert all applicable characters to HTML entities.
|
|
*
|
|
* @param html The HTML to encode
|
|
* @return The encoded data
|
|
*/
|
|
public static String htmlEncode(final String html) {
|
|
validate(html, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return html.chars().mapToObj(c -> "\\u" + String.format("%04x", c).toUpperCase()).map(e -> HtmlEntities.encodedEntities.get(e)).collect(joining());
|
|
}
|
|
|
|
/**
|
|
* It returns a string with its characters in random order.
|
|
*
|
|
* @param value The input String
|
|
* @return The shuffled String
|
|
*/
|
|
public static String shuffle(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
String[] chars = chars(value);
|
|
Random random = new Random();
|
|
for (int i = 0; i < chars.length; i++) {
|
|
int r = random.nextInt(chars.length);
|
|
String tmp = chars[i];
|
|
chars[i] = chars[r];
|
|
chars[r] = tmp;
|
|
}
|
|
return Arrays.stream(chars).collect(joining());
|
|
}
|
|
|
|
/**
|
|
* Alias of substring method
|
|
*
|
|
* @param value The input String
|
|
* @param begin Start of slice.
|
|
* @param end End of slice.
|
|
* @return The String sliced!
|
|
*/
|
|
public static String slice(final String value, int begin, int end) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return value.substring(begin, end);
|
|
}
|
|
|
|
/**
|
|
* Convert a String to a slug
|
|
*
|
|
* @param value The value to slugify
|
|
* @return The slugified value
|
|
*/
|
|
public static String slugify(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
String transliterated = transliterate(collapseWhitespace(value.trim().toLowerCase()));
|
|
return Arrays.stream(words(transliterated.replace("&", "-and-"))).collect(joining("-"));
|
|
}
|
|
|
|
/**
|
|
* Remove all non valid characters. Example: change á => a or ẽ => e.
|
|
*
|
|
* @param value The input String
|
|
* @return String without non valid characters.
|
|
*/
|
|
public static String transliterate(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
String result = value;
|
|
Set<Map.Entry<String, List<String>>> entries = Ascii.ascii.entrySet();
|
|
for (Map.Entry<String, List<String>> entry : entries) {
|
|
for (String ch : entry.getValue()) {
|
|
result = result.replace(ch, entry.getKey());
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/**
|
|
* Surrounds a 'value' with the given 'prefix' and 'suffix'.
|
|
*
|
|
* @param value The input String
|
|
* @param prefix prefix. If suffix is null then prefix is used
|
|
* @param suffix suffix
|
|
* @return The String with surround substrs!
|
|
*/
|
|
public static String surround(final String value, final String prefix, final String suffix) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
String _prefix = Optional.ofNullable(prefix).orElse("");
|
|
return append(_prefix, value, Optional.ofNullable(suffix).orElse(_prefix));
|
|
}
|
|
|
|
/**
|
|
* Transform to camelCase
|
|
*
|
|
* @param value The input String
|
|
* @return String in camelCase.
|
|
*/
|
|
public static String toCamelCase(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
String str = toStudlyCase(value);
|
|
return str.substring(0, 1).toLowerCase() + str.substring(1);
|
|
}
|
|
|
|
/**
|
|
* Transform to StudlyCaps.
|
|
*
|
|
* @param value The input String
|
|
* @return String in StudlyCaps.
|
|
*/
|
|
public static String toStudlyCase(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
String[] words = collapseWhitespace(value.trim()).split("\\s*(_|-|\\s)\\s*");
|
|
return Arrays.stream(words).filter(w -> !w.trim().isEmpty()).map(w -> head(w).toUpperCase() + tail(w)).collect(joining());
|
|
}
|
|
|
|
/**
|
|
* Return tail of the String
|
|
*
|
|
* @param value The input String
|
|
* @return String tail
|
|
*/
|
|
public static String tail(final String value) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return last(value, value.length() - 1);
|
|
}
|
|
|
|
/**
|
|
* Decamelize String
|
|
*
|
|
* @param value The input String
|
|
* @return String decamelized.
|
|
*/
|
|
public static String toDecamelize(final String value, final String chr) {
|
|
String camelCasedString = toCamelCase(value);
|
|
String[] words = camelCasedString.split("(?=\\p{Upper})");
|
|
return Arrays.stream(words).map(w -> w.toLowerCase()).collect(joining(Optional.ofNullable(chr).orElse(" ")));
|
|
}
|
|
|
|
/**
|
|
* Transform to kebab-case.
|
|
*
|
|
* @param value The input String
|
|
* @return String in kebab-case.
|
|
*/
|
|
public static String toKebabCase(final String value) {
|
|
return toDecamelize(value, "-");
|
|
}
|
|
|
|
/**
|
|
* Transform to snake_case.
|
|
*
|
|
* @param value The input String
|
|
* @return String in snake_case.
|
|
*/
|
|
public static String toSnakeCase(final String value) {
|
|
return toDecamelize(value, "_");
|
|
}
|
|
|
|
public static String decode(final String value, final int digits, final int radix) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return Arrays
|
|
.stream(value.split("(?<=\\G.{" + digits + "})"))
|
|
.map(data -> String.valueOf(Character.toChars(Integer.parseInt(data, radix))))
|
|
.collect(joining());
|
|
}
|
|
|
|
public static String encode(final String value, final int digits, final int radix) {
|
|
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG_SUPPLIER);
|
|
return value.chars().mapToObj(ch -> leftPad(Integer.toString(ch, radix), "0", digits)).collect(joining());
|
|
}
|
|
|
|
private static void validate(String value, Predicate<String> predicate, final Supplier<String> supplier) {
|
|
if (predicate.test(value)) {
|
|
throw new IllegalArgumentException(supplier.get());
|
|
}
|
|
}
|
|
|
|
private static long countSubstr(String value, String subStr, boolean allowOverlapping, long count) {
|
|
int position = value.indexOf(subStr);
|
|
if (position == -1) {
|
|
return count;
|
|
}
|
|
int offset;
|
|
if (!allowOverlapping) {
|
|
offset = position + subStr.length();
|
|
} else {
|
|
offset = position + 1;
|
|
}
|
|
return countSubstr(value.substring(offset), subStr, allowOverlapping, ++count);
|
|
}
|
|
}
|