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     * 字符串为 null 或者内部字符全部为 ' ', '\t', '\n', '\r' 这四类字符时返回 true
109     */
110    public static boolean isBlank(String str) {
111        if (str == null) {
112            return true;
113        }
114
115        for (int i = 0, len = str.length(); i < len; i++) {
116            if (str.charAt(i) > ' ') {
117                return false;
118            }
119        }
120        return true;
121    }
122
123
124    public static boolean isAnyBlank(String... strings) {
125        if (strings == null || strings.length == 0) {
126            throw new IllegalArgumentException("args is empty.");
127        }
128
129        for (String str : strings) {
130            if (isBlank(str)) {
131                return true;
132            }
133        }
134        return false;
135    }
136
137
138    public static boolean isNotBlank(String str) {
139        return !isBlank(str);
140    }
141
142
143    public static boolean areNotBlank(String... strings) {
144        return !isAnyBlank();
145    }
146
147
148    /**
149     * 这个字符串是否是全是数字
150     *
151     * @param str
152     * @return
153     */
154    public static boolean isNumeric(String str) {
155        if (isBlank(str)) {
156            return false;
157        }
158        for (int i = str.length(); --i >= 0; ) {
159            int chr = str.charAt(i);
160            if (chr < 48 || chr > 57) {
161                return false;
162            }
163        }
164        return true;
165    }
166
167
168    public static boolean startsWithAny(String str, String... prefixes) {
169        if (isBlank(str) || prefixes == null || prefixes.length == 0) {
170            return false;
171        }
172
173        for (String prefix : prefixes) {
174            if (str.startsWith(prefix)) {
175                return true;
176            }
177        }
178        return false;
179    }
180
181
182    public static boolean endsWithAny(String str, String... suffixes) {
183        if (isBlank(str) || suffixes == null || suffixes.length == 0) {
184            return false;
185        }
186
187        for (String suffix : suffixes) {
188            if (str.endsWith(suffix)) {
189                return true;
190            }
191        }
192        return false;
193    }
194
195
196    public static String trimOrNull(String string) {
197        return string != null ? string.trim() : null;
198    }
199
200
201    /**
202     * 正则匹配
203     *
204     * @param regex
205     * @param input
206     * @return
207     */
208    public static boolean matches(String regex, String input) {
209        if (null == regex || null == input) {
210            return false;
211        }
212        return Pattern.matches(regex, input);
213    }
214
215    /**
216     * 合并字符串,优化 String.join() 方法
217     *
218     * @param delimiter
219     * @param elements
220     * @return 新拼接好的字符串
221     * @see String#join(CharSequence, CharSequence...)
222     */
223    public static String join(String delimiter, CharSequence... elements) {
224        if (ArrayUtil.isEmpty(elements)) {
225            return "";
226        } else if (elements.length == 1) {
227            return String.valueOf(elements[0]);
228        } else {
229            return String.join(delimiter, elements);
230        }
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, Collection<? extends CharSequence> elements) {
242        if (CollectionUtil.isEmpty(elements)) {
243            return "";
244        } else if (elements.size() == 1) {
245            return String.valueOf(elements.iterator().next());
246        } else {
247            return String.join(delimiter, elements);
248        }
249    }
250
251
252    /**
253     * 合并字符串,优化 String.join() 方法
254     *
255     * @param delimiter
256     * @param objs
257     * @param function
258     * @param <T>
259     */
260    public static <T> String join(String delimiter, Collection<T> objs, Function<T, String> function) {
261        if (CollectionUtil.isEmpty(objs)) {
262            return "";
263        } else if (objs.size() == 1) {
264            T next = objs.iterator().next();
265            return String.valueOf(function.apply(next));
266        } else {
267            String[] strings = new String[objs.size()];
268            int index = 0;
269            for (T obj : objs) {
270                strings[index++] = function.apply(obj);
271            }
272            return String.join(delimiter, strings);
273        }
274    }
275
276    public static String buildSchemaWithTable(String schema, String tableName) {
277        return isNotBlank(schema) ? schema + "." + tableName : tableName;
278    }
279
280    public static String[] getSchemaAndTableName(String tableNameWithSchema) {
281        int index = tableNameWithSchema.indexOf(".");
282        return index <= 0 ? new String[]{null, tableNameWithSchema.trim()}
283            : new String[]{tableNameWithSchema.substring(0, index).trim(), tableNameWithSchema.substring(index + 1).trim()};
284    }
285
286    public static String tryTrim(String string) {
287        return string != null ? string.trim() : null;
288    }
289
290
291}