package cn.flightfeather.supervision.common.utils
|
|
import java.io.File
|
import java.nio.charset.StandardCharsets
|
import java.nio.file.Files
|
import java.nio.file.Paths
|
import java.util.regex.Pattern
|
|
/**
|
* 注解复制工具类
|
* 用于将Java文件中的ApiModelProperty注解复制到Kotlin文件中对应的属性
|
*/
|
object AnnotationCopyTool {
|
|
/**
|
* 将一个文件中的ApiModelProperty注解和ApiModel类注解复制到另一个文件中
|
* @param sourceFilePath 源文件路径(可以是Java或Kotlin文件)
|
* @param targetFilePath 目标文件路径(可以是Java或Kotlin文件)
|
*/
|
fun copyAnnotations(sourceFilePath: String, targetFilePath: String) {
|
try {
|
// 1. 验证文件是否存在
|
val sourceFile = File(sourceFilePath)
|
val targetFile = File(targetFilePath)
|
|
if (!sourceFile.exists() || !targetFile.exists()) {
|
println("文件不存在: ${if (!sourceFile.exists()) sourceFilePath else targetFilePath}")
|
return
|
}
|
|
// 2. 获取文件扩展名
|
val sourceExtension = sourceFile.extension.toLowerCase()
|
val targetExtension = targetFile.extension.toLowerCase()
|
|
// 3. 验证文件类型是否支持
|
if (sourceExtension != "java" && sourceExtension != "kt") {
|
println("源文件 $sourceFilePath 不是有效的Java或Kotlin文件")
|
return
|
}
|
|
if (targetExtension != "java" && targetExtension != "kt") {
|
println("目标文件 $targetFilePath 不是有效的Java或Kotlin文件")
|
return
|
}
|
|
// 4. 读取源文件和目标文件内容
|
val sourceContent = String(Files.readAllBytes(Paths.get(sourceFilePath)), StandardCharsets.UTF_8)
|
val targetContent = String(Files.readAllBytes(Paths.get(targetFilePath)), StandardCharsets.UTF_8)
|
|
// 5. 提取源文件中的类级ApiModel注解
|
val apiModelAnnotation = extractApiModelAnnotation(sourceContent)
|
|
// 6. 根据文件类型解析源文件,提取属性和对应的ApiModelProperty注解
|
val sourcePropertiesMap = if (sourceExtension == "java") {
|
parseJavaProperties(sourceContent)
|
} else {
|
parseKotlinPropertiesForAnnotations(sourceContent)
|
}
|
|
// 7. 根据文件类型解析目标文件,提取属性和对应的Column注解
|
val targetPropertiesMap = if (targetExtension == "java") {
|
parseJavaPropertiesForMapping(targetContent)
|
} else {
|
parseKotlinProperties(targetContent)
|
}
|
|
// 8. 根据Column的name值匹配源文件和目标文件中的属性,并构建新的目标文件内容
|
val newTargetContent = if (targetExtension == "java") {
|
buildNewJavaContent(targetContent, apiModelAnnotation, sourcePropertiesMap, targetPropertiesMap)
|
} else {
|
buildNewKotlinContent(targetContent, apiModelAnnotation, sourcePropertiesMap, targetPropertiesMap)
|
}
|
|
// 9. 写入新的目标文件内容
|
Files.write(Paths.get(targetFilePath), newTargetContent.toByteArray(StandardCharsets.UTF_8))
|
println("已成功将注解从 $sourceFilePath 复制到 $targetFilePath")
|
} catch (e: Exception) {
|
println("复制注解时出错: ${e.message}")
|
e.printStackTrace()
|
}
|
}
|
|
/**
|
* 从源文件内容中提取ApiModel类注解
|
*/
|
private fun extractApiModelAnnotation(fileContent: String): String {
|
// 匹配ApiModel注解的正则表达式
|
val pattern = Pattern.compile("@ApiModel\\(.*?\\)", Pattern.DOTALL)
|
val matcher = pattern.matcher(fileContent)
|
|
return if (matcher.find()) {
|
matcher.group(0)
|
} else {
|
""
|
}
|
}
|
|
/**
|
* 解析Java文件,提取属性和对应的ApiModelProperty注解
|
*/
|
private fun parseJavaProperties(javaContent: String): Map<String, String> {
|
val propertiesMap = mutableMapOf<String, String>()
|
|
// 匹配Java属性的正则表达式
|
val pattern = Pattern.compile(
|
"@Column\\(name = \"([^\"]+)\"\\)\\s+(?:@ApiModelProperty\\(value = \"([^\"]+)\"\\)\\s+)?private \\w+ \\w+;"
|
)
|
val matcher = pattern.matcher(javaContent)
|
|
while (matcher.find()) {
|
val columnName = matcher.group(1)
|
val annotationValue = matcher.group(2) ?: ""
|
if (annotationValue.isNotEmpty()) {
|
propertiesMap[columnName] = "@ApiModelProperty(value = \"${annotationValue}\")"
|
}
|
}
|
|
return propertiesMap
|
}
|
|
/**
|
* 解析Kotlin文件,提取属性和对应的ApiModelProperty注解(用于从Kotlin文件读取注解)
|
*/
|
private fun parseKotlinPropertiesForAnnotations(kotlinContent: String): Map<String, String> {
|
val propertiesMap = mutableMapOf<String, String>()
|
|
// 匹配Kotlin属性的正则表达式
|
val pattern = Pattern.compile(
|
"@Column\\(name = \"([^\"]+)\"\\)\\s+(?:@ApiModelProperty\\(value = \"([^\"]+)\"\\)\\s+)?var \\w+:"
|
)
|
val matcher = pattern.matcher(kotlinContent)
|
|
while (matcher.find()) {
|
val columnName = matcher.group(1)
|
val annotationValue = matcher.group(2) ?: ""
|
if (annotationValue.isNotEmpty()) {
|
propertiesMap[columnName] = "@ApiModelProperty(value = \"$annotationValue\")"
|
}
|
}
|
|
return propertiesMap
|
}
|
|
/**
|
* 解析Kotlin文件,提取属性和对应的Column注解
|
*/
|
private fun parseKotlinProperties(kotlinContent: String): Map<String, String> {
|
val propertiesMap = mutableMapOf<String, String>()
|
|
// 匹配Kotlin属性的正则表达式
|
val pattern = Pattern.compile(
|
"@Column\\(name = \"([^\"]+)\"\\)\\s+(?:@ApiModelProperty\\(value = \"([^\"]+)\"\\)\\s+)?var (\\w+):"
|
)
|
val matcher = pattern.matcher(kotlinContent)
|
|
while (matcher.find()) {
|
val columnName = matcher.group(1)
|
val propertyName = matcher.group(3)
|
propertiesMap[columnName] = propertyName
|
}
|
|
return propertiesMap
|
}
|
|
/**
|
* 解析Java文件,提取属性和对应的Column注解(用于映射到Java文件)
|
*/
|
private fun parseJavaPropertiesForMapping(javaContent: String): Map<String, String> {
|
val propertiesMap = mutableMapOf<String, String>()
|
|
// 匹配Java属性的正则表达式
|
val pattern = Pattern.compile(
|
"@Column\\(name = \"([^\"]+)\"\\)\\s+(?:@ApiModelProperty\\(value = \"([^\"]+)\"\\)\\s+)?private \\w+ (\\w+);"
|
)
|
val matcher = pattern.matcher(javaContent)
|
|
while (matcher.find()) {
|
val columnName = matcher.group(1)
|
val propertyName = matcher.group(3)
|
propertiesMap[columnName] = propertyName
|
}
|
|
return propertiesMap
|
}
|
|
/**
|
* 构建新的Kotlin文件内容,添加ApiModelProperty注解
|
*/
|
private fun buildNewKotlinContent(
|
originalContent: String,
|
apiModelAnnotation: String,
|
sourcePropertiesMap: Map<String, String>,
|
targetPropertiesMap: Map<String, String>,
|
): String {
|
var newContent = originalContent
|
|
// // 检查是否已经导入了ApiModelProperty
|
// if (!originalContent.contains("import io.swagger.annotations.ApiModelProperty")) {
|
// // 在其他import语句后添加导入
|
// val importPattern = Pattern.compile("(import.*\\n)+")
|
// val importMatcher = importPattern.matcher(newContent)
|
// if (importMatcher.find()) {
|
// val imports = importMatcher.group(0)
|
// val newImports = imports + "import io.swagger.annotations.ApiModelProperty\n"
|
// newContent = newContent.replace(imports, newImports)
|
// }
|
// }
|
|
// 检查是否需要添加import语句
|
if ((!originalContent.contains("import io.swagger.annotations.ApiModelProperty") && sourcePropertiesMap.isNotEmpty()) ||
|
(!originalContent.contains("import io.swagger.annotations.ApiModel") && apiModelAnnotation.isNotEmpty())) {
|
val importPattern = Pattern.compile("(import.*\\n)+")
|
val importMatcher = importPattern.matcher(newContent)
|
if (importMatcher.find()) {
|
val imports = importMatcher.group(0)
|
val newImports = StringBuilder(imports)
|
|
if (!originalContent.contains("import io.swagger.annotations.ApiModelProperty") && sourcePropertiesMap.isNotEmpty()) {
|
newImports.append("import io.swagger.annotations.ApiModelProperty\n")
|
}
|
if (!originalContent.contains("import io.swagger.annotations.ApiModel") && apiModelAnnotation.isNotEmpty()) {
|
newImports.append("import io.swagger.annotations.ApiModel\n")
|
}
|
|
newContent = newContent.replace(imports, newImports.toString())
|
}
|
}
|
|
// 添加ApiModel类注解
|
if (apiModelAnnotation.isNotEmpty()) {
|
// 查找class关键字行
|
val classPattern = Pattern.compile("class\\s+\\w+")
|
val classMatcher = classPattern.matcher(newContent)
|
|
if (classMatcher.find()) {
|
val classNameLine = classMatcher.group(0)
|
val startIndex = classMatcher.start()
|
val lines = newContent.lines()
|
|
// 查找类定义所在的行
|
var classLineIndex = 0
|
var currentPosition = 0
|
for ((i, line) in lines.withIndex()) {
|
if (currentPosition + line.length + 1 > startIndex) {
|
classLineIndex = i
|
break
|
}
|
currentPosition += line.length + 1
|
}
|
|
// 检查类定义行的前一行是否已经有ApiModel注解
|
if (classLineIndex > 0 && !lines[classLineIndex - 1].trim().startsWith("@ApiModel")) {
|
val updatedLines = lines.toMutableList()
|
updatedLines.add(classLineIndex, apiModelAnnotation)
|
newContent = updatedLines.joinToString("\n")
|
} else if (classLineIndex == 0) {
|
// 如果类定义在第一行,在前面添加注解
|
newContent = apiModelAnnotation + "\n" + newContent
|
}
|
}
|
}
|
|
// 为每个Kotlin属性添加对应的ApiModelProperty注解
|
targetPropertiesMap.forEach { (columnName, propertyName) ->
|
val annotation = sourcePropertiesMap[columnName]
|
if (annotation != null) {
|
// 查找属性定义行
|
val propertyPattern = Pattern.compile("(@Column\\(name = \"$columnName\"\\))\\s+var $propertyName:")
|
val propertyMatcher = propertyPattern.matcher(newContent)
|
|
if (propertyMatcher.find()) {
|
// 检查是否已经存在ApiModelProperty注解
|
val columnLine = propertyMatcher.group(0)
|
if (!columnLine.contains("@ApiModelProperty")) {
|
// 在@Column注解后添加@ApiModelProperty注解
|
val newPropertyLine = "@Column(name = \"$columnName\")\n $annotation\n var $propertyName:"
|
newContent = newContent.replace(columnLine, newPropertyLine)
|
}
|
}
|
}
|
}
|
|
return newContent
|
}
|
|
/**
|
* 构建新的Java文件内容,添加ApiModelProperty注解
|
*/
|
private fun buildNewJavaContent(
|
originalContent: String,
|
apiModelAnnotation: String,
|
sourcePropertiesMap: Map<String, String>,
|
targetPropertiesMap: Map<String, String>,
|
): String {
|
var newContent = originalContent
|
|
// 检查是否已经导入了ApiModelProperty
|
if (!originalContent.contains("import io.swagger.annotations.ApiModelProperty")) {
|
// 在其他import语句后添加导入
|
val importPattern = Pattern.compile("(import.*\\n)+")
|
val importMatcher = importPattern.matcher(newContent)
|
if (importMatcher.find()) {
|
val imports = importMatcher.group(0)
|
val newImports = imports + "import io.swagger.annotations.ApiModelProperty\n"
|
newContent = newContent.replace(imports, newImports)
|
}
|
}
|
// 检查是否需要添加import语句
|
if ((!originalContent.contains("import io.swagger.annotations.ApiModelProperty") && sourcePropertiesMap.isNotEmpty()) ||
|
(!originalContent.contains("import io.swagger.annotations.ApiModel") && apiModelAnnotation.isNotEmpty())) {
|
val importPattern = Pattern.compile("(import.*\\n)+")
|
val importMatcher = importPattern.matcher(newContent)
|
if (importMatcher.find()) {
|
val imports = importMatcher.group(0)
|
val newImports = StringBuilder(imports)
|
|
if (!originalContent.contains("import io.swagger.annotations.ApiModelProperty") && sourcePropertiesMap.isNotEmpty()) {
|
newImports.append("import io.swagger.annotations.ApiModelProperty\n")
|
}
|
if (!originalContent.contains("import io.swagger.annotations.ApiModel") && apiModelAnnotation.isNotEmpty()) {
|
newImports.append("import io.swagger.annotations.ApiModel\n")
|
}
|
|
newContent = newContent.replace(imports, newImports.toString())
|
}
|
}
|
|
// 添加ApiModel类注解
|
if (apiModelAnnotation.isNotEmpty()) {
|
// 查找class关键字行
|
val classPattern = Pattern.compile("public\\s+class\\s+\\w+")
|
val classMatcher = classPattern.matcher(newContent)
|
|
if (classMatcher.find()) {
|
val classNameLine = classMatcher.group(0)
|
val startIndex = classMatcher.start()
|
val lines = newContent.lines()
|
|
// 查找类定义所在的行
|
var classLineIndex = 0
|
var currentPosition = 0
|
for ((i, line) in lines.withIndex()) {
|
if (currentPosition + line.length + 1 > startIndex) {
|
classLineIndex = i
|
break
|
}
|
currentPosition += line.length + 1
|
}
|
|
// 检查类定义行的前一行是否已经有ApiModel注解
|
if (classLineIndex > 0 && !lines[classLineIndex - 1].trim().startsWith("@ApiModel")) {
|
val updatedLines = lines.toMutableList()
|
updatedLines.add(classLineIndex, apiModelAnnotation)
|
newContent = updatedLines.joinToString("\n")
|
} else if (classLineIndex == 0) {
|
// 如果类定义在第一行,在前面添加注解
|
newContent = apiModelAnnotation + "\n" + newContent
|
}
|
}
|
}
|
|
// 为每个Java属性添加对应的ApiModelProperty注解
|
targetPropertiesMap.forEach { (columnName, propertyName) ->
|
val annotation = sourcePropertiesMap[columnName]
|
if (annotation != null) {
|
// 查找属性定义行
|
val propertyPattern = Pattern.compile("(@Column\\(name = \"$columnName\"\\))\\s+private \\w+ $propertyName;")
|
val propertyMatcher = propertyPattern.matcher(newContent)
|
|
if (propertyMatcher.find()) {
|
// 检查是否已经存在ApiModelProperty注解
|
val columnLine = propertyMatcher.group(0)
|
if (!columnLine.contains("@ApiModelProperty")) {
|
// 使用正则表达式替换,确保类型保持不变
|
val updatedPattern =
|
Pattern.compile("@Column\\(name = \"$columnName\"\\)\\s+(private \\w+) $propertyName;")
|
val updatedMatcher = updatedPattern.matcher(newContent)
|
if (updatedMatcher.find()) {
|
val propertyTypePart = updatedMatcher.group(1)
|
val properlyUpdatedLine =
|
"@Column(name = \"$columnName\")\n $annotation\n $propertyTypePart $propertyName;"
|
newContent = newContent.replace(updatedMatcher.group(0), properlyUpdatedLine)
|
}
|
}
|
}
|
}
|
}
|
|
return newContent
|
}
|
|
/**
|
* 批量处理目录下的所有文件
|
* @param sourceDir 源文件所在目录
|
* @param targetDir 目标文件所在目录
|
*/
|
fun batchCopyAnnotations(sourceDir: String, targetDir: String) {
|
val sourceDirFile = File(sourceDir)
|
val targetDirFile = File(targetDir)
|
|
if (!sourceDirFile.exists() || !targetDirFile.exists()) {
|
println("指定的目录不存在")
|
return
|
}
|
|
// 获取源目录下的所有文件
|
val sourceFiles = sourceDirFile.walkTopDown().filter { it.isFile}
|
|
sourceFiles.forEach { sourceFile ->
|
// 查找对应的目标kt文件
|
val targetFileName = sourceFile.nameWithoutExtension + ".kt"
|
val targetFile = File(targetDirFile, targetFileName)
|
|
if (targetFile.exists()) {
|
copyAnnotations(sourceFile.absolutePath, targetFile.absolutePath)
|
return@forEach
|
}
|
|
// 查找对应的目标java文件
|
val targetFileName1 = sourceFile.nameWithoutExtension + ".java"
|
val targetFile1 = File(targetDirFile, targetFileName1)
|
|
if (targetFile1.exists()) {
|
copyAnnotations(sourceFile.absolutePath, targetFile1.absolutePath)
|
} else {
|
println("未找到对应的目标文件: $targetFileName1")
|
}
|
}
|
}
|
}
|
|
fun main() {
|
AnnotationCopyTool.copyAnnotations(
|
"C:\\work\\ideaProject\\supervision\\src\\main\\kotlin\\cn\\flightfeather\\supervision\\domain\\ds1\\entity2\\Evaluationsubrule" +
|
".java",
|
"C:\\work\\ideaProject\\supervision\\src\\main\\kotlin\\cn\\flightfeather\\supervision\\domain\\ds1\\entity\\Evaluationsubrule.kt"
|
)
|
// AnnotationCopyTool.batchCopyAnnotations(
|
// "C:\\work\\ideaProject\\supervision\\src\\main\\kotlin\\cn\\flightfeather\\supervision\\domain\\ds1\\entity2",
|
// "C:\\work\\ideaProject\\supervision\\src\\main\\kotlin\\cn\\flightfeather\\supervision\\domain\\ds1\\entity"
|
// )
|
}
|