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     * @param string
032     */
033    public static String firstCharToLowerCase(String string) {
034        char firstChar = string.charAt(0);
035        if (firstChar >= 'A' && firstChar <= 'Z') {
036            char[] arr = string.toCharArray();
037            arr[0] += ('a' - 'A');
038            return new String(arr);
039        }
040        return string;
041    }
042
043
044    /**
045     * 第一个字符转换为大写
046     *
047     * @param string
048     */
049    public static String firstCharToUpperCase(String string) {
050        char firstChar = string.charAt(0);
051        if (firstChar >= 'a' && firstChar <= 'z') {
052            char[] arr = string.toCharArray();
053            arr[0] -= ('a' - 'A');
054            return new String(arr);
055        }
056        return string;
057    }
058
059
060    /**
061     * 驼峰转下划线格式
062     *
063     * @param string
064     */
065    public static String camelToUnderline(String string) {
066        if (isBlank(string)) {
067            return "";
068        }
069        int strLen = string.length();
070        StringBuilder sb = new StringBuilder(strLen);
071        for (int i = 0; i < strLen; i++) {
072            char c = string.charAt(i);
073            if (Character.isUpperCase(c) && i > 0) {
074                sb.append('_');
075            }
076            sb.append(Character.toLowerCase(c));
077        }
078        return sb.toString();
079    }
080
081    /**
082     * 下划线转驼峰格式
083     *
084     * @param string
085     */
086    public static String underlineToCamel(String string) {
087        if (isBlank(string)) {
088            return "";
089        }
090        String temp = string.toLowerCase();
091        int strLen = temp.length();
092        StringBuilder sb = new StringBuilder(strLen);
093        for (int i = 0; i < strLen; i++) {
094            char c = temp.charAt(i);
095            if (c == '_') {
096                if (++i < strLen) {
097                    sb.append(Character.toUpperCase(temp.charAt(i)));
098                }
099            } else {
100                sb.append(c);
101            }
102        }
103        return sb.toString();
104    }
105
106    /**
107     * 字符串为 null 或者内部字符全部为 ' ', '\t', '\n', '\r' 这四类字符时返回 true
108     */
109    public static boolean isBlank(String str) {
110        if (str == null) {
111            return true;
112        }
113
114        for (int i = 0, len = str.length(); i < len; i++) {
115            if (str.charAt(i) > ' ') {
116                return false;
117            }
118        }
119        return true;
120    }
121
122
123    public static boolean isAnyBlank(String... strings) {
124        if (strings == null || strings.length == 0) {
125            throw new IllegalArgumentException("args is empty.");
126        }
127
128        for (String str : strings) {
129            if (isBlank(str)) {
130                return true;
131            }
132        }
133        return false;
134    }
135
136
137    public static boolean isNotBlank(String str) {
138        return !isBlank(str);
139    }
140
141
142    public static boolean areNotBlank(String... strings) {
143        return !isAnyBlank();
144    }
145
146
147    /**
148     * 这个字符串是否是全是数字
149     *
150     * @param str
151     * @return
152     */
153    public static boolean isNumeric(String str) {
154        if (isBlank(str)) {
155            return false;
156        }
157        for (int i = str.length(); --i >= 0; ) {
158            int chr = str.charAt(i);
159            if (chr < 48 || chr > 57) {
160                return false;
161            }
162        }
163        return true;
164    }
165
166
167    public static boolean startsWithAny(String str, String... prefixes) {
168        if (isBlank(str) || prefixes == null || prefixes.length == 0) {
169            return false;
170        }
171
172        for (String prefix : prefixes) {
173            if (str.startsWith(prefix)) {
174                return true;
175            }
176        }
177        return false;
178    }
179
180
181    public static boolean endsWithAny(String str, String... suffixes) {
182        if (isBlank(str) || suffixes == null || suffixes.length == 0) {
183            return false;
184        }
185
186        for (String suffix : suffixes) {
187            if (str.endsWith(suffix)) {
188                return true;
189            }
190        }
191        return false;
192    }
193
194
195    public static String trimOrNull(String string) {
196        return string != null ? string.trim() : null;
197    }
198
199
200    /**
201     * 正则匹配
202     *
203     * @param regex
204     * @param input
205     * @return
206     */
207    public static boolean matches(String regex, String input) {
208        if (null == regex || null == input) {
209            return false;
210        }
211        return Pattern.matches(regex, input);
212    }
213
214    /**
215     * 合并字符串,优化 String.join() 方法
216     *
217     * @param delimiter
218     * @param elements
219     * @return 新拼接好的字符串
220     * @see String#join(CharSequence, CharSequence...)
221     */
222    public static String join(String delimiter, CharSequence... elements) {
223        if (ArrayUtil.isEmpty(elements)) {
224            return "";
225        } else if (elements.length == 1) {
226            return String.valueOf(elements[0]);
227        } else {
228            return String.join(delimiter, elements);
229        }
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     * 合并字符串,优化 String.join() 方法
253     *
254     * @param delimiter
255     * @param objs
256     * @param function
257     * @param <T>
258     */
259    public static <T> String join(String delimiter, Collection<T> objs, Function<T, String> function) {
260        if (CollectionUtil.isEmpty(objs)) {
261            return "";
262        } else if (objs.size() == 1) {
263            T next = objs.iterator().next();
264            return String.valueOf(function.apply(next));
265        } else {
266            String[] strings = new String[objs.size()];
267            int index = 0;
268            for (T obj : objs) {
269                strings[index++] = function.apply(obj);
270            }
271            return String.join(delimiter, strings);
272        }
273    }
274
275
276}