/*
* 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 net.sf.fast.ibatis.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Class with string utilities.
*/
public final class StringUtils {
private static final Pattern SPLIT_PATTERN = Pattern.compile("([A-Z]+)");
private static final Pattern PREFIX_PATTERN = Pattern.compile("[^A-Z][\\sA-Z]");
/**
* Converts first char to lower.
*
* @param string the input string
* @return the modified string
*/
public static String firstToLower(String string) {
if (string == null || string.length() == 0) {
return "";
}
else if (string.length() == 1) {
return string.toLowerCase();
}
return string.substring(0, 1).toLowerCase() + string.substring(1);
}
/**
* Converts first to upper.
*
* @param string the input string
* @return the modified string
*/
public static String firstToUpper(String string) {
if (string == null || string.length() == 0) {
return "";
}
else if (string.length() == 1) {
return string.toUpperCase();
}
return string.substring(0, 1).toUpperCase() + string.substring(1);
}
/**
* Split string, where characters change from lower to upper case.
* All characters will be changed to lower case, despite of the
* first and sequences with more then one upper case letter.
* Example: getIDFromProdukt => get ID from produkt
*
* @param string the input string
* @return the modified string
*/
public static String split(String string) {
String[] strings = splitByUpperCase(string);
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < strings.length; ++i) {
if (i > 0) {
buffer.append(" ");
}
buffer.append(strings[i]);
}
return buffer.toString();
}
/**
* Split string, where characters change from lower to upper case.
* All characters will be changed to lower case, despite of the
* first and sequences with more then one upper case letter.
* Example: getIDFromProdukt => get ID from produkt
*
* @param string the input string
* @return the resulting string array
*/
public static String[] splitByUpperCase(String string) {
Matcher matcher = SPLIT_PATTERN.matcher(string); // "([A-Z]+)"
int start = 0;
List<String> list = new ArrayList<String>();
while (matcher.find()) {
// change from lower to upper case -> append up to last lower case letter
if (start < matcher.start()) {
list.addAll(Arrays.asList(splitBySpace(string.substring(start, matcher.start()))));
}
// only one upper case letter?
if (matcher.group(1).length() == 1) {
// yes -> use as start of next string
start = matcher.start();
continue;
}
// more then one upper case letter
if (matcher.end(1) < string.length()) {
// not at end of string -> append n-1 letters
list.addAll(Arrays.asList(splitBySpace(string.substring(matcher.start(), matcher.end(1) - 1))));
start = matcher.end(1) - 1;
}
else {
// upper case letters up to end of string -> append all
list.addAll(Arrays.asList(splitBySpace(string.substring(matcher.start()))));
start = string.length();
}
}
// and the rest...
if (start < string.length()) {
list.addAll(Arrays.asList(splitBySpace(string.substring(start))));
}
return (String[])list.toArray(new String[list.size()]);
}
/**
* Splits the given string by space.
*
* @param string the string
* @return the resulting string array
*/
public static String[] splitBySpace(String string) {
return string.split("\\s");
}
/**
* Checks for spaces in the given string.
*
* @param string the string
* @return true, if spaces exists
*/
public static boolean hasSpaces(String string) {
return string.indexOf(' ') >= 0;
}
/**
* Puts all strings to lower case.
*
* @param strings the strings
* @param includeFirst false, if the first string should not be modified
* @return the resulting string array
*/
public static String[] allToLower(String[] strings, boolean includeFirst) {
int start = includeFirst ? 0 : 1;
for (int i = start; i < strings.length; ++i) {
strings[i] = strings[i].toLowerCase();
}
return strings;
}
/**
* Gets the substring up to the first upper case letter.
*
* @param string the string
* @return the prefix
*/
public static String getPrefix(String string) {
Matcher matcher = PREFIX_PATTERN.matcher(string); // "[^A-Z][\sA-Z]"
int start = 0;
String prefix = null;
if (matcher.find()) {
start = matcher.start() + 1;
prefix = string.substring(0, start).trim();
}
return prefix;
}
/**
* Gets the last element of the given path.
*
* @param path the path
* @param separator the element separator
* @return the last element
*/
public static String getLastElement(String path, char separator) {
int index = path.lastIndexOf(separator);
if (index < 0) {
return path;
}
if (index >= path.length() - 1) {
return "";
}
return path.substring(index + 1);
}
/**
* Checks, if the string starts with the given regular expression.
* String.startsWith() does not work with regular expressions.
*
* @param string the string
* @param regexp the regular expression
* @return true, if starts with
*/
public static boolean startsWith(String string, String regexp) {
return Pattern.compile("^" + regexp).matcher(string).find();
}
/**
* Returns empty string in case of null.
*
* @param string the string
* @return the string
*/
public static String checkNull(String string) {
return string == null ? "" : string;
}
/**
* Infer the indentation level based on the given reference indentation
* and tab size.
*
* @param tabSize the tab size
* @param reference the reference indentation
* @return the inferred indentation level
*/
public static int inferIndentationLevel(String reference, int tabSize) {
StringBuffer expanded = new StringBuffer(StringUtils.expandTabs(reference, tabSize));
int referenceWidth = expanded.length();
if (tabSize == 0) {
return referenceWidth;
}
int spaceWidth= 1;
int level = referenceWidth / (tabSize * spaceWidth);
if (referenceWidth % (tabSize * spaceWidth) > 0) {
level++;
}
return level;
}
/**
* Expands the given string's tabs according to the given tab size.
*
* @param string the string
* @param tabSize the tab size
* @return the expanded string
*/
public static String expandTabs(String string, int tabSize) {
StringBuffer expanded = new StringBuffer();
for (int i = 0, n = string.length(), chars = 0; i < n; i++) {
char ch = string.charAt(i);
if (ch == '\t') {
for (; chars < tabSize; chars++) {
expanded.append(' ');
}
chars = 0;
} else {
expanded.append(ch);
chars++;
if (chars >= tabSize) {
chars = 0;
}
}
}
return expanded.toString();
}
}