| /* |
| * 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.openjpa.lib.util; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| |
| |
| public final class StringUtil { |
| |
| private static final String[] EMPTY_STRING_ARRAY = new String[0]; |
| |
| |
| private static final Byte BYTE_ZERO = Byte.valueOf((byte) 0); |
| private static final Character CHAR_ZERO = Character.valueOf((char) 0); |
| private static final Double DOUBLE_ZERO = Double.valueOf(0.0d); |
| private static final Float FLOAT_ZERO = Float.valueOf(0.0f); |
| private static final Integer INTEGER_ZERO = Integer.valueOf(0); |
| private static final Long LONG_ZERO = Long.valueOf(0); |
| private static final Short SHORT_ZERO = Short.valueOf((short) 0); |
| |
| private StringUtil() { |
| } |
| |
| /** |
| * @return {@code true} if the given string is null or empty. |
| */ |
| public static boolean isEmpty(String val) { |
| return val == null || val.isEmpty(); |
| } |
| |
| public static boolean isNotEmpty(String val) { |
| return !isEmpty(val); |
| } |
| |
| /** |
| * <p>Checks if a CharSequence is whitespace, empty ("") or null.</p> |
| * |
| * <pre> |
| * StringUtils.isBlank(null) = true |
| * StringUtils.isBlank("") = true |
| * StringUtils.isBlank(" ") = true |
| * StringUtils.isBlank("bob") = false |
| * StringUtils.isBlank(" bob ") = false |
| * </pre> |
| * |
| * Ported over from Apache commons-lang3 |
| * |
| * @param cs the CharSequence to check, may be null |
| * @return {@code true} if the CharSequence is null, empty or whitespace |
| */ |
| public static boolean isBlank(final CharSequence cs) { |
| int strLen; |
| if (cs == null || (strLen = cs.length()) == 0) { |
| return true; |
| } |
| for (int i = 0; i < strLen; i++) { |
| if (Character.isWhitespace(cs.charAt(i)) == false) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p> |
| * |
| * <pre> |
| * StringUtils.isNotBlank(null) = false |
| * StringUtils.isNotBlank("") = false |
| * StringUtils.isNotBlank(" ") = false |
| * StringUtils.isNotBlank("bob") = true |
| * StringUtils.isNotBlank(" bob ") = true |
| * </pre> |
| * |
| * Ported over from Apache commons-lang3 |
| * |
| * @param cs the CharSequence to check, may be null |
| * @return {@code true} if the CharSequence is not empty and not null and not whitespace |
| */ |
| public static boolean isNotBlank(final CharSequence cs) { |
| return !isBlank(cs); |
| } |
| |
| |
| /** |
| * @param val the string to search in |
| * @param charToSearchFor the character to search for |
| * @return {@code true} if the charToSearchFor is contained in the String val |
| */ |
| public static boolean contains(String val, char charToSearchFor) { |
| return val != null && val.indexOf(charToSearchFor) > -1; |
| } |
| |
| |
| public static boolean equalsIgnoreCase(String str1, String str2) { |
| if (str1 == null || str2 == null) { |
| return str1 == str2; |
| } |
| else if (str1 == str2) { |
| return true; |
| } |
| |
| return str1.equalsIgnoreCase(str2); |
| } |
| |
| /** |
| * Splits the given string on the given token. Follows the semantics |
| * of the Java 1.4 {@link String#split(String, int)} method, but does |
| * not treat the given token as a regular expression. |
| */ |
| public static String[] split(String str, String token, int max) { |
| if (str == null || str.length() == 0) { |
| return EMPTY_STRING_ARRAY; |
| } |
| if (token == null || token.length() == 0) { |
| throw new IllegalArgumentException("token: [" + token + "]"); |
| } |
| |
| // split on token |
| List<String> ret = new ArrayList<>(); |
| int start = 0; |
| int len = str.length(); |
| int tlen = token.length(); |
| |
| int pos = 0; |
| while (pos != -1) { |
| pos = str.indexOf(token, start); |
| if (pos != -1) { |
| ret.add(str.substring(start, pos)); |
| start = pos + tlen; |
| } |
| } |
| if (start < len) { |
| ret.add(str.substring(start)); |
| } |
| else if (start == len) { |
| ret.add(""); |
| } |
| |
| |
| // now take max into account; this isn't the most efficient way |
| // of doing things since we split the maximum number of times |
| // regardless of the given parameters, but it makes things easy |
| if (max == 0) { |
| int size = ret.size(); |
| // discard any trailing empty splits |
| while (ret.get(--size).isEmpty()) { |
| ret.remove(size); |
| } |
| } |
| else if (max > 0 && ret.size() > max) { |
| // move all splits over max into the last split |
| StringBuilder sb = new StringBuilder(256); |
| sb.append(ret.get(max - 1)); |
| ret.remove(max - 1); |
| while (ret.size() >= max) { |
| sb.append(token).append(ret.get(max - 1)); |
| ret.remove(max - 1); |
| } |
| ret.add(sb.toString()); |
| } |
| return ret.toArray(new String[ret.size()]); |
| } |
| |
| /** |
| * Replace all instances of <code>from</code> in <code>str</code> |
| * with <code>to</code>. |
| * |
| * @param str the candidate string to replace |
| * @param from the token to replace |
| * @param to the new token |
| * @return the string with all the replacements made |
| */ |
| public static String replace(String str, String from, String to) { |
| if (from.equals(to)) { |
| return str; |
| } |
| String[] split = split(str, from, Integer.MAX_VALUE); |
| return join(split, to); |
| } |
| |
| |
| /** |
| * Null-safe {@link String#trim()} |
| */ |
| public static String trim(final String str) { |
| return str == null ? null : str.trim(); |
| } |
| |
| /** |
| * @return the trimmed string str or {@code null} if the trimmed string would be empty. |
| */ |
| public static String trimToNull(String str) { |
| if (str == null || str.isEmpty()) { |
| return null; |
| } |
| str = str.trim(); |
| if (str.isEmpty()) { |
| return null; |
| } |
| return str; |
| } |
| |
| public static String join(Object[] values, String joinToken) { |
| if (values == null) { |
| return null; |
| } |
| if (values.length == 0) { |
| return ""; |
| } |
| if (values.length == 1) { |
| return values[0].toString(); |
| } |
| if (joinToken == null) { |
| joinToken = "null"; // backward compat with commons-lang StringUtils... |
| } |
| |
| StringBuilder sb = new StringBuilder(values.length * (16 + joinToken.length())); |
| sb.append(values[0]); |
| for (int i = 1; i < values.length; i++) { |
| sb.append(joinToken).append(values[i]); |
| } |
| return sb.toString(); |
| } |
| |
| |
| |
| /** |
| * Parse the given |
| * |
| * @param val value to parse |
| * @param type the target type of the the parsed value |
| * @return the converted value |
| */ |
| public static <T> T parse(String val, Class<T> type) { |
| if (type == null) { |
| throw new NullPointerException("target type must not be null"); |
| } |
| |
| // handle primitives |
| if (type == byte.class) { |
| return (T) (val == null ? BYTE_ZERO : Byte.valueOf(val)); |
| } |
| if (type == char.class) { |
| return (T) (val == null ? CHAR_ZERO : parseCharString(val)); |
| } |
| if (type == double.class) { |
| return (T) (val == null ? DOUBLE_ZERO : Double.valueOf(val)); |
| } |
| if (type == float.class) { |
| return (T) (val == null ? FLOAT_ZERO : Float.valueOf(val)); |
| } |
| if (type == int.class) { |
| return (T) (val == null ? INTEGER_ZERO : Integer.valueOf(val)); |
| } |
| if (type == long.class) { |
| return (T) (val == null ? LONG_ZERO : Long.valueOf(val)); |
| } |
| if (type == short.class) { |
| return (T) (val == null ? SHORT_ZERO : Short.valueOf(val)); |
| } |
| if (type == boolean.class) { |
| return (T) (val == null ? Boolean.FALSE : Boolean.valueOf(val)); |
| } |
| if (type == void.class) { |
| throw new IllegalStateException("Cannot parse void type"); |
| } |
| |
| // handle wrapper types |
| if (type == Byte.class) { |
| return (T) (val == null ? null : Byte.valueOf(val)); |
| } |
| if (type == Character.class) { |
| return (T) (val == null ? null : parseCharString(val)); |
| } |
| if (type == Double.class) { |
| return (T) (val == null ? null : Double.valueOf(val)); |
| } |
| if (type == Float.class) { |
| return (T) (val == null ? null : Float.valueOf(val)); |
| } |
| if (type == Integer.class) { |
| return (T) (val == null ? null : Integer.valueOf(val)); |
| } |
| if (type == Long.class) { |
| return (T) (val == null ? null : Long.valueOf(val)); |
| } |
| if (type == Short.class) { |
| return (T) (val == null ? null : Short.valueOf(val)); |
| } |
| if (type == Boolean.class) { |
| return (T) (val == null ? null : Boolean.valueOf(val)); |
| } |
| |
| throw new IllegalArgumentException("Unsupported type: " + type.getCanonicalName()); |
| } |
| |
| /** |
| * <p>Capitalizes a String changing the first letter to title case as |
| * per {@link Character#toTitleCase(char)}. No other letters are changed.</p> |
| * |
| * |
| * <pre> |
| * StringUtil.capitalize(null) = null |
| * StringUtil.capitalize("") = "" |
| * StringUtil.capitalize("cat") = "Cat" |
| * StringUtil.capitalize("cAt") = "CAt" |
| * </pre> |
| * |
| * Ported over from Apache commons-lang3 |
| * |
| * @param str the String to capitalize, may be null |
| * @return the capitalized String, {@code null} if null String input |
| * @see #uncapitalize(String) |
| */ |
| public static String capitalize(final String str) { |
| int strLen; |
| if (str == null || (strLen = str.length()) == 0) { |
| return str; |
| } |
| |
| final char firstChar = str.charAt(0); |
| if (Character.isTitleCase(firstChar)) { |
| // already capitalized |
| return str; |
| } |
| |
| return new StringBuilder(strLen) |
| .append(Character.toTitleCase(firstChar)) |
| .append(str.substring(1)) |
| .toString(); |
| } |
| |
| /** |
| * <p>Uncapitalizes a String changing the first letter to title case as |
| * per {@link Character#toLowerCase(char)}. No other letters are changed.</p> |
| * |
| * <pre> |
| * StringUtil.uncapitalize(null) = null |
| * StringUtil.uncapitalize("") = "" |
| * StringUtil.uncapitalize("Cat") = "cat" |
| * StringUtil.uncapitalize("CAT") = "cAT" |
| * </pre> |
| * |
| * Ported over from Apache commons-lang3 |
| * |
| * @param str the String to uncapitalize, may be null |
| * @return the uncapitalized String, {@code null} if null String input |
| * @see #capitalize(String) |
| */ |
| public static String uncapitalize(final String str) { |
| int strLen; |
| if (str == null || (strLen = str.length()) == 0) { |
| return str; |
| } |
| |
| final char firstChar = str.charAt(0); |
| if (Character.isLowerCase(firstChar)) { |
| // already uncapitalized |
| return str; |
| } |
| |
| return new StringBuilder(strLen) |
| .append(Character.toLowerCase(firstChar)) |
| .append(str.substring(1)) |
| .toString(); |
| } |
| |
| public static boolean endsWithIgnoreCase(String str, String suffix) { |
| if (str == null || suffix == null) { |
| return str == null && suffix == null; |
| } |
| int strlen = str.length(); |
| if (suffix.length() > strlen) { |
| return false; |
| } |
| |
| return str.substring(str.length() - suffix.length(), strlen).equalsIgnoreCase(suffix); |
| } |
| |
| |
| /** |
| * <p>Strips any of a set of characters from the end of a String.</p> |
| * |
| * <p>A {@code null} input String returns {@code null}. |
| * An empty string ("") input returns the empty string.</p> |
| * |
| * <p>If the stripChars String is {@code null}, whitespace is |
| * stripped as defined by {@link Character#isWhitespace(char)}.</p> |
| * |
| * <pre> |
| * StringUtils.stripEnd(null, *) = null |
| * StringUtils.stripEnd("", *) = "" |
| * StringUtils.stripEnd("abc", "") = "abc" |
| * StringUtils.stripEnd("abc", null) = "abc" |
| * StringUtils.stripEnd(" abc", null) = " abc" |
| * StringUtils.stripEnd("abc ", null) = "abc" |
| * StringUtils.stripEnd(" abc ", null) = " abc" |
| * StringUtils.stripEnd(" abcyx", "xyz") = " abc" |
| * StringUtils.stripEnd("120.00", ".0") = "12" |
| * </pre> |
| * |
| * Ported over from Apache commons-lang3 |
| * |
| * @param str the String to remove characters from, may be null |
| * @param stripChars the set of characters to remove, null treated as whitespace |
| * @return the stripped String, {@code null} if null String input |
| */ |
| public static String stripEnd(final String str, final String stripChars) { |
| int end; |
| if (str == null || (end = str.length()) == 0) { |
| return str; |
| } |
| |
| if (stripChars == null) { |
| while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) { |
| end--; |
| } |
| } else if (stripChars.isEmpty()) { |
| return str; |
| } else { |
| while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != -1) { |
| end--; |
| } |
| } |
| return str.substring(0, end); |
| } |
| |
| |
| |
| private static Character parseCharString(String val) { |
| if (val.length() == 0) { |
| return Character.valueOf((char) 0); |
| } |
| if (val.length() == 1) { |
| return val.charAt(0); |
| } |
| throw new IllegalArgumentException("'" + val + "' is longer than one character."); |
| } |
| |
| } |