All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.abelhu.protocol_bridge_processor.ProtocolProxyFileGenerate.kt Maven / Gradle / Ivy

There is a newer version: 1.0.7
Show newest version
package com.abelhu.protocol_bridge_processor

import com.abelhu.protocalbridge.Protocol
import com.squareup.kotlinpoet.*
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import javax.annotation.processing.Filer
import javax.lang.model.element.Element

class ProtocolProxyFileGenerate(private val filer: Filer, private val element: Element, private val protocols: List) {
    private val protocolName = ClassName("${element.enclosingElement}", listOf("${element.simpleName}"))
    private val className = ClassName("${element.enclosingElement}", "${element.simpleName}${ProtocolProcessor.SUFFIX}")
    fun generateFile() {
        FileSpec.builder(className.packageName, className.simpleName).addType(generateClass(element, protocols)).build().writeTo(filer)
    }

    private fun generateClass(element: Element, protocols: List): TypeSpec {
        return TypeSpec.classBuilder(className.simpleName).primaryConstructor(FunSpec.constructorBuilder().addModifiers(KModifier.PRIVATE).build())
                .addType(generateInstance(className))
                .addProperty(PropertySpec.builder("map", generateHashMap(String::class.asTypeName())).initializer("HashMap()").build())
                .addInitializerBlock(generateInit(protocols))
                .addFunction(generateGetProtocolFunction())
                .build()
    }

    private fun generateInit(protocols: List): CodeBlock {
        return CodeBlock.builder().apply {
            protocols.forEach { protocol ->
                addStatement("map[\"${protocol.getAnnotation(Protocol::class.java).protocol}\"] = \"${protocol}\"")
            }
        }.build()
    }

    private fun generateGetProtocolFunction(): FunSpec {
        return FunSpec.builder("getProtocol")
                .addParameter("protocol", String::class)
                .addParameter(ParameterSpec.builder("data", String::class).defaultValue("\"\"").build())
                .addParameter(ParameterSpec.builder("types", ARRAY.parameterizedBy(ClassName("java.lang", "Class")
                        .parameterizedBy(WildcardTypeName.producerOf(ClassName("kotlin", "Any"))))).defaultValue("emptyArray()").build())
                .addParameter(ParameterSpec.builder("params", ARRAY.parameterizedBy(WildcardTypeName.producerOf(ClassName("kotlin", "Any"))))
                        .defaultValue("emptyArray()").build())
                .addCode("""
        return map[protocol]?.let { clazzName ->
            val clazz = Class.forName(clazzName)
            val constructor = if (data.isEmpty()) clazz.getConstructor(*types) else clazz.getConstructor(data::class.java, *types)
            val protocolInstance = if (data.isEmpty()) constructor.newInstance(*params) else constructor.newInstance(data, *params)
            protocolInstance as? JsProtocol
        }
        """.trimMargin()).returns((protocolName as TypeName).copy(true))
                .addKdoc("""
                         有多个参数的情况
                         如果需要传多个参数,需要把对应的类型和数据一起传过来
                         
                         @param protocol 协议名称
                         @param data 数据,需要转变成对应数据类型的数据,如果没有,获取无参的构造函数
                         @param types 不需要转变的数据的数据类型
                         @param params 不需要转变的数据
                """.trimIndent())
                .build()
    }

    private fun generateInstance(className: ClassName): TypeSpec {
        return TypeSpec.companionObjectBuilder().apply {
            addProperty(PropertySpec.builder("Instance", className).apply {
                delegate(CodeBlock.builder().beginControlFlow("lazy").addStatement("${className.simpleName}()").endControlFlow().build())
            }.build())
        }.build()
    }

    private fun generateHashMap(type: TypeName) = generateHashMap(type, type)

    private fun generateHashMap(key: TypeName, value: TypeName) = ClassName("kotlin.collections", "HashMap").parameterizedBy(key, value)

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy