001/*
002 *  Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
003 *  <p>
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *  <p>
008 *  http://www.apache.org/licenses/LICENSE-2.0
009 *  <p>
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package com.mybatisflex.core.util;
017
018
019import java.util.Collection;
020import java.util.function.Function;
021import java.util.regex.Pattern;
022
023public class StringUtil {
024
025    private StringUtil() {
026    }
027
028
029    /**
030     * 第一个字符转换为小写
031     *
032     * @param string
033     */
034    public static String firstCharToLowerCase(String string) {
035        char firstChar = string.charAt(0);
036        if (firstChar >= 'A' && firstChar <= 'Z') {
037            char[] arr = string.toCharArray();
038            arr[0] += ('a' - 'A');
039            return new String(arr);
040        }
041        return string;
042    }
043
044
045    /**
046     * 第一个字符转换为大写
047     *
048     * @param string
049     */
050    public static String firstCharToUpperCase(String string) {
051        char firstChar = string.charAt(0);
052        if (firstChar >= 'a' && firstChar <= 'z') {
053            char[] arr = string.toCharArray();
054            arr[0] -= ('a' - 'A');
055            return new String(arr);
056        }
057        return string;
058    }
059
060
061    /**
062     * 驼峰转下划线格式
063     *
064     * @param string
065     */
066    public static String camelToUnderline(String string) {
067        if (isBlank(string)) {
068            return "";
069        }
070        int strLen = string.length();
071        StringBuilder sb = new StringBuilder(strLen);
072        for (int i = 0; i < strLen; i++) {
073            char c = string.charAt(i);
074            if (Character.isUpperCase(c) && i > 0) {
075                sb.append('_');
076            }
077            sb.append(Character.toLowerCase(c));
078        }
079        return sb.toString();
080    }
081
082    /**
083     * 下划线转驼峰格式
084     *
085     * @param string
086     */
087    public static String underlineToCamel(String string) {
088        if (isBlank(string)) {
089            return "";
090        }
091        String temp = string.toLowerCase();
092        int strLen = temp.length();
093        StringBuilder sb = new StringBuilder(strLen);
094        for (int i = 0; i < strLen; i++) {
095            char c = temp.charAt(i);
096            if (c == '_') {
097                if (++i < strLen) {
098                    sb.append(Character.toUpperCase(temp.charAt(i)));
099                }
100            } else {
101                sb.append(c);
102            }
103        }
104        return sb.toString();
105    }
106
107
108    /**
109     * 删除字符串中的字符
110     */
111    public static String deleteChar(String string,char deleteChar) {
112        if (isBlank(string)) {
113            return "";
114        }
115        char[] chars = string.toCharArray();
116        StringBuilder sb = new StringBuilder(string.length());
117        for (char aChar : chars) {
118            if (aChar != deleteChar){
119               sb.append(aChar);
120            }
121        }
122        return sb.toString();
123    }
124
125    /**
126     * 字符串为 null 或者内部字符全部为 ' ', '\t', '\n', '\r' 这四类字符时返回 true
127     */
128    public static boolean isBlank(String str) {
129        if (str == null) {
130            return true;
131        }
132
133        for (int i = 0, len = str.length(); i < len; i++) {
134            if (str.charAt(i) > ' ') {
135                return false;
136            }
137        }
138        return true;
139    }
140
141
142    public static boolean isAnyBlank(String... strings) {
143        if (strings == null || strings.length == 0) {
144            throw new IllegalArgumentException("args is empty.");
145        }
146
147        for (String str : strings) {
148            if (isBlank(str)) {
149                return true;
150            }
151        }
152        return false;
153    }
154
155
156    public static boolean isNotBlank(String str) {
157        return !isBlank(str);
158    }
159
160
161    public static boolean areNotBlank(String... strings) {
162        return !isAnyBlank();
163    }
164
165
166    /**
167     * 这个字符串是否是全是数字
168     *
169     * @param str
170     * @return
171     */
172    public static boolean isNumeric(String str) {
173        if (isBlank(str)) {
174            return false;
175        }
176        for (int i = str.length(); --i >= 0; ) {
177            int chr = str.charAt(i);
178            if (chr < 48 || chr > 57) {
179                return false;
180            }
181        }
182        return true;
183    }
184
185
186    public static boolean startsWithAny(String str, String... prefixes) {
187        if (isBlank(str) || prefixes == null || prefixes.length == 0) {
188            return false;
189        }
190
191        for (String prefix : prefixes) {
192            if (str.startsWith(prefix)) {
193                return true;
194            }
195        }
196        return false;
197    }
198
199
200    public static boolean endsWithAny(String str, String... suffixes) {
201        if (isBlank(str) || suffixes == null || suffixes.length == 0) {
202            return false;
203        }
204
205        for (String suffix : suffixes) {
206            if (str.endsWith(suffix)) {
207                return true;
208            }
209        }
210        return false;
211    }
212
213
214    public static String trimOrNull(String string) {
215        return string != null ? string.trim() : null;
216    }
217
218
219    /**
220     * 正则匹配
221     *
222     * @param regex
223     * @param input
224     * @return
225     */
226    public static boolean matches(String regex, String input) {
227        if (null == regex || null == input) {
228            return false;
229        }
230        return Pattern.matches(regex, input);
231    }
232
233    /**
234     * 合并字符串,优化 String.join() 方法
235     *
236     * @param delimiter
237     * @param elements
238     * @return 新拼接好的字符串
239     * @see String#join(CharSequence, CharSequence...)
240     */
241    public static String join(String delimiter, CharSequence... elements) {
242        if (ArrayUtil.isEmpty(elements)) {
243            return "";
244        } else if (elements.length == 1) {
245            return String.valueOf(elements[0]);
246        } else {
247            return String.join(delimiter, elements);
248        }
249    }
250
251    /**
252     * 合并字符串,优化 String.join() 方法
253     *
254     * @param delimiter
255     * @param elements
256     * @return 新拼接好的字符串
257     * @see String#join(CharSequence, CharSequence...)
258     */
259    public static String join(String delimiter, Collection<? extends CharSequence> elements) {
260        if (CollectionUtil.isEmpty(elements)) {
261            return "";
262        } else if (elements.size() == 1) {
263            return String.valueOf(elements.iterator().next());
264        } else {
265            return String.join(delimiter, elements);
266        }
267    }
268
269
270    /**
271     * 合并字符串,优化 String.join() 方法
272     *
273     * @param delimiter
274     * @param objs
275     * @param function
276     * @param <T>
277     */
278    public static <T> String join(String delimiter, Collection<T> objs, Function<T, String> function) {
279        if (CollectionUtil.isEmpty(objs)) {
280            return "";
281        } else if (objs.size() == 1) {
282            T next = objs.iterator().next();
283            return String.valueOf(function.apply(next));
284        } else {
285            String[] strings = new String[objs.size()];
286            int index = 0;
287            for (T obj : objs) {
288                strings[index++] = function.apply(obj);
289            }
290            return String.join(delimiter, strings);
291        }
292    }
293
294    public static String buildSchemaWithTable(String schema, String tableName) {
295        return isNotBlank(schema) ? schema + "." + tableName : tableName;
296    }
297
298    public static String[] getSchemaAndTableName(String tableNameWithSchema) {
299        int index = tableNameWithSchema.indexOf(".");
300        return index <= 0 ? new String[]{null, tableNameWithSchema.trim()}
301            : new String[]{tableNameWithSchema.substring(0, index).trim(), tableNameWithSchema.substring(index + 1).trim()};
302    }
303
304    public static String[] getTableNameWithAlisa(String tableNameWithAlisa) {
305        int index = tableNameWithAlisa.indexOf(".");
306        return index <= 0 ? new String[]{tableNameWithAlisa, null}
307            : new String[]{tableNameWithAlisa.substring(0, index), tableNameWithAlisa.substring(index + 1)};
308    }
309
310    public static String tryTrim(String string) {
311        return string != null ? string.trim() : null;
312    }
313
314    public static String substringAfterLast(String text, String str) {
315        if (text == null) {
316            return null;
317        }
318        if (str == null) {
319            return text;
320        }
321        return text.substring(text.lastIndexOf(str) + 1);
322    }
323
324
325}