![JAR search and dependency download from the Maven repository](/logo.png)
com.tomtom.speedtools.utils.StringUtils Maven / Gradle / Ivy
/*
* Copyright (C) 2012-2019, TomTom (http://tomtom.com).
*
* Licensed 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 com.tomtom.speedtools.utils;
import com.tomtom.speedtools.objects.Immutables;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
public final class StringUtils {
private StringUtils() {
// Prevent instantiation.
}
/**
* Converts a {@code null} string to an empty string.
*
* @param s Input string, or {@code null}.
* @return The empty string when {@code s} is {@code null}, {@code s} otherwise.
*/
@Nonnull
public static String nullToEmpty(@Nullable final String s) {
return (s == null) ? "" : s;
}
/**
* Converts an empty or null string to null.
*
* @param s Input string, or {@code null}.
* @return Null when {@code s} is empty, {@code s} otherwise.
*/
@Nullable
public static String emptyToNull(@Nullable final String s) {
return ((s != null) && s.isEmpty()) ? null : s;
}
/**
* Trims a string and can accept {@code null} input strings. Returns {@code null} when input is {@code null}.
*
* @param s Input string, or {@code null}.
* @return Trimmed string, or {@code null}.
*/
@Nullable
public static String trim(@Nullable final String s) {
if (s == null) {
return null;
} else {
return s.trim();
}
}
/**
* Trims a list of strings, retaining the order of the input list. Can accept {@code null} input lists. Returns
* {@code null} when input is {@code null}.
*
* @param sList List of strings to trim, or {@code null}.
* @return List containing trimmed strings, or {@code null}.
*/
@Nullable
public static List trim(@Nullable final List sList) {
if (sList == null) {
return null;
}
return trim(Immutables.listOf(sList), new ArrayList<>(sList.size()));
}
/**
* Trims a set of strings. Can accept {@code null} input sets. Returns {@code null} when input is {@code null}.
*
* @param sSet Set of strings to trim, or {@code null}.
* @return Set containing trimmed strings, or {@code null}.
*/
@Nullable
public static Set trim(@Nullable final Set sSet) {
if (sSet == null) {
return null;
}
return trim(sSet, new HashSet<>());
}
/**
* Trims a collection of strings.
*
* @param in Collection of strings to trim.
* @param out Collection in which trimmed strings should be stored in.
* @param Collection type.
* @return Returns {@code out} for convenience.
*/
@Nonnull
private static > T trim(@Nonnull final T in, @Nonnull final T out) {
assert in != null;
assert out != null;
for (final String s : in) {
out.add(trim(s));
}
return out;
}
/**
* Converts a string to lower case in a locale insensitive manner, and can accept {@code null} input strings.
* Returns {@code null} when input is {@code null}.
*
* The string conversion uses {@link String#toLowerCase() String.toLowerCase(Locale.ENGLISH)}. See {@link
* String#toLowerCase()} on when to use the default system locale during conversion to lower case, and in which
* cases this will produce the wrong results.
*
* @param s Input string, or {@code null}.
* @return String converted to lower case, or {@code null}.
*/
@Nullable
public static String literalToLowerCase(@Nullable final String s) {
if (s == null) {
return null;
} else {
return s.toLowerCase(Locale.ENGLISH);
}
}
/**
* Converts a string to a list of Unicode code points. This method should be used when wanting to iterate over a
* string character-by-character.
*
* This method is necessary because Java stores characters as UTF-16 values in a String, and {@link
* String#charAt(int)} returns a 16-bit value. This works fine for characters in the Basic Multilingual Plane (BMP),
* but Unicode allows for supplementary characters that take up more than 16 bits to represent them. For Strings,
* this means that Java will store those characters as two characters, with the first character being a value in the
* high-surrogates range, and the second value in the low-surrogates range. Therefore, {@code charAt(n)} may
* actually return a char value that does not represent the actual character when a supplementary character is
* stored, and only combining {@code charAt(n)} together with {@code charAt(n plus 1)} would result in the correct
* character.
*
* The implementation of this method is based on JDK-5003547
* and JDK-5063163.
*
* See {@link Character} and Supplementary
* Characters in the Java Platform for further information on Java and Unicode.
*
* @param s Input string.
* @return Array of all code points contained in-order in {@code s}. The length of the returned array is {@code <=}
* the length of the given {@code s}.
*/
@Nonnull
public static int[] toCodePoints(@Nonnull final String s) {
assert s != null;
final int[] codePoints = new int[s.codePointCount(0, s.length())];
assert codePoints != null;
assert codePoints.length <= s.length();
int stringIndex = 0;
for (int codePointsIndex = 0; codePointsIndex < codePoints.length; codePointsIndex++) {
codePoints[codePointsIndex] = s.codePointAt(stringIndex);
stringIndex += Character.charCount(codePoints[codePointsIndex]);
}
return codePoints;
}
/**
* Assembles a String with all the elements of an input collection using a provided separator. Example:
*
* final List<Integer> list = new ArrayList<Integer>();
* list.add(1);
* list.add(2);
* list.add(3);
*
*
* Calling mkString as shown below:
*
* final String result = mkString("|", list);
*
* will provide:
*
* result := "1|2|3"
*
*
* @param values Values.
* @param separator Separator string between values.
* @return String with values, separated by separator.
*/
@Nonnull
public static String mkString(@Nonnull final String separator, @Nonnull final Collection> values) {
assert values != null;
assert separator != null;
boolean first = true;
final StringBuilder sb = new StringBuilder();
for (final Object value : values) {
if (value != null) {
final String str = value.toString();
if (!str.isEmpty()) {
if (!first) {
sb.append(separator);
} else {
first = false;
}
sb.append(str);
}
}
}
return sb.toString();
}
@Nonnull
public static String mkRevString(@Nonnull final String separator, @Nonnull final Collection values) {
final LinkedList rev = new LinkedList<>();
for (final T value : values) {
rev.addFirst(value);
}
return mkString(separator, rev);
}
/**
* Same as mkString but for an Array.
*
* @param Element type.
* @param separator The separator to use.
* @param values The values.
* @return String with values, separated by separator.
*/
@SafeVarargs
@Nonnull
public static String mkString(@Nonnull final String separator, @Nonnull final T... values) {
return mkString(separator, Arrays.asList(values));
}
/**
* Same as mkRevString but for an Array.
*
* @param Element type.
* @param separator The separator to use.
* @param values The values.
* @return String with values, separated by separator.
*/
@SafeVarargs
@Nonnull
public static String mkRevString(@Nonnull final String separator, @Nonnull final T... values) {
return mkRevString(separator, Arrays.asList(values));
}
/**
* Method generates a random string from given characters with specified length.
*
* @param chars The characters, Should at least contain 1 character.
* @param length The length. Should be greater than 0.
* @return Random String.
*/
@Nonnull
public static String generateRandomStringFromChars(@Nonnull final char[] chars, final int length) {
assert chars != null;
assert length > 0;
assert chars.length > 0;
final char[] code = new char[length];
final Random random = new Random();
for (int i = 0; i < length; i++) {
final int index = random.nextInt(chars.length);
code[i] = chars[index];
}
return new String(code);
}
/**
* Method escapes a string in JSON format.
*
* @param input The original string.
* @return The escaped string.
*/
@SuppressWarnings("ConstantConditions")
@Nonnull
public static String encodeToJsonString(@Nonnull final String input) {
assert input != null;
final int len = input.length();
final StringBuilder sb = new StringBuilder(len + 2); // Min. length = string length + 2 quotes.
sb.append('"');
for (int i = 0; i < len; ++i) {
final char ch = input.charAt(i);
switch (ch) {
case '\\':
// Fall through.
case '"':
// Fall through.
case '/':
sb.append('\\');
sb.append(ch);
break;
case '\b':
sb.append("\\b");
break;
case '\t':
sb.append("\\t");
break;
case '\n':
sb.append("\\n");
break;
case '\f':
sb.append("\\f");
break;
case '\r':
sb.append("\\r");
break;
default:
if (((ch >= '\u0000') && (ch <= '\u001F')) ||
((ch >= '\u007F') && (ch <= '\u009F')) ||
(((ch >= '\u2000') && (ch <= '\u20FF')))) {
sb.append("\\u").append(Integer.toHexString(((int) ch) + 0x10000).substring(1));
} else {
sb.append(ch);
}
break;
}
}
sb.append('"');
return sb.toString();
}
/**
* Method unescapes a JSON string to regular string format.
*
* @param input The JSON string.
* @return The regular unescaped string, or null if conversion failed.
*/
@Nullable
public static String decodeFromJsonString(@Nonnull final String input) {
assert input != null;
// String must be contained in "...".
if ((input.length() < 2) || (input.charAt(0) != '"') || (input.charAt(input.length() - 1) != '"')) {
return null;
}
final int len = input.length() - 2;
final StringBuilder sb = new StringBuilder(len);
int i = 1;
while (i <= len) {
char ch = input.charAt(i);
if (ch == '\\') {
// Bail out: "\" at end of string is not valid.
if (i == len) {
return null;
}
++i;
ch = input.charAt(i);
switch (ch) {
case '\\':
// Fall through.
case '"':
// Fall through.
case '/':
// Strip '\' and add character behind it.
sb.append(ch);
++i;
break;
case 'b':
sb.append('\b');
++i;
break;
case 't':
sb.append('\t');
++i;
break;
case 'n':
sb.append('\n');
++i;
break;
case 'f':
sb.append('\f');
++i;
break;
case 'r':
sb.append('\r');
++i;
break;
case 'u':
// Unicode character, format 'u' followed by 4 hex digits.
if (i > (len - 4)) {
return null;
}
++i;
final String hex = input.substring(i, i + 4);
i = i + 4;
final int hexValue;
try {
hexValue = Integer.parseInt(hex, 16);
} catch (final NumberFormatException ignored) {
// Illegal format, bail out.
return null;
}
assert ((0x0000 <= hexValue) && (hexValue <= 0xFFFF));
//noinspection NumericCastThatLosesPrecision
sb.append((char) hexValue);
break;
default:
sb.append(ch);
++i;
break;
}
} else {
// Regular character, just add to string.
sb.append(ch);
++i;
}
}
return sb.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy