001/* 002 * Copyright (c) 2022-2025, 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 */ 016 017package com.mybatisflex.processor.util; 018 019import java.util.Arrays; 020import java.util.List; 021import java.util.regex.Matcher; 022import java.util.regex.Pattern; 023 024/** 025 * 字符串工具类。 026 * 027 * @author 王帅 028 * @since 2023-06-22 029 */ 030@SuppressWarnings("all") 031public class StrUtil { 032 033 private StrUtil() { 034 } 035 036 private static final Pattern PACKAGE_REGEX = Pattern.compile("(?<expression>\\$\\{entityPackage[.parent]*\\})(?<subPackage>.*)"); 037 038 /** 039 * com.mybatisflex.test.entity.Account -> Account 040 */ 041 public static String getClassName(String str) { 042 return str.substring(str.lastIndexOf(".") + 1); 043 } 044 045 public static boolean isBlank(String str) { 046 return str == null || str.trim().length() == 0; 047 } 048 049 public static String camelToUnderline(String str) { 050 if (isBlank(str)) { 051 return ""; 052 } 053 int len = str.length(); 054 StringBuilder sb = new StringBuilder(len); 055 for (int i = 0; i < len; i++) { 056 char c = str.charAt(i); 057 if (Character.isUpperCase(c) && i > 0) { 058 char prev = str.charAt(i - 1); 059 if (!Character.isUpperCase(prev) && prev != '_') { 060 sb.append('_'); 061 } 062 } 063 sb.append(Character.toLowerCase(c)); 064 } 065 return sb.toString(); 066 } 067 068 public static String firstCharToLowerCase(String str) { 069 char firstChar = str.charAt(0); 070 if (firstChar >= 'A' && firstChar <= 'Z') { 071 char[] arr = str.toCharArray(); 072 arr[0] += ('a' - 'A'); 073 return new String(arr); 074 } 075 return str; 076 } 077 078 public static String firstCharToUpperCase(String str) { 079 char firstChar = str.charAt(0); 080 if (firstChar >= 'a' && firstChar <= 'z') { 081 char[] arr = str.toCharArray(); 082 arr[0] -= ('a' - 'A'); 083 return new String(arr); 084 } 085 return str; 086 } 087 088 public static String buildFieldName(String name, String tableDefPropertiesNameStyle) { 089 if ("upperCase".equalsIgnoreCase(tableDefPropertiesNameStyle)) { 090 return camelToUnderline(name).toUpperCase(); 091 } else if ("lowerCase".equalsIgnoreCase(tableDefPropertiesNameStyle)) { 092 return camelToUnderline(name).toLowerCase(); 093 } else if ("upperCamelCase".equalsIgnoreCase(tableDefPropertiesNameStyle)) { 094 return firstCharToUpperCase(name); 095 } else { 096 //lowerCamelCase 097 return firstCharToLowerCase(name); 098 } 099 } 100 101 public static String buildTableDefPackage(String entityClass) { 102 StringBuilder guessPackage = new StringBuilder(); 103 if (!entityClass.contains(".")) { 104 guessPackage.append("table"); 105 } else { 106 guessPackage.append(entityClass, 0, entityClass.lastIndexOf(".")).append(".table"); 107 } 108 return guessPackage.toString(); 109 } 110 111 public static String buildMapperPackage(String entityClass) { 112 if (!entityClass.contains(".")) { 113 return "mapper"; 114 } else { 115 String entityPackage = entityClass.substring(0, entityClass.lastIndexOf(".")); 116 if (entityPackage.contains(".")) { 117 return entityPackage.substring(0, entityPackage.lastIndexOf(".")) + ".mapper"; 118 } else { 119 return "mapper"; 120 } 121 } 122 } 123 124 /** 125 * 解析包名表达式 126 * <p>将{@code `${entityPackage}`}替换为实际实体包名, 表达式中如果存在一个{@code `.parent`}则缩减包名末尾的一位。</p> 127 * <p>示例:{@code `entityClass = com.test1.test2`}<br> 128 * 1. 对于{@code `packageStr = ${entityPackage}`}处理结果为 {@code `com.test1.test2`}<br> 129 * 2. 对于{@code `packageStr = ${entityPackage.parent}`}处理结果为 {@code `com.test1`}<br> 130 * 3. 对于{@code `packageStr = ${entityPackage.parent}.customize`}处理结果为 {@code `com.test1.customize`} 131 * </p> 132 */ 133 public static String processPackageExpression(String entityClass, String packageStr) { 134 String entityPackage = entityClass.substring(0, entityClass.lastIndexOf(".")); 135 Matcher matcher = PACKAGE_REGEX.matcher(packageStr); 136 if (!matcher.find()) { 137 return packageStr; 138 } 139 String expression = matcher.group("expression"); 140 expression = expression.substring(2, expression.length() - 1); 141 String subPackage = matcher.group("subPackage"); 142 List<String> entityPackageSplit = Arrays.asList(entityPackage.split("\\.")); 143 while (expression.contains(".parent")) { 144 if (entityPackageSplit.size() == 0) { 145 throw new RuntimeException("Expression [.parent] has exceeded the maximum limit."); 146 } 147 int index = expression.lastIndexOf(".parent"); 148 if (index != -1) { 149 expression = expression.substring(0, index); 150 entityPackageSplit = entityPackageSplit.subList(0, entityPackageSplit.size() - 1); 151 } 152 } 153 expression = expression.replace("entityPackage", String.join(".", entityPackageSplit)); 154 return expression + subPackage; 155 } 156 157 158 public static boolean isGetterMethod(String methodName, String property) { 159 if (methodName.startsWith("get") && methodName.length() > 3) { 160 return firstCharToUpperCase(property).concat("()").equals(methodName.substring(3)); 161 } else if (methodName.startsWith("is") && methodName.length() > 2) { 162 return firstCharToUpperCase(property).concat("()").equals(methodName.substring(2)); 163 } else { 164 return false; 165 } 166 } 167 168}