package com.taobao.tddl.common.utils;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
/**
* TDDL专用的字符处理便捷类,集成了apache common StringUtils类,方便字符串处理
*
* @author linxuan
* @author jianghang 2013-10-24 下午4:02:24
* @since 5.0.0
*/
public class TStringUtil extends StringUtils {
/**
* 获得第一个start,end之间的字串, 不包括start,end本身。返回值已做了trim
*
* <pre>
* TStringUtil.getBetween("wx[ b ]yz", "[", "]") = "b"
* TStringUtil.getBetween(null, *, *) = null
* TStringUtil.getBetween(*, null, *) = null
* TStringUtil.getBetween(*, *, null) = null
* TStringUtil.getBetween("", "", "") = ""
* TStringUtil.getBetween("", "", "]") = null
* TStringUtil.getBetween("", "[", "]") = null
* TStringUtil.getBetween("yabcz", "", "") = ""
* TStringUtil.getBetween("yabcz", "y", "z") = "abc"
* TStringUtil.getBetween("yabczyabcz", "y", "z") = "abc"
* </pre>
*/
public static String getBetween(String sql, String start, String end) {
if (sql == null || start == null || end == null) {
return null;
}
int index0 = sql.indexOf(start);
if (index0 == -1) {
return null;
}
int index1 = sql.indexOf(end, index0);
if (index1 == -1) {
return null;
}
return sql.substring(index0 + start.length(), index1).trim();
}
/**
* 去除第一个start,end之间的字符串,包括start,end本身
*
* <pre>
* TStringUtil.removeBetween("abc[xxx]bc", "[", "]") = "abc bc"
* </pre>
*
* @param sql
* @param start
* @param end
* @return
*/
public static String removeBetween(String sql, String start, String end) {
if (sql == null) {
return null;
}
if (start == null || end == null) {
return sql;
}
int index0 = sql.indexOf(start);
if (index0 == -1) {
return sql;
}
int index1 = sql.indexOf(end, index0);
if (index1 == -1) {
return sql;
}
StringBuilder sb = new StringBuilder();
sb.append(sql.substring(0, index0));
sb.append(" ");
sb.append(sql.substring(index1 + end.length()));
return sb.toString();
}
/**
* 只做一次切分
*
* <pre>
* TStringUtil.twoPartSplit("abc:bc:bc", ":") = ["abc","bc:bc"]
* TStringUtil.twoPartSplit(null, *) = [null]
* TStringUtil.twoPartSplit("abc:bc", null) = ["abc:bc"]
* TStringUtil.twoPartSplit("abc:bc", ";") = ["abc:bc:bc"]
* </pre>
*
* @param str
* @param splitor
* @return
*/
public static String[] twoPartSplit(String str, String splitor) {
if (str != null && splitor != null) {
int index = str.indexOf(splitor);
if (index != -1) {
String first = str.substring(0, index);
String sec = str.substring(index + splitor.length());
return new String[] { first, sec };
} else {
return new String[] { str };
}
} else {
return new String[] { str };
}
}
/**
* 递归调用twoPartSplit进行切分
*
* <pre>
* TStringUtil.twoPartSplit("abc:bc:bc", ":") = ["abc","bc","bc"]
* TStringUtil.twoPartSplit(null, *) = [null]
* TStringUtil.twoPartSplit("abc:bc", null) = ["abc:bc"]
* TStringUtil.twoPartSplit("abc:bc", ";") = ["abc:bc"]
* </pre>
*
* @param str
* @param splitor
* @return
*/
public static List<String> recursiveSplit(String str, String splitor) {
List<String> re = new ArrayList<String>();
String[] strs = twoPartSplit(str, splitor);
if (strs.length == 2) {
re.add(strs[0]);
re.addAll(recursiveSplit(strs[1], splitor));
} else {
re.add(strs[0]);
}
return re;
}
/**
* 将所有/t/s/n等空白符全部替换为空格,并且去除多余空白
*
* <pre>
* TStringUtil.fillTabWithSpace("abc bc ") = "abc bc "
* </pre>
*/
public static String fillTabWithSpace(String str) {
if (str == null) {
return null;
}
str = str.trim();
int sz = str.length();
StringBuilder buffer = new StringBuilder(sz);
int index = 0, index0 = -1, index1 = -1;
for (int i = 0; i < sz; i++) {
char c = str.charAt(i);
if (!Character.isWhitespace(c)) {
if (index0 != -1) {
// if (!(index0 == index1 && str.charAt(i - 1) == ' ')) {
if (index0 != index1 || str.charAt(i - 1) != ' ') {
buffer.append(str.substring(index, index0)).append(" ");
index = index1 + 1;
}
}
index0 = index1 = -1;
} else {
if (index0 == -1) {
index0 = index1 = i; // 第一个空白
} else {
index1 = i;
}
}
}
buffer.append(str.substring(index));
return buffer.toString();
}
/**
* Determines whether or not the sting 'searchIn' contains the string
* 'searchFor', disregarding case and leading whitespace
*
* @param searchIn the string to search in
* @param searchFor the string to search for
* @return true if the string starts with 'searchFor' ignoring whitespace
*/
public static boolean startsWithIgnoreCaseAndWs(String searchIn, String searchFor) {
return startsWithIgnoreCaseAndWs(searchIn, searchFor, 0);
}
/**
* Determines whether or not the sting 'searchIn' contains the string
* 'searchFor', disregarding case and leading whitespace
*
* @param searchIn the string to search in
* @param searchFor the string to search for
* @param beginPos where to start searching
* @return true if the string starts with 'searchFor' ignoring whitespace
*/
public static boolean startsWithIgnoreCaseAndWs(String searchIn, String searchFor, int beginPos) {
if (searchIn == null) {
return searchFor == null;
}
int inLength = searchIn.length();
for (; beginPos < inLength; beginPos++) {
if (!Character.isWhitespace(searchIn.charAt(beginPos))) {
break;
}
}
return startsWithIgnoreCase(searchIn, beginPos, searchFor);
}
/**
* Determines whether or not the string 'searchIn' contains the string
* 'searchFor', dis-regarding case starting at 'startAt' Shorthand for a
* String.regionMatch(...)
*
* @param searchIn the string to search in
* @param startAt the position to start at
* @param searchFor the string to search for
* @return whether searchIn starts with searchFor, ignoring case
*/
public static boolean startsWithIgnoreCase(String searchIn, int startAt, String searchFor) {
return searchIn.regionMatches(true, startAt, searchFor, 0, searchFor.length());
}
/**
* Returns the given string, with comments removed
*
* @param src the source string
* @param stringOpens characters which delimit the "open" of a string
* @param stringCloses characters which delimit the "close" of a string, in
* counterpart order to <code>stringOpens</code>
* @param slashStarComments strip slash-star type "C" style comments
* @param slashSlashComments strip slash-slash C++ style comments to
* end-of-line
* @param hashComments strip #-style comments to end-of-line
* @param dashDashComments strip "--" style comments to end-of-line
* @return the input string with all comment-delimited data removed
*/
public static String stripComments(String src, String stringOpens, String stringCloses, boolean slashStarComments,
boolean slashSlashComments, boolean hashComments, boolean dashDashComments) {
if (src == null) {
return null;
}
StringBuffer buf = new StringBuffer(src.length());
// It's just more natural to deal with this as a stream
// when parsing..This code is currently only called when
// parsing the kind of metadata that developers are strongly
// recommended to cache anyways, so we're not worried
// about the _1_ extra object allocation if it cleans
// up the code
StringReader sourceReader = new StringReader(src);
int contextMarker = Character.MIN_VALUE;
boolean escaped = false;
int markerTypeFound = -1;
int ind = 0;
int currentChar = 0;
try {
while ((currentChar = sourceReader.read()) != -1) {
if (currentChar == '\\') {
escaped = !escaped;
} else if (markerTypeFound != -1 && currentChar == stringCloses.charAt(markerTypeFound) && !escaped) {
contextMarker = Character.MIN_VALUE;
markerTypeFound = -1;
} else if ((ind = stringOpens.indexOf(currentChar)) != -1 && !escaped
&& contextMarker == Character.MIN_VALUE) {
markerTypeFound = ind;
contextMarker = currentChar;
}
if (contextMarker == Character.MIN_VALUE && currentChar == '/'
&& (slashSlashComments || slashStarComments)) {
currentChar = sourceReader.read();
if (currentChar == '*' && slashStarComments) {
int prevChar = 0;
while ((currentChar = sourceReader.read()) != '/' || prevChar != '*') {
if (currentChar == '\r') {
currentChar = sourceReader.read();
if (currentChar == '\n') {
currentChar = sourceReader.read();
}
} else {
if (currentChar == '\n') {
currentChar = sourceReader.read();
}
}
if (currentChar < 0) break;
prevChar = currentChar;
}
continue;
} else if (currentChar == '/' && slashSlashComments) {
while ((currentChar = sourceReader.read()) != '\n' && currentChar != '\r' && currentChar >= 0)
;
}
} else if (contextMarker == Character.MIN_VALUE && currentChar == '#' && hashComments) {
// Slurp up everything until the newline
while ((currentChar = sourceReader.read()) != '\n' && currentChar != '\r' && currentChar >= 0)
;
} else if (contextMarker == Character.MIN_VALUE && currentChar == '-' && dashDashComments) {
currentChar = sourceReader.read();
if (currentChar == -1 || currentChar != '-') {
buf.append('-');
if (currentChar != -1) {
buf.append(currentChar);
}
continue;
}
// Slurp up everything until the newline
while ((currentChar = sourceReader.read()) != '\n' && currentChar != '\r' && currentChar >= 0)
;
}
if (currentChar != -1) {
buf.append((char) currentChar);
}
}
} catch (IOException ioEx) {
// we'll never see this from a StringReader
}
return buf.toString();
}
/**
* 去除第一个start,end之间的字符串,包括start,end本身
*
* @param sql
* @param start
* @param end
* @return
*/
public static String removeBetweenWithSplitor(String sql, String start, String end) {
int index0 = sql.indexOf(start);
if (index0 == -1) {
return sql;
}
int index1 = sql.indexOf(end, index0);
if (index1 == -1) {
return sql;
}
StringBuilder sb = new StringBuilder();
sb.append(sql.substring(0, index0));
sb.append(" ");
sb.append(sql.substring(index1 + end.length()));
return sb.toString();
}
public static String removeBetweenWithSplitorNotExistNull(String sql, String start, String end) {
int index0 = sql.indexOf(start);
if (index0 == -1) {
return null;
}
int index1 = sql.indexOf(end, index0);
if (index1 == -1) {
return null;
}
StringBuilder sb = new StringBuilder();
sb.append(sql.substring(0, index0));
sb.append(" ");
sb.append(sql.substring(index1 + end.length()));
return sb.toString();
}
/**
* 简单地检查是否是逻辑表与具体子表的关系。子表名满足父表名+"_数字";
*
* @param fatherTable
* @param sonTable
* @return
*/
public static boolean isTableFatherAndSon(String fatherTable, String sonTable) {
if (fatherTable == null || fatherTable.trim().isEmpty() || sonTable == null || sonTable.trim().isEmpty()) {
return false;
}
if (!sonTable.startsWith(fatherTable) || fatherTable.length() + 2 > sonTable.length()) {
return false;
}
String suffix = sonTable.substring(fatherTable.length());
if (suffix.matches("_[\\d]+")) {
return true;
}
return false;
}
}