
org.seppiko.commons.utils.StringUtil Maven / Gradle / Ivy
/*
* Copyright 2023 the original author or authors.
*
* 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 org.seppiko.commons.utils;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.regex.Matcher;
/**
* String Util
*
* @author Leonard Woo
*/
public class StringUtil {
private StringUtil() {}
/**
* Require a CharSequence with default value.
*
* @param value CharSequence instance.
* @param defaultValue default CharSequence instance.
* @return CharSequence without null.
*/
public static CharSequence requireNonBlankElse(CharSequence value, CharSequence defaultValue) {
return isNullOrEmpty(value)? defaultValue: value;
}
/**
* Test CharSequence is empty or contains only whitespace codepoints
*
* @param value CharSequence instance.
* @return true is yes.
*/
public static boolean isNullOrEmpty(CharSequence value) {
return Objects.isNull(value) || value.isEmpty();
}
/**
* Test CharSequence has any char
*
* @param input CharSequence instance.
* @return true is yes.
*/
public static boolean hasLength(CharSequence input) {
return Objects.nonNull(input) && (input.length() > 0);
}
/**
* Test CharSequence has any char without non-blank character
*
* @param input CharSequence instance.
* @return true is not null and without whitespace, false is otherwise.
*/
public static boolean hasText(CharSequence input) {
return hasLength(input) && containsText(input);
}
/**
* Test CharSequence is not null and empty or has non-blank character
*
* @param input CharSequence instance.
* @return true is not null and empty, false is otherwise.
*/
public static boolean nonText(CharSequence input) {
return Objects.nonNull(input) && (input.isEmpty() || !containsText(input));
}
// check input include whitespace or ISO control chars.
private static boolean containsText(CharSequence input) {
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
if (!Character.isWhitespace(ch) || !Character.isISOControl(ch)) {
return true;
}
}
return false;
}
/**
* Test CharSequence is uppercase
*
* @param input uppercase CharSequence.
* @return true is uppercase.
*/
public static boolean isUppercase(CharSequence input) {
return RegexUtil.matches("^[\\p{Upper}A-Z]+$", input);
}
/**
* Test CharSequence is lowercase
*
* @param input lowercase CharSequence.
* @return true is lowercase.
*/
public static boolean isLowercase(CharSequence input) {
return RegexUtil.matches("^[\\p{Lower}a-z]+$", input);
}
/**
* Test CharSequence is numeric
*
* @param input numeric CharSequence.
* @return true is numeric.
*/
public static boolean isNumeric(CharSequence input) {
return RegexUtil.matches("^[--++]?[\\d0-9]+([\\..]{1}[\\d0-9]+)?$", input);
}
/**
* Test CharSequence is integer
*
* @param input integer CharSequence.
* @return true is integer.
*/
public static boolean isInteger(CharSequence input) {
return RegexUtil.matches("^[--++]?[\\d0-9]+$", input);
}
/**
* Test CharSequence is decimal
*
* @param input decimal CharSequence.
* @return true is decimal.
*/
public static boolean isDecimal(CharSequence input) {
return RegexUtil.matches("^[--++]?[\\d0-9]+[\\..]{1}[\\d0-9]+$", input);
}
/**
* Test CharSequence is punctuation
*
* @param input punctuation CharSequence.
* @return true is punctuation.
*/
public static boolean isPunctuation(CharSequence input) {
return RegexUtil.matches("^[\\p{Punct}!"#$%&'()*+,-./:;<=>?@[\]^_`{|}]+$", input);
}
/**
* Convert string data from old encoding to new encoding
*
* @param data CharSequence data.
* @param oldEncoding old encoding.
* @param newEncoding new encoding.
* @return new encoding CharSequence.
* @throws NullPointerException old encode or new decode exception.
*/
public static String transcoding(CharSequence data, Charset oldEncoding, Charset newEncoding)
throws NullPointerException {
byte[] oldData = CharUtil.charsetEncode(oldEncoding, CharBuffer.wrap(data));
if (oldData == Environment.EMPTY_BYTE_ARRAY) {
throw new NullPointerException("old encode exception");
}
CharBuffer cb = CharUtil.charsetDecode(newEncoding, oldData);
if (cb.capacity() == 0) {
throw new NullPointerException("new decode exception");
}
return cb.toString();
}
/**
* Return fixed length string object
*
* @param str string object.
* @param length count length.
* @param preChar pre-padded character.
* @return fixed length string object.
*/
public static String fixedLength(String str, int length, char preChar) {
StringBuilder sb = new StringBuilder();
if (str.length() < length) {
int preLength = length - str.length();
sb.append(String.valueOf(preChar).repeat(preLength));
sb.append(str);
} else {
sb.append(str.substring(str.length() - length));
}
return sb.toString();
}
/**
* Capitalize the first letter
*
* @param input origin string.
* @return new string.
*/
public static String toFirstUpperCase(String input) {
String s = String.valueOf(Character.toUpperCase(input.charAt(0)));
if (input.length() > 1) {
return s + input.subSequence(1, input.length());
}
return s;
}
/**
* Replace CharSequence between start and end
*
* @param data origin data.
* @param start replace start index.
* @param end replace end index.
* @param replacement replace data.
* @return new string.
*/
public static String replaceBetween(
CharSequence data, int start, int end, CharSequence replacement) {
StringBuilder sb = new StringBuilder();
sb.append(data, 0, start);
sb.append(replacement);
sb.append(data, end, data.length());
return sb.toString();
}
/**
* convert joiner string with delimiter
*
* @param delimiter the sequence of characters to be used between each array element.
* @param strs string array.
* @return the string representation.
*/
public static String convertJoinerString(String delimiter, String... strs) {
StringJoiner sj = new StringJoiner(delimiter);
for (String str : strs) {
if (hasLength(str)) {
sj.add(str);
}
}
return sj.toString();
}
/**
* Convert Char Sequence to String with separate
*
* @param input Raw data.
* @param splitNum Separation interval.
* @param split Separator.
* @return encoded string.
*/
public static String convertToString(CharSequence input, int splitNum, String split) {
StringBuilder sb = new StringBuilder();
// add split in every splitNum
for (int i = 0; i < input.length(); i = i + splitNum) {
for (int j = 0; j < splitNum; j++) {
sb.append(input.charAt(i + j));
}
sb.append(split);
}
String dst = sb.toString();
return dst.substring(0, dst.length() - split.length()); // delete last split
}
/**
* Delete string separator and to char array.
*
* @param src string.
* @param separator separator.
* @return char array.
* @throws NullPointerException when data or separator is null.
*/
public static char[] convertToCharArray(String src, String separator) throws NullPointerException {
Objects.requireNonNull(src, "src must not be null.");
Objects.requireNonNull(separator, "separator must not be null.");
Matcher m = RegexUtil.getMatcher(separator, src);
Objects.requireNonNull(m, "split matcher failed");
if (m.find()) {
return m.replaceAll("").toCharArray();
}
return src.toCharArray();
}
/**
* Split key value pair string to the map.
*
* @param input The key value pair string to be split.
* @param nodeSeparator Split the input string on this delimiter with regex.
* @param pairSeparator For each part, split with this delimiter with regex.
* @return key value pair map.
*/
public static Map splitToMap(String input, String nodeSeparator, String pairSeparator) {
Map map = new HashMap<>();
if (!input.isEmpty()) {
String[] parts = RegexUtil.split(nodeSeparator, input);
for (String part : parts) {
String[] pair = RegexUtil.split(pairSeparator, part);
map.put(pair[0], pair[1]);
}
}
return map;
}
/** between {@code '\uFF01'} and {\u0021} number */
protected static final Integer BETWEEN =
(CharUtil.FULLWIDTH_EXCLAMATION_MARK - CharUtil.EXCLAMATION_MARK);
/**
* Convert half-width string ({@code '\u005Cu0021'} through {@code '\u005Cu007E'}) to
* full-width string ({@code '\u005CuFF01'} through {@code '\u005CuFF5E'})
*
* @param src Half-width string.
* @return Full-width string.
*/
public static String toFullWidth(CharSequence src) {
StringBuilder sb = new StringBuilder(src.length());
for (int i = 0; i < src.length(); i++) {
char c = src.charAt(i);
if (NumberUtil.between(c, CharUtil.EXCLAMATION_MARK, CharUtil.TILDE)) {
sb.append((char) (c + BETWEEN));
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
* Convert full-width string ({@code '\u005CuFF01'} through {@code '\u005CuFF5E'}) to
* half-width string ({@code '\u005Cu0021'} through {@code '\u005Cu007E'})
*
* @param src Full-width string.
* @return Half-width string.
*/
public static String toHalfWidth(CharSequence src) {
StringBuilder sb = new StringBuilder(src.length());
for (int i = 0; i < src.length(); i++) {
char c = src.charAt(i);
if (NumberUtil.between(c, CharUtil.FULLWIDTH_EXCLAMATION_MARK, CharUtil.FULLWIDTH_TILDE)) {
sb.append((char) (c - BETWEEN));
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
* Unicode decoding.
* When not found return origin String
*
* @param src unicode string like {@code '\\uXXXX'}.
* @return String. If src is null or empty return empty string.
*/
public static String unicodeDecode(String src) {
if (isNullOrEmpty(src)) {
return "";
}
Matcher m = RegexUtil.getMatcher("(\\\\u(\\p{XDigit}{4}))", src);
while (m.find()) {
String group = m.group(2);
char ch = (char) Integer.parseInt(group, 16);
String group1 = m.group(1);
src = src.replace(group1, String.valueOf(ch));
}
return src;
}
/**
* Unicode encoding
*
* @param src String
* @return unicode string like {@code '\\uXXXX'}. If src is null or empty return empty string.
*/
public static String unicodeEncode(String src) {
if (isNullOrEmpty(src)) {
return "";
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < src.length(); i++) {
char ch = src.charAt(i);
if (NumberUtil.between(ch, CharUtil.SPACE, CharUtil.TILDE)) {
sb.append(ch);
} else {
sb.append("\\u");
String hex = Integer.toHexString(ch & 0xFFFF).toUpperCase();
sb.append(fixedLength(hex, 4, CharUtil.DIGIT_ONE));
}
}
return sb.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy