StringUtils.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. /**
  2. * Copyright (c) 2011-2014, hubin (jobob@qq.com).
  3. * <p>
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. * <p>
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. * <p>
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.baomidou.mybatisplus.toolkit;
  17. import java.util.ArrayList;
  18. import java.util.Collection;
  19. import java.util.Collections;
  20. import java.util.Iterator;
  21. import java.util.List;
  22. import java.util.regex.Matcher;
  23. import java.util.regex.Pattern;
  24. /**
  25. * <p>
  26. * String 工具类
  27. * </p>
  28. *
  29. * @author D.Yang
  30. * @Date 2016-08-18
  31. */
  32. public class StringUtils {
  33. /**
  34. * 空字符
  35. */
  36. public static final String EMPTY = "";
  37. /**
  38. * 字符串 is
  39. */
  40. public static final String IS = "is";
  41. /**
  42. * 下划线字符
  43. */
  44. public static final char UNDERLINE = '_';
  45. /**
  46. * 占位符
  47. */
  48. public static final String PLACE_HOLDER = "{%s}";
  49. private static boolean separatorBeforeDigit = false;
  50. private static boolean separatorAfterDigit = true;
  51. private StringUtils() {
  52. }
  53. /**
  54. * <p>
  55. * 判断字符串是否为空
  56. * </p>
  57. *
  58. * @param cs 需要判断字符串
  59. * @return 判断结果
  60. */
  61. public static boolean isEmpty(final CharSequence cs) {
  62. int strLen;
  63. if (cs == null || (strLen = cs.length()) == 0) {
  64. return true;
  65. }
  66. for (int i = 0; i < strLen; i++) {
  67. if (!Character.isWhitespace(cs.charAt(i))) {
  68. return false;
  69. }
  70. }
  71. return true;
  72. }
  73. /**
  74. * <p>
  75. * 判断字符串是否不为空
  76. * </p>
  77. *
  78. * @param cs 需要判断字符串
  79. * @return 判断结果
  80. */
  81. public static boolean isNotEmpty(final CharSequence cs) {
  82. return !isEmpty(cs);
  83. }
  84. /**
  85. * <p>
  86. * 字符串驼峰转下划线格式
  87. * </p>
  88. *
  89. * @param param 需要转换的字符串
  90. * @return 转换好的字符串
  91. */
  92. public static String camelToUnderline(String param) {
  93. if (isEmpty(param)) {
  94. return EMPTY;
  95. }
  96. int len = param.length();
  97. StringBuilder sb = new StringBuilder(len);
  98. for (int i = 0; i < len; i++) {
  99. char c = param.charAt(i);
  100. if (Character.isUpperCase(c) && i > 0) {
  101. sb.append(UNDERLINE);
  102. }
  103. sb.append(Character.toLowerCase(c));
  104. }
  105. return sb.toString();
  106. }
  107. /**
  108. * <p>
  109. * 字符串下划线转驼峰格式
  110. * </p>
  111. *
  112. * @param param 需要转换的字符串
  113. * @return 转换好的字符串
  114. */
  115. public static String underlineToCamel(String param) {
  116. if (isEmpty(param)) {
  117. return EMPTY;
  118. }
  119. String temp = param.toLowerCase();
  120. int len = temp.length();
  121. StringBuilder sb = new StringBuilder(len);
  122. for (int i = 0; i < len; i++) {
  123. char c = temp.charAt(i);
  124. if (c == UNDERLINE) {
  125. if (++i < len) {
  126. sb.append(Character.toUpperCase(temp.charAt(i)));
  127. }
  128. } else {
  129. sb.append(c);
  130. }
  131. }
  132. return sb.toString();
  133. }
  134. /**
  135. * <p>
  136. * 首字母转换小写
  137. * </p>
  138. *
  139. * @param param 需要转换的字符串
  140. * @return 转换好的字符串
  141. */
  142. public static String firstToLowerCase(String param) {
  143. if (isEmpty(param)) {
  144. return EMPTY;
  145. }
  146. StringBuilder sb = new StringBuilder(param.length());
  147. sb.append(param.substring(0, 1).toLowerCase());
  148. sb.append(param.substring(1));
  149. return sb.toString();
  150. }
  151. /**
  152. * <p>
  153. * 判断字符串是否为纯大写字母
  154. * </p>
  155. *
  156. * @param str 要匹配的字符串
  157. * @return
  158. */
  159. public static boolean isUpperCase(String str) {
  160. return match("^[A-Z]+$", str);
  161. }
  162. /**
  163. * <p>
  164. * 正则表达式匹配
  165. * </p>
  166. *
  167. * @param regex 正则表达式字符串
  168. * @param str 要匹配的字符串
  169. * @return 如果str 符合 regex的正则表达式格式,返回true, 否则返回 false;
  170. */
  171. public static boolean match(String regex, String str) {
  172. Pattern pattern = Pattern.compile(regex);
  173. Matcher matcher = pattern.matcher(str);
  174. return matcher.matches();
  175. }
  176. /**
  177. * <p>
  178. * SQL 参数填充
  179. * </p>
  180. *
  181. * @param content 填充内容
  182. * @param args 填充参数
  183. * @return
  184. */
  185. public static String sqlArgsFill(String content, Object... args) {
  186. if (StringUtils.isEmpty(content)) {
  187. return null;
  188. }
  189. if (args != null) {
  190. int length = args.length;
  191. if (length >= 1) {
  192. for (int i = 0; i < length; i++) {
  193. content = content.replace(String.format(PLACE_HOLDER, i), sqlParam(args[i]));
  194. }
  195. }
  196. }
  197. return content;
  198. }
  199. /**
  200. * <p>
  201. * 获取SQL PARAMS字符串
  202. * </p>
  203. *
  204. * @param obj
  205. * @return
  206. */
  207. public static String sqlParam(Object obj) {
  208. String repStr;
  209. if (obj instanceof Collection) {
  210. repStr = StringUtils.quotaMarkList((Collection<?>) obj);
  211. } else {
  212. repStr = StringUtils.quotaMark(obj);
  213. }
  214. return repStr;
  215. }
  216. /**
  217. * <p>
  218. * 使用单引号包含字符串
  219. * </p>
  220. *
  221. * @param obj 原字符串
  222. * @return 单引号包含的原字符串
  223. */
  224. public static String quotaMark(Object obj) {
  225. String srcStr = String.valueOf(obj);
  226. if (obj instanceof CharSequence) {
  227. // fix #79
  228. return StringEscape.escapeString(srcStr);
  229. }
  230. return srcStr;
  231. }
  232. /**
  233. * <p>
  234. * 使用单引号包含字符串
  235. * </p>
  236. *
  237. * @param coll 集合
  238. * @return 单引号包含的原字符串的集合形式
  239. */
  240. public static String quotaMarkList(Collection<?> coll) {
  241. StringBuilder sqlBuild = new StringBuilder();
  242. sqlBuild.append("(");
  243. int size = coll.size();
  244. int i = 0;
  245. Iterator<?> iterator = coll.iterator();
  246. while (iterator.hasNext()) {
  247. String tempVal = StringUtils.quotaMark(iterator.next());
  248. sqlBuild.append(tempVal);
  249. if (i + 1 < size) {
  250. sqlBuild.append(",");
  251. }
  252. i++;
  253. }
  254. sqlBuild.append(")");
  255. return sqlBuild.toString();
  256. }
  257. /**
  258. * <p>
  259. * 拼接字符串第二个字符串第一个字母大写
  260. * </p>
  261. *
  262. * @param concatStr
  263. * @param str
  264. * @return
  265. */
  266. public static String concatCapitalize(String concatStr, final String str) {
  267. if (isEmpty(concatStr)) {
  268. concatStr = EMPTY;
  269. }
  270. int strLen;
  271. if (str == null || (strLen = str.length()) == 0) {
  272. return str;
  273. }
  274. final char firstChar = str.charAt(0);
  275. if (Character.isTitleCase(firstChar)) {
  276. // already capitalized
  277. return str;
  278. }
  279. StringBuilder sb = new StringBuilder(strLen);
  280. sb.append(concatStr);
  281. sb.append(Character.toTitleCase(firstChar));
  282. sb.append(str.substring(1));
  283. return sb.toString();
  284. }
  285. /**
  286. * <p>
  287. * 字符串第一个字母大写
  288. * </p>
  289. *
  290. * @param str
  291. * @return
  292. */
  293. public static String capitalize(final String str) {
  294. return concatCapitalize(null, str);
  295. }
  296. /**
  297. * <p>
  298. * 判断对象是否为空
  299. * </p>
  300. *
  301. * @param object
  302. * @return
  303. */
  304. public static boolean checkValNotNull(Object object) {
  305. if (object instanceof CharSequence) {
  306. return isNotEmpty((CharSequence) object);
  307. }
  308. return object != null;
  309. }
  310. /**
  311. * <p>
  312. * 判断对象是否为空
  313. * </p>
  314. *
  315. * @param object
  316. * @return
  317. */
  318. public static boolean checkValNull(Object object) {
  319. return !checkValNotNull(object);
  320. }
  321. /**
  322. * <p>
  323. * 包含大写字母
  324. * </p>
  325. *
  326. * @param word 待判断字符串
  327. * @return
  328. */
  329. public static boolean containsUpperCase(String word) {
  330. for (int i = 0; i < word.length(); i++) {
  331. char c = word.charAt(i);
  332. if (Character.isUpperCase(c)) {
  333. return true;
  334. }
  335. }
  336. return false;
  337. }
  338. /**
  339. * <p>
  340. * 是否为大写命名
  341. * </p>
  342. *
  343. * @param word 待判断字符串
  344. * @return
  345. */
  346. public static boolean isCapitalMode(String word) {
  347. return null != word && word.matches("^[0-9A-Z/_]+$");
  348. }
  349. /**
  350. * <p>
  351. * Check if a String ends with a specified suffix.
  352. * </p>
  353. * <p>
  354. * <p>
  355. * <code>null</code>s are handled without exceptions. Two <code>null</code>
  356. * references are considered to be equal. The comparison is case sensitive.
  357. * </p>
  358. * <p>
  359. * <pre>
  360. * StringUtils.endsWith(null, null) = true
  361. * StringUtils.endsWith(null, "abcdef") = false
  362. * StringUtils.endsWith("def", null) = false
  363. * StringUtils.endsWith("def", "abcdef") = true
  364. * StringUtils.endsWith("def", "ABCDEF") = false
  365. * </pre>
  366. *
  367. * @param str the String to check, may be null
  368. * @param suffix the suffix to find, may be null
  369. * @return <code>true</code> if the String ends with the suffix, case
  370. * sensitive, or both <code>null</code>
  371. * @see java.lang.String#endsWith(String)
  372. * @since 2.4
  373. */
  374. public static boolean endsWith(String str, String suffix) {
  375. return endsWith(str, suffix, false);
  376. }
  377. /**
  378. * <p>
  379. * Case insensitive check if a String ends with a specified suffix.
  380. * </p>
  381. * <p>
  382. * <p>
  383. * <code>null</code>s are handled without exceptions. Two <code>null</code>
  384. * references are considered to be equal. The comparison is case
  385. * insensitive.
  386. * </p>
  387. * <p>
  388. * <pre>
  389. * StringUtils.endsWithIgnoreCase(null, null) = true
  390. * StringUtils.endsWithIgnoreCase(null, "abcdef") = false
  391. * StringUtils.endsWithIgnoreCase("def", null) = false
  392. * StringUtils.endsWithIgnoreCase("def", "abcdef") = true
  393. * StringUtils.endsWithIgnoreCase("def", "ABCDEF") = false
  394. * </pre>
  395. *
  396. * @param str the String to check, may be null
  397. * @param suffix the suffix to find, may be null
  398. * @return <code>true</code> if the String ends with the suffix, case
  399. * insensitive, or both <code>null</code>
  400. * @see java.lang.String#endsWith(String)
  401. * @since 2.4
  402. */
  403. public static boolean endsWithIgnoreCase(String str, String suffix) {
  404. return endsWith(str, suffix, true);
  405. }
  406. /**
  407. * <p>
  408. * Check if a String ends with a specified suffix (optionally case
  409. * insensitive).
  410. * </p>
  411. *
  412. * @param str the String to check, may be null
  413. * @param suffix the suffix to find, may be null
  414. * @param ignoreCase inidicates whether the compare should ignore case (case
  415. * insensitive) or not.
  416. * @return <code>true</code> if the String starts with the prefix or both
  417. * <code>null</code>
  418. * @see java.lang.String#endsWith(String)
  419. */
  420. private static boolean endsWith(String str, String suffix, boolean ignoreCase) {
  421. if (str == null || suffix == null) {
  422. return (str == null && suffix == null);
  423. }
  424. if (suffix.length() > str.length()) {
  425. return false;
  426. }
  427. int strOffset = str.length() - suffix.length();
  428. return str.regionMatches(ignoreCase, strOffset, suffix, 0, suffix.length());
  429. }
  430. /**
  431. * <p>
  432. * Splits the provided text into an array, separators specified. This is an
  433. * alternative to using StringTokenizer.
  434. * </p>
  435. * <p>
  436. * <p>
  437. * The separator is not included in the returned String array. Adjacent
  438. * separators are treated as one separator. For more control over the split
  439. * use the StrTokenizer class.
  440. * </p>
  441. * <p>
  442. * <p>
  443. * A {@code null} input String returns {@code null}. A {@code null}
  444. * separatorChars splits on whitespace.
  445. * </p>
  446. * <p>
  447. * <pre>
  448. * StringUtils.split(null, *) = null
  449. * StringUtils.split("", *) = []
  450. * StringUtils.split("abc def", null) = ["abc", "def"]
  451. * StringUtils.split("abc def", " ") = ["abc", "def"]
  452. * StringUtils.split("abc def", " ") = ["abc", "def"]
  453. * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
  454. * </pre>
  455. *
  456. * @param str the String to parse, may be null
  457. * @param separatorChars the characters used as the delimiters, {@code null} splits on
  458. * whitespace
  459. * @return an array of parsed Strings, {@code null} if null String input
  460. */
  461. public static String[] split(final String str, final String separatorChars) {
  462. List<String> strings = splitWorker(str, separatorChars, -1, false);
  463. return strings.toArray(new String[strings.size()]);
  464. }
  465. /**
  466. * Performs the logic for the {@code split} and
  467. * {@code splitPreserveAllTokens} methods that return a maximum array
  468. * length.
  469. *
  470. * @param str the String to parse, may be {@code null}
  471. * @param separatorChars the separate character
  472. * @param max the maximum number of elements to include in the array. A zero
  473. * or negative value implies no limit.
  474. * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty
  475. * token separators; if {@code false}, adjacent separators are
  476. * treated as one separator.
  477. * @return an array of parsed Strings, {@code null} if null String input
  478. */
  479. public static List<String> splitWorker(final String str, final String separatorChars, final int max,
  480. final boolean preserveAllTokens) {
  481. // Performance tuned for 2.0 (JDK1.4)
  482. // Direct code is quicker than StringTokenizer.
  483. // Also, StringTokenizer uses isSpace() not isWhitespace()
  484. if (str == null) {
  485. return null;
  486. }
  487. final int len = str.length();
  488. if (len == 0) {
  489. return Collections.emptyList();
  490. }
  491. final List<String> list = new ArrayList<>();
  492. int sizePlus1 = 1;
  493. int i = 0, start = 0;
  494. boolean match = false;
  495. boolean lastMatch = false;
  496. if (separatorChars == null) {
  497. // Null separator means use whitespace
  498. while (i < len) {
  499. if (Character.isWhitespace(str.charAt(i))) {
  500. if (match || preserveAllTokens) {
  501. lastMatch = true;
  502. if (sizePlus1++ == max) {
  503. i = len;
  504. lastMatch = false;
  505. }
  506. list.add(str.substring(start, i));
  507. match = false;
  508. }
  509. start = ++i;
  510. continue;
  511. }
  512. lastMatch = false;
  513. match = true;
  514. i++;
  515. }
  516. } else if (separatorChars.length() == 1) {
  517. // Optimise 1 character case
  518. final char sep = separatorChars.charAt(0);
  519. while (i < len) {
  520. if (str.charAt(i) == sep) {
  521. if (match || preserveAllTokens) {
  522. lastMatch = true;
  523. if (sizePlus1++ == max) {
  524. i = len;
  525. lastMatch = false;
  526. }
  527. list.add(str.substring(start, i));
  528. match = false;
  529. }
  530. start = ++i;
  531. continue;
  532. }
  533. lastMatch = false;
  534. match = true;
  535. i++;
  536. }
  537. } else {
  538. // standard case
  539. while (i < len) {
  540. if (separatorChars.indexOf(str.charAt(i)) >= 0) {
  541. if (match || preserveAllTokens) {
  542. lastMatch = true;
  543. if (sizePlus1++ == max) {
  544. i = len;
  545. lastMatch = false;
  546. }
  547. list.add(str.substring(start, i));
  548. match = false;
  549. }
  550. start = ++i;
  551. continue;
  552. }
  553. lastMatch = false;
  554. match = true;
  555. i++;
  556. }
  557. }
  558. if (match || preserveAllTokens && lastMatch) {
  559. list.add(str.substring(start, i));
  560. }
  561. return list;
  562. }
  563. /**
  564. * <p>
  565. * 是否为CharSequence类型
  566. * </p>
  567. *
  568. * @param cls
  569. * @return
  570. */
  571. public static Boolean isCharSequence(Class<?> cls) {
  572. return cls != null && CharSequence.class.isAssignableFrom(cls);
  573. }
  574. /**
  575. * <p>
  576. * 去除boolean类型is开头的字符串
  577. * </p>
  578. *
  579. * @param propertyName 字段名
  580. * @param propertyType 字段类型
  581. * @return
  582. */
  583. public static String removeIsPrefixIfBoolean(String propertyName, Class<?> propertyType) {
  584. if (isBoolean(propertyType) && propertyName.startsWith(IS)) {
  585. String property = propertyName.replaceFirst(IS, EMPTY);
  586. if (isEmpty(property)) {
  587. return propertyName;
  588. } else {
  589. String firstCharToLowerStr = firstCharToLower(property);
  590. return property.equals(firstCharToLowerStr) ? propertyName : firstCharToLowerStr;
  591. }
  592. }
  593. return propertyName;
  594. }
  595. /**
  596. * <p>
  597. * 是否为CharSequence类型
  598. * </p>
  599. *
  600. * @param propertyType
  601. * @return
  602. */
  603. public static Boolean isCharSequence(String propertyType) {
  604. try {
  605. return isCharSequence(Class.forName(propertyType));
  606. } catch (ClassNotFoundException e) {
  607. return false;
  608. }
  609. }
  610. /**
  611. * <p>
  612. * 是否为Boolean类型(包含普通类型)
  613. * </p>
  614. *
  615. * @param propertyCls
  616. * @return
  617. */
  618. public static Boolean isBoolean(Class<?> propertyCls) {
  619. return propertyCls != null && (boolean.class.isAssignableFrom(propertyCls) || Boolean.class.isAssignableFrom(propertyCls));
  620. }
  621. /**
  622. * <p>
  623. * 第一个首字母小写,之后字符大小写的不变<br>
  624. * StringUtils.firstCharToLower( "UserService" ) = userService
  625. * StringUtils.firstCharToLower( "UserServiceImpl" ) = userServiceImpl
  626. * </p>
  627. *
  628. * @param rawString 需要处理的字符串
  629. * @return
  630. */
  631. public static String firstCharToLower(String rawString) {
  632. return prefixToLower(rawString, 1);
  633. }
  634. /**
  635. * <p>
  636. * 前n个首字母小写,之后字符大小写的不变
  637. * </p>
  638. *
  639. * @param rawString 需要处理的字符串
  640. * @param index 多少个字符(从左至右)
  641. * @return
  642. */
  643. public static String prefixToLower(String rawString, int index) {
  644. String beforeChar = rawString.substring(0, index).toLowerCase();
  645. String afterChar = rawString.substring(index, rawString.length());
  646. return beforeChar + afterChar;
  647. }
  648. /**
  649. * <p>
  650. * 删除字符前缀之后,首字母小写,之后字符大小写的不变<br>
  651. * StringUtils.removePrefixAfterPrefixToLower( "isUser", 2 ) = user
  652. * StringUtils.removePrefixAfterPrefixToLower( "isUserInfo", 2 ) = userInfo
  653. * </p>
  654. *
  655. * @param rawString 需要处理的字符串
  656. * @param index 删除多少个字符(从左至右)
  657. * @return
  658. */
  659. public static String removePrefixAfterPrefixToLower(String rawString, int index) {
  660. return prefixToLower(rawString.substring(index, rawString.length()), 1);
  661. }
  662. /**
  663. * <p>
  664. * 驼峰转连字符<br>
  665. * StringUtils.camelToHyphen( "managerAdminUserService" ) = manager-admin-user-service
  666. * </p>
  667. *
  668. * @param input
  669. * @return 以'-'分隔
  670. * @see <a href="https://github.com/krasa/StringManipulation">document</a>
  671. */
  672. public static String camelToHyphen(String input) {
  673. return wordsToHyphenCase(wordsAndHyphenAndCamelToConstantCase(input));
  674. }
  675. private static String wordsAndHyphenAndCamelToConstantCase(String input) {
  676. boolean betweenUpperCases = false;
  677. boolean containsLowerCase = containsLowerCase(input);
  678. StringBuilder buf = new StringBuilder();
  679. char previousChar = ' ';
  680. char[] chars = input.toCharArray();
  681. for (int i = 0; i < chars.length; i++) {
  682. char c = chars[i];
  683. boolean isUpperCaseAndPreviousIsUpperCase = (Character.isUpperCase(previousChar)) && (Character.isUpperCase(c));
  684. boolean isUpperCaseAndPreviousIsLowerCase = (Character.isLowerCase(previousChar)) && (Character.isUpperCase(c));
  685. boolean previousIsWhitespace = Character.isWhitespace(previousChar);
  686. boolean lastOneIsNotUnderscore = (buf.length() > 0) && (buf.charAt(buf.length() - 1) != '_');
  687. boolean isNotUnderscore = c != '_';
  688. if ((lastOneIsNotUnderscore) && ((isUpperCaseAndPreviousIsLowerCase) || (previousIsWhitespace) || ((betweenUpperCases)
  689. && (containsLowerCase) && (isUpperCaseAndPreviousIsUpperCase)))) {
  690. buf.append("_");
  691. } else if (((separatorAfterDigit) && (Character.isDigit(previousChar))
  692. && (Character.isLetter(c))) || ((separatorBeforeDigit) && (Character
  693. .isDigit(c)) && (Character.isLetter(previousChar)))) {
  694. buf.append('_');
  695. }
  696. if ((shouldReplace(c)) && (lastOneIsNotUnderscore)) {
  697. buf.append('_');
  698. } else if ((!Character.isWhitespace(c)) && ((isNotUnderscore) || (lastOneIsNotUnderscore))) {
  699. buf.append(Character.toUpperCase(c));
  700. }
  701. previousChar = c;
  702. }
  703. if (Character.isWhitespace(previousChar)) {
  704. buf.append("_");
  705. }
  706. return buf.toString();
  707. }
  708. public static boolean containsLowerCase(String s) {
  709. for (char c : s.toCharArray()) {
  710. if (Character.isLowerCase(c)) {
  711. return true;
  712. }
  713. }
  714. return false;
  715. }
  716. private static boolean shouldReplace(char c) {
  717. return (c == '.') || (c == '_') || (c == '-');
  718. }
  719. private static String wordsToHyphenCase(String s) {
  720. StringBuilder buf = new StringBuilder();
  721. char lastChar = 'a';
  722. for (char c : s.toCharArray()) {
  723. if ((Character.isWhitespace(lastChar)) && (!Character.isWhitespace(c))
  724. && ('-' != c) && (buf.length() > 0)
  725. && (buf.charAt(buf.length() - 1) != '-')) {
  726. buf.append("-");
  727. }
  728. if ('_' == c) {
  729. buf.append('-');
  730. } else if ('.' == c) {
  731. buf.append('-');
  732. } else if (!Character.isWhitespace(c)) {
  733. buf.append(Character.toLowerCase(c));
  734. }
  735. lastChar = c;
  736. }
  737. if (Character.isWhitespace(lastChar)) {
  738. buf.append("-");
  739. }
  740. return buf.toString();
  741. }
  742. }