All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.rapiddweller.common.StringUtil Maven / Gradle / Ivy

Go to download

'rapiddweller Common' is an open source Java library forked from Databene Commons by Volker Bergmann. It provides extensions to the Java core library by utility classes, abstract concepts and concrete implementations.

There is a newer version: 2.0.1-jdk-11
Show newest version
/*
 * Copyright (C) 2004-2015 Volker Bergmann ([email protected]).
 * All rights reserved.
 *
 * 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.rapiddweller.common;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * Provides String related utility operations.
 * Created: 05.07.2006 22:45:12
 *
 * @author Volker Bergmann
 */
public final class StringUtil {

  /**
   * Bell character (BEL, 0x07)
   */
  public static final String BEL = String.valueOf((char) 7);

  /**
   * Backspace character (BS, 0x08)
   */
  public static final String BS = String.valueOf((char) 8);

  /**
   * Horizontal Tab character (HT, 0x09)
   */
  public static final String HT = String.valueOf('\t');

  /**
   * Line Feed character (LF, 0x0A)
   */
  public static final String LF = String.valueOf('\n');

  /**
   * Vertical Tab character (VT, 0x0B)
   */
  public static final String VT = String.valueOf('\u000B');

  /**
   * character (FF, 0x0C)
   */
  public static final String FF = String.valueOf('\f');

  /**
   * character (CR, 0x0D)
   */
  public static final String CR = String.valueOf('\r');


  /**
   * Short ordinal string.
   *
   * @param number the number
   * @return the string
   */
  public static String shortOrdinal(int number) {
    switch (number) {
      case 1:
        return "1st";
      case 2:
        return "2nd";
      case 3:
        return "3rd";
      default:
        return number + "th";
    }
  }

  /**
   * Tells if a String is null or isEmpty.
   *
   * @param s the string argument to check
   * @return true if the String is null or isEmpty, otherwise false.
   */
  public static boolean isEmpty(CharSequence s) {
    return s == null || s.length() == 0;
  }

  /**
   * Returns the suffix of a String. If the last character is a
   * separator, or if no separator was found, the string is assumed
   * to have no suffix.
   *
   * @param name      the String to check
   * @param separator the character that separates name from suffix
   * @return a suffix if one exists, else null.
   */
  public static String suffix(String name, char separator) {
    if (name == null) {
      return null;
    }
    int separatorIndex = name.lastIndexOf(separator);
    if (separatorIndex < 0 || separatorIndex == name.length() - 1) {
      return null;
    } else {
      return name.substring(separatorIndex + 1);
    }
  }

  /**
   * Returns the last token of a list in string representation.
   * If the string does not contain the separator, the string itself
   * is the token. If the string ends with a separator, the token is
   * null.
   *
   * @param name      the name to parse
   * @param separator the character that separates the tokens
   * @return the last token
   */
  public static String lastToken(String name, char separator) {
    if (name == null) {
      return null;
    }
    int separatorIndex = name.lastIndexOf(separator);
    if (separatorIndex < 0) {
      return name;
    } else if (separatorIndex == name.length() - 1) {
      return null;
    } else {
      return name.substring(separatorIndex + 1);
    }
  }

  /**
   * Splits a list's String representation into tokens.
   *
   * @param text      the String representation of a list.
   * @param separator the character used to separate tokens
   * @return an array of tokens.
   */
  public static String[] tokenize(String text, char separator) {
    if (text == null) {
      return null;
    }
    if (text.length() == 0) {
      return new String[] {""};
    }
    int i = 0;
    int sep;
    List list = new ArrayList<>();
    while ((sep = text.indexOf(separator, i)) >= 0) {
      if (sep == i) {
        list.add("");
        i++;
      } else {
        list.add(text.substring(i, sep));
        i = sep + 1;
      }
    }
    if (i < text.length()) {
      list.add(text.substring(i));
    } else if (text.endsWith("" + separator)) {
      list.add("");
    }
    String[] tokens = new String[list.size()];
    for (i = 0; i < tokens.length; i++) {
      tokens[i] = list.get(i);
    }
    return tokens;
  }

  /**
   * Split and trim string [ ].
   *
   * @param list      the list
   * @param separator the separator
   * @return the string [ ]
   */
  public static String[] splitAndTrim(String list, char separator) {
    return StringUtil.trimAll(split(list, separator));
  }

  /**
   * Split string [ ].
   *
   * @param list      the list
   * @param separator the separator
   * @return the string [ ]
   */
  public static String[] split(String list, char separator) {
    String separatorRegex = String.valueOf(separator);
    // nothing to do
    if (separator == '*') {
      separatorRegex = "\\" + separatorRegex; // TODO support other regex meta characters
    }
    return list.split(separatorRegex);
  }

  /**
   * Normalize string.
   *
   * @param s the s
   * @return the string
   */
  public static String normalize(String s) {
    char[] srcBuffer = new char[s.length()];
    s.getChars(0, s.length(), srcBuffer, 0);
    char[] dstBuffer = new char[s.length()];
    int dstIndex = 0;
    for (char c : srcBuffer) {
      if (c >= 16) {
        dstBuffer[dstIndex++] = c;
      }
    }
    return new String(dstBuffer, 0, dstIndex);
  }

  /**
   * Append left aligned string builder.
   *
   * @param builder the builder
   * @param text    the text
   * @param columns the columns
   * @return the string builder
   */
  public static StringBuilder appendLeftAligned(StringBuilder builder, String text, int columns) {
    builder.append(text);
    int columnsToInsert = columns - text.length();
    builder.append(" ".repeat(Math.max(0, columnsToInsert)));
    return builder;
  }

  /**
   * Increment string.
   *
   * @param text the text
   * @return the string
   */
  public static String increment(String text) {
    if (text == null || text.length() == 0) {
      return "0";
    }
    char[] chars = new char[text.length()];
    text.getChars(0, text.length(), chars, 0);
    chars = increment(chars, chars.length - 1);
    return String.valueOf(chars);
  }

  /**
   * Increment char [ ].
   *
   * @param chars the chars
   * @param index the index
   * @return the char [ ]
   */
  public static char[] increment(char[] chars, int index) {
    char c = chars[index];
    switch (c) {
      case '9':
        chars[index] = 'a';
        break;
      case 'z':
      case 'Z':
        if (index > 0) {
          chars[index] = '0';
          chars = increment(chars, index - 1);
        } else {
          char[] result = new char[chars.length + 1];
          Arrays.fill(result, '0');
          result[0] = '1';
          return result;
        }
        break;
      default:
        chars[index]++;
    }
    return chars;
  }

  /**
   * interprets an nbsp as space character
   *
   * @param c the character to check
   * @return true if the character is a whitespace, otherwise false.
   */
  public static boolean isWhitespace(char c) {
    return Character.isWhitespace(c) || c == 160;
  }

  /**
   * Trims a String by removing white spaces (including nbsp) from left and right.
   *
   * @param s the String to trim
   * @return the trimmed string
   */
  public static String trim(String s) {
    if (s == null || s.length() == 0) {
      return s;
    }
    int beginIndex;
    for (beginIndex = 0; beginIndex < s.length() && isWhitespace(s.charAt(beginIndex)); beginIndex++) {
    }
    int endIndex;
    for (endIndex = s.length() - 1; endIndex > 0 && isWhitespace(s.charAt(endIndex)); endIndex--) {
    }
    if (beginIndex > endIndex) {
      return "";
    }
    return s.substring(beginIndex, endIndex + 1);
  }

  /**
   * Trims all String in the array.
   *
   * @param array an array of the Strings to trim
   * @return the same array but with its elements trimmed
   * @since 0.2.05
   */
  public static String[] trimAll(String[] array) {
    for (int i = 0; i < array.length; i++) {
      array[i] = trim(array[i]);
    }
    return array;
  }

  /**
   * Returns the platform dependent line separator
   *
   * @return the system's line separator
   */
  public static String lineSeparator() {
    return System.getProperty("line.separator");
  }

  /**
   * Contains boolean.
   *
   * @param s the s
   * @param c the c
   * @return the boolean
   */
  public static boolean contains(String s, char c) {
    return s.indexOf(c) >= 0;
  }

  /**
   * Remove string.
   *
   * @param s     the s
   * @param chars the chars
   * @return the string
   */
  public static String remove(String s, String chars) {
    if (s == null) {
      return s;
    }
    StringBuilder result = new StringBuilder(s.length());
    for (int i = 0; i < s.length(); i++) {
      if (!(contains(chars, s.charAt(i)))) {
        result.append(s.charAt(i));
      }
    }
    return result.toString();
  }

  /**
   * Null to empty string.
   *
   * @param text the text
   * @return the string
   */
  public static String nullToEmpty(String text) {
    return (text != null ? text : "");
  }

  /**
   * Substitute null string.
   *
   * @param value        the value
   * @param substitution the substitution
   * @return the string
   */
  public static String substituteNull(String value, String substitution) {
    return (value != null ? value : substitution);
  }

  /**
   * Normalize space string.
   *
   * @param s the s
   * @return the string
   */
  public static String normalizeSpace(String s) {
    if (s == null || s.length() == 0) {
      return s;
    }
    s = trim(s);
    if (s.length() == 0) {
      return s;
    }
    char lastChar = s.charAt(0);
    StringBuilder result = new StringBuilder().append(lastChar);
    for (int i = 1; i < s.length(); i++) {
      char c = s.charAt(i);
      if (!isWhitespace(c)) {
        result.append(c);
      } else if (!(isWhitespace(lastChar))) {
        result.append(' ');
      }
      lastChar = c;
    }
    return result.toString();
  }

  /**
   * Trim end string.
   *
   * @param s the s
   * @return the string
   */
  public static String trimEnd(String s) {
    if (s == null || s.length() == 0) {
      return s;
    }
    int lastIndex = s.length() - 1;
    while (lastIndex >= 0 && isWhitespace(s.charAt(lastIndex))) {
      lastIndex--;
    }
    if (lastIndex < 0) {
      return "";
    }
    return s.substring(0, lastIndex + 1);
  }

  /**
   * Count chars int.
   *
   * @param s the s
   * @param c the c
   * @return the int
   */
  public static int countChars(String s, char c) {
    int count = 0;
    for (int i = 0; i < s.length(); i++) {
      if (s.charAt(i) == c) {
        count++;
      }
    }
    return count;
  }

  /**
   * To array string [ ].
   *
   * @param list the list
   * @return the string [ ]
   */
  public static String[] toArray(List list) {
    String[] result = new String[list.size()];
    for (int i = 0; i < list.size(); i++) {
      result[i] = list.get(i);
    }
    return result;
  }

  /**
   * To array array string [ ] [ ].
   *
   * @param list the list
   * @return the string [ ] [ ]
   */
  public static String[][] toArrayArray(List> list) {
    String[][] result = new String[list.size()][];
    for (int i = 0; i < list.size(); i++) {
      result[i] = toArray(list.get(i));
    }
    return result;
  }

  /**
   * Pad left string.
   *
   * @param text   the text
   * @param length the length
   * @param c      the c
   * @return the string
   */
  public static String padLeft(String text, int length, char c) {
    if (text == null) {
      text = "";
    }
    int textLength = text.length();
    if (textLength > length) {
      throw new IllegalArgumentException("Text is too long (" + textLength + ") to be padded to " + length + " columns");
    }
    char[] chars = new char[length];
    int offset = length - textLength;
    fill(chars, 0, offset, c);
    getChars(0, textLength, text, chars, offset);
    return new String(chars);
  }

  /**
   * Pad right string.
   *
   * @param text   the text
   * @param length the length
   * @param c      the c
   * @return the string
   */
  public static String padRight(String text, int length, char c) {
    if (text == null) {
      text = "";
    }
    int textLength = text.length();
    if (textLength > length) {
      throw new IllegalArgumentException("Text is too long (" + textLength + ") to be padded to " + length + " columns");
    }
    char[] chars = new char[length];
    fill(chars, textLength, length, c);
    getChars(0, textLength, text, chars, 0);
    return new String(chars);
/*
        int textLength = text.length();
        if (textLength > length)
            throw new IllegalArgumentException("Text is too long (" + textLength + ") to be padded to " + length + " columns");
        int padLength = length - textLength;
        char[] padChars = new char[padLength];
        if (padLength < 20) {
            for (int i = 0; i < padLength; i++)
                padChars[i] = c;
        } else if (c == ' ' && padLength <= WHITESPACE_BUFFER.length) {
            System.arraycopy(WHITESPACE_BUFFER, 0, padChars, 0, padLength);
        } else {
            Arrays.fill(padChars, 0, padLength, c);
        }
        return text.concat(new String(padChars));
*/
  }

  private static final int BUFFER_SIZE = 1024;
  private static final char[] WHITESPACE_BUFFER;

  static {
    WHITESPACE_BUFFER = new char[BUFFER_SIZE];
    Arrays.fill(WHITESPACE_BUFFER, ' ');
  }

  /**
   * Fill char [ ].
   *
   * @param chars     the chars
   * @param fromIndex the from index
   * @param toIndex   the to index
   * @param c         the c
   * @return the char [ ]
   */
  public static char[] fill(char[] chars, int fromIndex, int toIndex, char c) {
    int length = toIndex - fromIndex;
    if (length < 20) {
      for (int i = fromIndex; i < toIndex; i++) {
        chars[i] = c;
      }
    } else if (c != ' ' || length > WHITESPACE_BUFFER.length) {
      Arrays.fill(chars, fromIndex, toIndex, c);
    } else {
      System.arraycopy(WHITESPACE_BUFFER, 0, chars, fromIndex, length);
    }
    return chars;
  }

  /**
   * Get chars char [ ].
   *
   * @param srcBegin the src begin
   * @param srcEnd   the src end
   * @param text     the text
   * @param chars    the chars
   * @param dstBegin the dst begin
   * @return the char [ ]
   */
  public static char[] getChars(int srcBegin, int srcEnd, String text, char[] chars, int dstBegin) {
    int textLength = text.length();
    if (textLength >= 6) {
      text.getChars(srcBegin, srcEnd, chars, dstBegin);
    } else {
      for (int i = 0; i < textLength; i++) {
        chars[i + dstBegin] = text.charAt(i);
      }
    }
    return chars;
  }

  /**
   * Get chars char [ ].
   *
   * @param s the s
   * @return the char [ ]
   */
  public static char[] getChars(String s) {
    char[] chars = new char[s.length()];
    return getChars(0, chars.length, s, chars, 0);
  }

  /**
   * Get chars char [ ].
   *
   * @param builder the builder
   * @return the char [ ]
   */
  public static char[] getChars(StringBuilder builder) {
    char[] chars = new char[builder.length()];
    builder.getChars(0, builder.length(), chars, 0);
    return chars;
  }

  /**
   * Pad string string.
   *
   * @param c      the c
   * @param length the length
   * @return the string
   */
  public static String padString(char c, int length) {
    if (length < 0) {
      throw new IllegalArgumentException("Negative pad length: " + length);
    }
    char[] chars = new char[length];
    Arrays.fill(chars, 0, length, c);
    return new String(chars);
  }

  /**
   * Trim right string.
   *
   * @param source the source
   * @return the string
   */
  public static String trimRight(String source) {
    if (source == null) {
      return null;
    }
    int i = source.length() - 1;
    while (i >= 0 && isWhitespace(source.charAt(i))) {
      i--;
    }
    return source.substring(0, i + 1);
  }

  /**
   * Trim right string.
   *
   * @param source  the source
   * @param padChar the pad char
   * @return the string
   */
  public static String trimRight(String source, char padChar) {
    if (source == null) {
      return null;
    }
    int i = source.length() - 1;
    while (i >= 0 && source.charAt(i) == padChar) {
      i--;
    }
    return source.substring(0, i + 1);
  }

  /**
   * Trim left string.
   *
   * @param source  the source
   * @param padChar the pad char
   * @return the string
   */
  public static String trimLeft(String source, char padChar) {
    if (source == null) {
      return null;
    }
    int i = 0;
    while (i < source.length() && source.charAt(i) == padChar) {
      i++;
    }
    return source.substring(i);
  }

  /**
   * Trim string.
   *
   * @param source  the source
   * @param padChar the pad char
   * @return the string
   */
  public static String trim(String source, char padChar) {
    if (source == null) {
      return null;
    }
    int i0 = 0;
    while (i0 < source.length() && source.charAt(i0) == padChar) {
      i0++;
    }
    if (i0 == source.length()) {
      return "";
    }
    int i1 = source.length() - 1;
    while (i1 > i0 && source.charAt(i1) == padChar) {
      i1--;
    }
    return source.substring(i0, i1 + 1);
  }

  /**
   * To lower case string [ ].
   *
   * @param src the src
   * @return the string [ ]
   */
  public static String[] toLowerCase(String[] src) {
    String[] dst = new String[src.length];
    for (int i = 0; i < src.length; i++) {
      dst[i] = src[i].toLowerCase();
    }
    return dst;
  }

  /**
   * Index of ignore case int.
   *
   * @param searched   the searched
   * @param candidates the candidates
   * @return the int
   */
  public static int indexOfIgnoreCase(String searched, String... candidates) {
    for (int i = 0; i < candidates.length; i++) {
      if (searched.equalsIgnoreCase(candidates[i])) {
        return i;
      }
    }
    return -1;
  }

  /**
   * Last char char.
   *
   * @param word the word
   * @return the char
   */
  public static char lastChar(String word) {
    return word.charAt(word.length() - 1);
  }

  /**
   * Makes the first character of a String uppercase.
   *
   * @param text the text to convert
   * @return a text that starts with a uppercase letter
   */
  public static String capitalize(String text) {
    return text.substring(0, 1).toUpperCase() + text.substring(1);
  }

  /**
   * Makes the first character of a String lowercase.
   *
   * @param text the text to convert
   * @return a text that starts with a lowercase letter
   * @since 0.2.04
   */
  public static String uncapitalize(String text) {
    return text.substring(0, 1).toLowerCase() + text.substring(1);
  }

  /**
   * Split on first separator string [ ].
   *
   * @param path      the path
   * @param separator the separator
   * @return the string [ ]
   */
  public static String[] splitOnFirstSeparator(String path, char separator) {
    if (path == null) {
      return new String[] {null, null};
    }
    if (path.indexOf(separator) < 0) {
      return new String[] {path, null};
    }
    int sepIndex = path.indexOf(separator);
    return splitAroundSeparator(path, sepIndex);
  }

  /**
   * Split on last separator string [ ].
   *
   * @param path      the path
   * @param separator the separator
   * @return the string [ ]
   */
  public static String[] splitOnLastSeparator(String path, char separator) {
    if (path == null) {
      return new String[] {null, null};
    }
    int sepIndex = path.lastIndexOf(separator);
    return splitAroundSeparator(path, sepIndex);
  }

  /**
   * Split around separator string [ ].
   *
   * @param path     the path
   * @param sepIndex the sep index
   * @return the string [ ]
   */
  public static String[] splitAroundSeparator(String path, int sepIndex) {
    if (sepIndex < 0) {
      return new String[] {null, path};
    } else if (sepIndex == 0) {
      return new String[] {"", path.substring(1)};
    } else if (sepIndex == path.length() - 1) {
      return new String[] {path.substring(0, path.length() - 1), ""};
    } else {
      return new String[] {path.substring(0, sepIndex), path.substring(sepIndex + 1)};
    }
  }

  /**
   * Concat string.
   *
   * @param separator the separator
   * @param parts     the parts
   * @return the string
   */
  public static String concat(Character separator, String... parts) {
    if (parts == null) {
      return "";
    }
    StringBuilder builder = new StringBuilder();
    for (String part : parts) {
      if (!isEmpty(part)) {
        if (builder.length() > 0 && separator != null) {
          builder.append(separator);
        }
        builder.append(part);
      }
    }
    return builder.toString();
  }

  /**
   * Equals ignore case boolean.
   *
   * @param s1 the s 1
   * @param s2 the s 2
   * @return the boolean
   */
  public static boolean equalsIgnoreCase(String s1, String s2) {
    return (s1 != null ? s1.equalsIgnoreCase(s2) : s2 == null);
  }

  /**
   * Equals ignore case boolean.
   *
   * @param a1 the a 1
   * @param a2 the a 2
   * @return the boolean
   */
  public static boolean equalsIgnoreCase(String[] a1, String[] a2) {
    if (a1.length != a2.length) {
      return false;
    }
    for (int i = 0; i < a1.length; i++) {
      if (!equalsIgnoreCase(a1[i], a2[i])) {
        return false;
      }
    }
    return true;
  }

  /**
   * Equals ignore case boolean.
   *
   * @param set1 the set 1
   * @param set2 the set 2
   * @return the boolean
   */
  public static boolean equalsIgnoreCase(Set set1, Set set2) {
    if (set1.size() != set2.size()) {
      return false;
    }
    for (String s1 : set1) {
      boolean found = false;
      for (String s2 : set2) {
        if (equalsIgnoreCase(s1, s2)) {
          found = true;
        }
      }
      if (!found) {
        return false;
      }
    }
    return true;
  }

  /**
   * Contains ignore case boolean.
   *
   * @param searchedWord the searched word
   * @param words        the words
   * @return the boolean
   */
  public static boolean containsIgnoreCase(String searchedWord, Collection words) {
    for (String name : words) {
      if (name.equalsIgnoreCase(searchedWord)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Contains ignore case boolean.
   *
   * @param searchedWord the searched word
   * @param words        the words
   * @return the boolean
   */
  public static boolean containsIgnoreCase(String searchedWord, String[] words) {
    for (String name : words) {
      if (name.equalsIgnoreCase(searchedWord)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Starts with ignore case boolean.
   *
   * @param text   the text
   * @param prefix the prefix
   * @return the boolean
   */
  public static boolean startsWithIgnoreCase(String text, String prefix) {
    if (text == null) {
      return (prefix == null);
    }
    if (prefix == null) {
      return false;
    }
    return text.toLowerCase().startsWith(prefix.toLowerCase());
  }

  /**
   * Ends with ignore case boolean.
   *
   * @param text   the text
   * @param suffix the suffix
   * @return the boolean
   */
  public static boolean endsWithIgnoreCase(String text, String suffix) {
    if (text == null) {
      return (suffix == null);
    }
    if (suffix == null) {
      return false;
    }
    return text.toLowerCase().endsWith(suffix.toLowerCase());
  }

  /**
   * Normalize name string.
   *
   * @param name the name
   * @return the string
   */
  public static String normalizeName(final String name) {
    if (StringUtil.isEmpty(name)) {
      return name;
    }
    final int NONE = -1;
    final int WS = 0;
    final int SPECIAL = 1;
    final int INITIAL = 2;
    final int SUBSEQUENT = 3;
    StringBuilder builder = new StringBuilder(name.length());
    StringCharacterIterator iterator = new StringCharacterIterator(name);
    iterator.skipWhitespace();
    int prevType = NONE;
    while (iterator.hasNext()) {
      char c = iterator.next();
      int type;
      if (Character.isWhitespace(c)) {
        type = WS;
      } else if (!Character.isLetter(c)) {
        type = SPECIAL;
      } else if (prevType == INITIAL) {
        type = SUBSEQUENT;
      } else if (prevType == NONE || prevType == WS || prevType == SPECIAL) {
        type = INITIAL;
      } else {
        type = prevType;
      }
      if (prevType == WS && (type == INITIAL || type == SPECIAL)) {
        builder.append(' ');
      }
      switch (type) {
        case INITIAL:
          builder.append(Character.toUpperCase(c));
          break;
        case SUBSEQUENT:
          builder.append(Character.toLowerCase(c));
          break;
        case SPECIAL:
          builder.append(c);
          break;
        case WS:
          break;
        default:
          throw new RuntimeException("Internal error");
      }
      prevType = type;
    }
    return builder.toString();
  }

  /**
   * Escape string.
   *
   * @param text the text
   * @return the string
   */
  public static String escape(String text) {
    return escape(text, false, false);
  }

  /**
   * Escapes a string in C/C++/Java style.
   *
   * @param text               the text to escape
   * @param escapeSingleQuotes true if single quotes shall be escaped, otherwise false
   * @param escapeDoubleQuotes true if double quotes shall be escaped, otherwise false
   * @return the escaped string
   * @see "http://en.wikipedia.org/wiki/ASCII"
   */
  public static String escape(String text, boolean escapeSingleQuotes, boolean escapeDoubleQuotes) {
    if (text == null) {
      return null;
    }
    text = text.replace("\\", "\\\\"); // keep this first, otherwise all other escapes will be doubled
    text = text.replace(BEL, "\\u0007");
    text = text.replace(BS, "\\u0008");
    text = text.replace(CR, "\\r");
    text = text.replace(LF, "\\n");
    text = text.replace(HT, "\\t");
    text = text.replace(VT, "\\u000B");
    text = text.replace(FF, "\\f");
    if (escapeSingleQuotes) {
      text = text.replace("'", "\\'");
    }
    if (escapeDoubleQuotes) {
      text = text.replace("\"", "\\\"");
    }
    return text;
  }

  /**
   * Unescapes a string in C/C++/Java style.
   *
   * @param text the text to unescape
   * @return the unescaped text
   * @see "http://en.wikipedia.org/wiki/ASCII"
   */
  public static String unescape(String text) {
    if (text == null) {
      return null;
    }
    StringBuilder builder = new StringBuilder(text.length());
    for (int i = 0; i < text.length(); i++) {
      char c = text.charAt(i);
      if (c != '\\') {
        builder.append(c);
      } else if (i < text.length() - 1) {
        c = text.charAt(++i);
        switch (c) {
          case '\'':
            builder.append('\'');
            break;
          case '"':
            builder.append('"');
            break;
          case '{':
            builder.append('{');
            break;
          case '}':
            builder.append('}');
            break;
          case 'a':
            builder.append(BEL);
            break;
          case 'b':
            builder.append(BS);
            break;
          case 'r':
            builder.append(CR);
            break;
          case 'n':
            builder.append(LF);
            break;
          case 't':
            builder.append(HT);
            break;
          case 'f':
            builder.append(FF);
            break;
          case 'u':
            long n = Long.parseLong(text.substring(i + 1, i + 5), 16);
            builder.append((char) n);
            i += 4;
            break;
          default:
            builder.append(c);
            break;
        }
      } else {
        builder.append('\\');
      }
    }
    return builder.toString();
  }

  /**
   * Replace tokens string.
   *
   * @param src    the src
   * @param token  the token
   * @param values the values
   * @return the string
   */
  public static String replaceTokens(String src, String token, String... values) {
    StringBuilder builder = new StringBuilder();
    int paramIndex = 0;
    int srcIndex = 0;
    while (srcIndex < src.length()) {
      int i = src.indexOf(token, srcIndex);
      if (i >= 0) {
        builder.append(src, srcIndex, i);
        builder.append(values[paramIndex++]);
        srcIndex = i + token.length();
      } else {
        builder.append(src.substring(srcIndex));
        break;
      }
    }
    return builder.toString();
  }

  /**
   * Empty to null string.
   *
   * @param s the s
   * @return the string
   */
  public static String emptyToNull(String s) {
    if (s == null || s.length() == 0) {
      return null;
    }
    String trimmed = trim(s);
    return (trimmed.length() != 0 ? s : null);
  }

  /**
   * Trimmed empty to null string.
   *
   * @param s the s
   * @return the string
   */
  public static String trimmedEmptyToNull(String s) {
    if (s == null || s.length() == 0) {
      return null;
    }
    String trimmed = trim(s);
    return (trimmed.length() != 0 ? trimmed : null);
  }

  /**
   * Remove section string.
   *
   * @param text      the text
   * @param beginMark the begin mark
   * @param endMark   the end mark
   * @return the string
   */
  public static String removeSection(String text, String beginMark, String endMark) {
    if (StringUtil.isEmpty(text)) {
      return text;
    }
    int beginIndex = text.indexOf(beginMark);
    int endIndex = text.indexOf(endMark);
    if (beginIndex < 0 || endIndex < 0 || beginIndex + beginMark.length() > endIndex + endMark.length()) {
      return text;
    }
    return text.substring(0, beginIndex) + text.substring(endIndex + endMark.length());
  }

  /**
   * Normalize line separators string.
   *
   * @param text          the text
   * @param lineSeparator the line separator
   * @return the string
   */
  public static String normalizeLineSeparators(String text, String lineSeparator) {
    if (StringUtil.isEmpty(text)) {
      return text;
    }
    StringBuilder builder = new StringBuilder();
    StringCharacterIterator iterator = new StringCharacterIterator(text);
    while (iterator.hasNext()) {
      char c = iterator.next();
      if (c != '\r' && c != '\n') {
        builder.append(c);
      } else {
        // swallow the \n part of of \r\n
        if (c == '\r' && iterator.hasNext()) {
          char c2 = iterator.next();
          if (c2 != '\n') // oops, it was only a \r
          {
            iterator.pushBack();
          }
        }
        builder.append(lineSeparator);
      }
    }
    return builder.toString();
  }

  /**
   * Extract string.
   *
   * @param text      the text
   * @param beginMark the begin mark
   * @param endMark   the end mark
   * @return the string
   */
  public static String extract(String text, String beginMark, String endMark) {
    int beginIndex = (beginMark != null ? text.indexOf(beginMark) + beginMark.length() : 0);
    if (endMark != null) {
      int endIndex = text.indexOf(endMark, beginIndex + 1);
      return (beginIndex >= 0 && endIndex >= 0 && endIndex > beginIndex ? text.substring(beginIndex, endIndex) : null);
    } else {
      return (beginIndex >= 0 ? text.substring(beginIndex) : null);
    }
  }

  /**
   * Build phrase string.
   *
   * @param parts the parts
   * @return the string
   */
  public static String buildPhrase(String... parts) {
    if (parts == null) {
      return "";
    }
    StringBuilder builder = new StringBuilder();
    for (String part : parts) {
      if (!StringUtil.isEmpty(part)) {
        if (builder.length() > 0) {
          builder.append(' ');
        }
        builder.append(part);
      }
    }
    return builder.toString();
  }

  /**
   * Trim line separators string.
   *
   * @param text the text
   * @return the string
   */
  public static String trimLineSeparators(String text) {
    if (text == null) {
      return null;
    }
    int start = 0;
    while (start < text.length() && isLineSeparatorChar(text.charAt(start))) {
      start++;
    }
    int end = text.length();
    while (end > 0 && (text.charAt(end - 1) == '\r' || text.charAt(end - 1) == '\n')) {
      end--;
    }
    return text.substring(start, end);
  }

  /**
   * Split lines list.
   *
   * @param text the text
   * @return the list
   */
  public static List splitLines(String text) {
    if (text == null) {
      return null;
    }
    List lines = new ArrayList<>();
    int TEXT = 0;
    int CR = 1;
    int LF = 2;
    int mode = TEXT;
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < text.length(); i++) {
      char c = text.charAt(i);
      if (c == '\r') {
        lines.add(builder.toString());
        builder.delete(0, builder.length());
        mode = CR;
      } else if (c == '\n') {
        if (mode != CR) {
          // only add a line if it is a standalone LF (no CRLF)
          lines.add(builder.toString());
          builder.delete(0, builder.length());
        }
        mode = LF;
      } else {
        mode = TEXT;
        builder.append(c);
      }
    }
    if (text.length() == 0 || mode != TEXT || builder.length() > 0) {
      lines.add(builder.toString());
    }
    return lines;
  }

  /**
   * Remove empty lines string.
   *
   * @param text the text
   * @return the string
   */
  public static String removeEmptyLines(String text) {
    if (text == null) {
      return null;
    }
    List lines = splitLines(text);
    lines.removeIf(s -> s.trim().length() == 0);
    String sep = lineSeparatorUsedIn(text);
    return ArrayFormat.format(sep, lines.toArray());
  }

  private static String lineSeparatorUsedIn(String text) {
    int i = 0;
    while (i < text.length() && !isLineSeparatorChar(text.charAt(i))) // search the first line separator char
    {
      i++;
    }
    if (i == text.length()) // if no line sep was found, then return null
    {
      return null;
    }
    char c1 = text.charAt(i);
    if (i == text.length() - 1) {
      return String.valueOf(c1); // if the found char is the last one in the string, return it, ...
    }
    char c2 = text.charAt(i + 1);  // ... otherwise check the char that follows
    if (isLineSeparatorChar(c2) && c1 != c2) {
      return "" + c1 + c2; // the line separator consists of two characters
    }
    return String.valueOf(c1);
  }

  /**
   * Is line separator char boolean.
   *
   * @param c the c
   * @return the boolean
   */
  public static boolean isLineSeparatorChar(char c) {
    return c == '\r' || c == '\n';
  }

  /**
   * Quote if not null string.
   *
   * @param text the text
   * @return the string
   */
  public static String quoteIfNotNull(String text) {
    return (text != null ? "'" + text + "'" : text);
  }

  /**
   * Gets leading whitespace.
   *
   * @param line the line
   * @return the leading whitespace
   */
  public static String getLeadingWhitespace(String line) {
    int i;
    for (i = 0; i < line.length() && Character.isWhitespace(line.charAt(i)); i++) {
      // empty iteration for index counting
    }
    return line.substring(0, i);
  }

  /**
   * Limit length string.
   *
   * @param text      the text
   * @param maxLength the max length
   * @return the string
   */
  public static String limitLength(String text, int maxLength) {
    if (text == null) {
      return null;
    } else if (text.length() <= maxLength) {
      return text;
    } else {
      return text.substring(0, maxLength);
    }
  }

  /**
   * Limit length with ellipsis string.
   *
   * @param text      the text
   * @param maxLength the max length
   * @return the string
   */
  public static String limitLengthWithEllipsis(String text, int maxLength) {
    if (text == null) {
      return null;
    } else if (text.length() <= maxLength) {
      return text;
    } else if (maxLength > 3) {
      return text.substring(0, maxLength - 3) + "...";
    } else if (maxLength == 3) {
      return text.charAt(0) + "..";
    } else if (maxLength > 0) {
      return text.substring(0, maxLength - 1) + ".";
    } else {
      return "";
    }
  }

  /**
   * Replace optional suffix string.
   *
   * @param text        the text
   * @param suffix      the suffix
   * @param replacement the replacement
   * @return the string
   */
  public static String replaceOptionalSuffix(String text, String suffix, String replacement) {
    if (text.endsWith(suffix)) {
      return text.substring(0, text.length() - suffix.length()) + replacement;
    } else {
      return text;
    }
  }

  /**
   * Remove suffix if present string.
   *
   * @param suffix the suffix
   * @param name   the name
   * @return the string
   */
  public static String removeSuffixIfPresent(String suffix, String name) {
    if (name != null && name.endsWith(suffix)) {
      return name.substring(0, name.length() - suffix.length());
    }
    return name;
  }

  /**
   * Substring after string.
   *
   * @param marker the marker
   * @param s      the s
   * @return the string
   */
  public static String substringAfter(String marker, String s) {
    int index = s.indexOf(marker);
    if (index < 0) {
      return null;
    }
    return s.substring(index + marker.length());
  }

  /**
   * Substring before string.
   *
   * @param marker the marker
   * @param s      the s
   * @return the string
   */
  public static String substringBefore(String marker, String s) {
    int index = s.indexOf(marker);
    if (index < 0) {
      return null;
    }
    return s.substring(0, index);
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy