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        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 str) {
131        if (str == null) {
132            return true;
133        }
134
135        for (int i = 0, len = str.length(); i < len; i++) {
136            if (str.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("args is empty.");
147        }
148
149        for (String str : strings) {
150            if (isBlank(str)) {
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 str
172     * @return
173     */
174    public static boolean isNumeric(String str) {
175        if (isBlank(str)) {
176            return false;
177        }
178        for (int i = str.length(); --i >= 0; ) {
179            int chr = str.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 str, String... prefixes) {
189        if (isBlank(str) || prefixes == null || prefixes.length == 0) {
190            return false;
191        }
192
193        for (String prefix : prefixes) {
194            if (str.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 || suffixes.length == 0) {
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    public static String trimOrNull(String string) {
217        return string != null ? string.trim() : null;
218    }
219
220
221    /**
222     * 正则匹配
223     *
224     * @param regex
225     * @param input
226     * @return
227     */
228    public static boolean matches(String regex, String input) {
229        if (null == regex || null == input) {
230            return false;
231        }
232        return Pattern.matches(regex, input);
233    }
234
235    /**
236     * 合并字符串,优化 String.join() 方法
237     *
238     * @param delimiter
239     * @param elements
240     * @return 新拼接好的字符串
241     * @see String#join(CharSequence, CharSequence...)
242     */
243    public static String join(String delimiter, CharSequence... elements) {
244        if (ArrayUtil.isEmpty(elements)) {
245            return "";
246        } else if (elements.length == 1) {
247            return String.valueOf(elements[0]);
248        } else {
249            return String.join(delimiter, elements);
250        }
251    }
252
253    /**
254     * 合并字符串,优化 String.join() 方法
255     *
256     * @param delimiter
257     * @param elements
258     * @return 新拼接好的字符串
259     * @see String#join(CharSequence, CharSequence...)
260     */
261    public static String join(String delimiter, Collection<? extends CharSequence> elements) {
262        if (CollectionUtil.isEmpty(elements)) {
263            return "";
264        } else if (elements.size() == 1) {
265            return String.valueOf(elements.iterator().next());
266        } else {
267            return String.join(delimiter, elements);
268        }
269    }
270
271
272    /**
273     * 合并字符串,优化 String.join() 方法
274     *
275     * @param delimiter
276     * @param objs
277     * @param function
278     * @param <T>
279     */
280    public static <T> String join(String delimiter, Collection<T> objs, Function<T, String> function) {
281        if (CollectionUtil.isEmpty(objs)) {
282            return "";
283        } else if (objs.size() == 1) {
284            T next = objs.iterator().next();
285            return String.valueOf(function.apply(next));
286        } else {
287            String[] strings = new String[objs.size()];
288            int index = 0;
289            for (T obj : objs) {
290                strings[index++] = function.apply(obj);
291            }
292            return String.join(delimiter, strings);
293        }
294    }
295
296    public static String buildSchemaWithTable(String schema, String tableName) {
297        return isNotBlank(schema) ? schema + "." + tableName : tableName;
298    }
299
300    public static String[] getSchemaAndTableName(String tableNameWithSchema) {
301        int index = tableNameWithSchema.indexOf(".");
302        return index <= 0 ? new String[]{null, tableNameWithSchema.trim()}
303            : new String[]{tableNameWithSchema.substring(0, index).trim(), tableNameWithSchema.substring(index + 1).trim()};
304    }
305
306    public static String[] getTableNameWithAlisa(String tableNameWithAlisa) {
307        int index = tableNameWithAlisa.indexOf(".");
308        return index <= 0 ? new String[]{tableNameWithAlisa, null}
309            : new String[]{tableNameWithAlisa.substring(0, index), tableNameWithAlisa.substring(index + 1)};
310    }
311
312    public static String tryTrim(String string) {
313        return string != null ? string.trim() : null;
314    }
315
316    public static String substringAfterLast(String text, String str) {
317        if (text == null) {
318            return null;
319        }
320        if (str == null) {
321            return text;
322        }
323        return text.substring(text.lastIndexOf(str) + 1);
324    }
325
326
327}