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[] chars = string.toCharArray();
038            chars[0] += ('a' - 'A');
039            return new String(chars);
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[] chars = string.toCharArray();
054            chars[0] -= ('a' - 'A');
055            return new String(chars);
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        if (Character.isUpperCase(string.charAt(0))) {
092            string = string.toLowerCase();
093        }
094        int strLen = string.length();
095        StringBuilder sb = new StringBuilder(strLen);
096        for (int i = 0; i < strLen; i++) {
097            char c = string.charAt(i);
098            if (c == '_') {
099                if (++i < strLen) {
100                    sb.append(Character.toUpperCase(string.charAt(i)));
101                }
102            } else {
103                sb.append(c);
104            }
105        }
106        return sb.toString();
107    }
108
109
110    /**
111     * 删除字符串中的字符
112     */
113    public static String deleteChar(String string, char deleteChar) {
114        if (isBlank(string)) {
115            return "";
116        }
117        char[] chars = string.toCharArray();
118        StringBuilder sb = new StringBuilder(string.length());
119        for (char aChar : chars) {
120            if (aChar != deleteChar) {
121                sb.append(aChar);
122            }
123        }
124        return sb.toString();
125    }
126
127    /**
128     * 字符串为 null 或者内部字符全部为 ' ', '\t', '\n', '\r' 这四类字符时返回 true
129     */
130    public static boolean isBlank(String string) {
131        if (string == null) {
132            return true;
133        }
134
135        for (int i = 0, len = string.length(); i < len; i++) {
136            if (string.charAt(i) > ' ') {
137                return false;
138            }
139        }
140        return true;
141    }
142
143
144    public static boolean isAnyBlank(String... strings) {
145        if (strings == null || strings.length == 0) {
146            throw new IllegalArgumentException("strings is null or empty.");
147        }
148
149        for (String string : strings) {
150            if (isBlank(string)) {
151                return true;
152            }
153        }
154        return false;
155    }
156
157
158    public static boolean isNotBlank(String str) {
159        return !isBlank(str);
160    }
161
162
163    public static boolean areNotBlank(String... strings) {
164        return !isAnyBlank();
165    }
166
167
168    /**
169     * 这个字符串是否是全是数字
170     *
171     * @param string
172     * @return 全部数数值时返回 true,否则返回 false
173     */
174    public static boolean isNumeric(String string) {
175        if (isBlank(string)) {
176            return false;
177        }
178        for (int i = string.length(); --i >= 0; ) {
179            int chr = string.charAt(i);
180            if (chr < 48 || chr > 57) {
181                return false;
182            }
183        }
184        return true;
185    }
186
187
188    public static boolean startsWithAny(String string, String... prefixes) {
189        if (isBlank(string) || prefixes == null) {
190            return false;
191        }
192
193        for (String prefix : prefixes) {
194            if (string.startsWith(prefix)) {
195                return true;
196            }
197        }
198        return false;
199    }
200
201
202    public static boolean endsWithAny(String str, String... suffixes) {
203        if (isBlank(str) || suffixes == null) {
204            return false;
205        }
206
207        for (String suffix : suffixes) {
208            if (str.endsWith(suffix)) {
209                return true;
210            }
211        }
212        return false;
213    }
214
215
216    /**
217     * 正则匹配
218     *
219     * @param regex
220     * @param input
221     * @return
222     */
223    public static boolean matches(String regex, String input) {
224        if (null == regex || null == input) {
225            return false;
226        }
227        return Pattern.matches(regex, input);
228    }
229
230    /**
231     * 合并字符串,优化 String.join() 方法
232     *
233     * @param delimiter
234     * @param elements
235     * @return 新拼接好的字符串
236     * @see String#join(CharSequence, CharSequence...)
237     */
238    public static String join(String delimiter, CharSequence... elements) {
239        if (ArrayUtil.isEmpty(elements)) {
240            return "";
241        } else if (elements.length == 1) {
242            return String.valueOf(elements[0]);
243        } else {
244            return String.join(delimiter, elements);
245        }
246    }
247
248    /**
249     * 合并字符串,优化 String.join() 方法
250     *
251     * @param delimiter
252     * @param elements
253     * @return 新拼接好的字符串
254     * @see String#join(CharSequence, CharSequence...)
255     */
256    public static String join(String delimiter, Collection<? extends CharSequence> elements) {
257        if (CollectionUtil.isEmpty(elements)) {
258            return "";
259        } else if (elements.size() == 1) {
260            return String.valueOf(elements.iterator().next());
261        } else {
262            return String.join(delimiter, elements);
263        }
264    }
265
266
267    /**
268     * 合并字符串,优化 String.join() 方法
269     *
270     * @param delimiter
271     * @param objs
272     * @param function
273     * @param <T>
274     */
275    public static <T> String join(String delimiter, Collection<T> objs, Function<T, String> function) {
276        if (CollectionUtil.isEmpty(objs)) {
277            return "";
278        } else if (objs.size() == 1) {
279            T next = objs.iterator().next();
280            return String.valueOf(function.apply(next));
281        } else {
282            String[] strings = new String[objs.size()];
283            int index = 0;
284            for (T obj : objs) {
285                strings[index++] = function.apply(obj);
286            }
287            return String.join(delimiter, strings);
288        }
289    }
290
291    public static String buildSchemaWithTable(String schema, String tableName) {
292        return isNotBlank(schema) ? schema + "." + tableName : tableName;
293    }
294
295    public static String[] getSchemaAndTableName(String tableNameWithSchema) {
296        int index = tableNameWithSchema.indexOf(".");
297        return index <= 0 ? new String[]{null, tableNameWithSchema.trim()}
298            : new String[]{tableNameWithSchema.substring(0, index).trim(), tableNameWithSchema.substring(index + 1).trim()};
299    }
300
301    public static String[] getTableNameWithAlias(String tableNameWithAlias) {
302        int index = tableNameWithAlias.indexOf(".");
303        return index <= 0 ? new String[]{tableNameWithAlias, null}
304            : new String[]{tableNameWithAlias.substring(0, index), tableNameWithAlias.substring(index + 1)};
305    }
306
307    public static String tryTrim(String string) {
308        return string != null ? string.trim() : null;
309    }
310
311    public static String substringAfterLast(String text, String prefix) {
312        if (text == null) {
313            return null;
314        }
315        if (prefix == null) {
316            return text;
317        }
318        return text.substring(text.lastIndexOf(prefix) + 1);
319    }
320
321
322}