mirror of
https://github.com/tursom/TursomServer.git
synced 2025-03-13 19:30:10 +08:00
update
This commit is contained in:
parent
3fb22b30bb
commit
b5150955a0
@ -20,6 +20,7 @@ include("ts-core:ts-json")
|
|||||||
include("ts-core:ts-xml")
|
include("ts-core:ts-xml")
|
||||||
include("ts-core:ts-async-http")
|
include("ts-core:ts-async-http")
|
||||||
include("ts-core:ts-proxy")
|
include("ts-core:ts-proxy")
|
||||||
|
include("ts-core:ts-reflect")
|
||||||
include("ts-socket")
|
include("ts-socket")
|
||||||
include("ts-web")
|
include("ts-web")
|
||||||
include("ts-web:ts-web-netty")
|
include("ts-web:ts-web-netty")
|
||||||
|
@ -30,12 +30,12 @@ import javax.mail.internet.MimeMultipart
|
|||||||
data class EmailData(
|
data class EmailData(
|
||||||
var host: String?, var port: Int?, var name: String?, var password: String?, var from: String?,
|
var host: String?, var port: Int?, var name: String?, var password: String?, var from: String?,
|
||||||
var to: String?, var subject: String?, var html: String? = null, var text: String? = null,
|
var to: String?, var subject: String?, var html: String? = null, var text: String? = null,
|
||||||
var image: Collection<Image>? = null, var attachment: Collection<DataSource>? = null
|
var image: Collection<Image>? = null, var attachment: Collection<DataSource>? = null,
|
||||||
) {
|
) : Mail {
|
||||||
/**
|
/**
|
||||||
* 发送邮件
|
* 发送邮件
|
||||||
*/
|
*/
|
||||||
fun send(transportListener: TransportListener? = null) {
|
override fun send(transportListener: TransportListener?) {
|
||||||
if (host == null || port == null || name == null || password == null || from == null || to == null || subject == null) return
|
if (host == null || port == null || name == null || password == null || from == null || to == null || subject == null) return
|
||||||
val props = Properties()
|
val props = Properties()
|
||||||
// props["mail.debug"] = "true" // 开启debug调试
|
// props["mail.debug"] = "true" // 开启debug调试
|
||||||
@ -69,7 +69,7 @@ data class EmailData(
|
|||||||
html: String?,
|
html: String?,
|
||||||
text: String?,
|
text: String?,
|
||||||
image: Collection<Image>?,
|
image: Collection<Image>?,
|
||||||
attachment: Collection<DataSource>?
|
attachment: Collection<DataSource>?,
|
||||||
): MimeMessage {
|
): MimeMessage {
|
||||||
//邮件内容部分
|
//邮件内容部分
|
||||||
val msg = MimeMessage(session)
|
val msg = MimeMessage(session)
|
||||||
|
@ -15,9 +15,8 @@ data class GroupEmailData(
|
|||||||
var host: String?, var port: Int?, var name: String?, var password: String?, var from: String?,
|
var host: String?, var port: Int?, var name: String?, var password: String?, var from: String?,
|
||||||
var to: Collection<String>?, var subject: String?, var html: String? = null, var text: String? = null,
|
var to: Collection<String>?, var subject: String?, var html: String? = null, var text: String? = null,
|
||||||
var image: Collection<Image>? = null, var attachment: Collection<DataSource>? = null,
|
var image: Collection<Image>? = null, var attachment: Collection<DataSource>? = null,
|
||||||
) {
|
) : Mail {
|
||||||
fun send() = send(null)
|
override fun send(transportListener: TransportListener?) {
|
||||||
fun send(transportListener: TransportListener?) {
|
|
||||||
if (host == null || port == null || name == null || password == null || from == null || to?.isEmpty() != false || subject == null) return
|
if (host == null || port == null || name == null || password == null || from == null || to?.isEmpty() != false || subject == null) return
|
||||||
val props = Properties()
|
val props = Properties()
|
||||||
// props["mail.debug"] = "true" // 开启debug调试
|
// props["mail.debug"] = "true" // 开启debug调试
|
||||||
|
7
ts-core/ts-mail/src/main/kotlin/cn/tursom/mail/Mail.kt
Normal file
7
ts-core/ts-mail/src/main/kotlin/cn/tursom/mail/Mail.kt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package cn.tursom.mail
|
||||||
|
|
||||||
|
import javax.mail.event.TransportListener
|
||||||
|
|
||||||
|
interface Mail {
|
||||||
|
fun send(transportListener: TransportListener? = null)
|
||||||
|
}
|
@ -4,6 +4,7 @@ import com.sun.mail.util.MailSSLSocketFactory
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.mail.Address
|
import javax.mail.Address
|
||||||
import javax.mail.Session
|
import javax.mail.Session
|
||||||
|
import javax.mail.event.TransportListener
|
||||||
import javax.mail.internet.InternetAddress
|
import javax.mail.internet.InternetAddress
|
||||||
|
|
||||||
data class MultipleEmailData(
|
data class MultipleEmailData(
|
||||||
@ -12,9 +13,9 @@ data class MultipleEmailData(
|
|||||||
var name: String?,
|
var name: String?,
|
||||||
var password: String?,
|
var password: String?,
|
||||||
var from: String?,
|
var from: String?,
|
||||||
var to: Collection<MailStructure>?
|
var to: Collection<MailStructure>?,
|
||||||
) {
|
) : Mail {
|
||||||
fun send() {
|
override fun send(transportListener: TransportListener?) {
|
||||||
val from = from ?: return
|
val from = from ?: return
|
||||||
val props = Properties()
|
val props = Properties()
|
||||||
// props["mail.debug"] = "true" // 开启debug调试
|
// props["mail.debug"] = "true" // 开启debug调试
|
||||||
@ -32,6 +33,7 @@ data class MultipleEmailData(
|
|||||||
//发送邮件
|
//发送邮件
|
||||||
val transport = session.transport
|
val transport = session.transport
|
||||||
transport.connect(host, name, password)
|
transport.connect(host, name, password)
|
||||||
|
transportListener?.apply { transport.addTransportListener(this) }
|
||||||
to?.forEach { (to, subject, html, text, image, attachment) ->
|
to?.forEach { (to, subject, html, text, image, attachment) ->
|
||||||
//邮件内容部分
|
//邮件内容部分
|
||||||
val msg = EmailData.getMsg(session, from, subject, html, text, image, attachment)
|
val msg = EmailData.getMsg(session, from, subject, html, text, image, attachment)
|
||||||
|
22
ts-core/ts-reflect/build.gradle.kts
Normal file
22
ts-core/ts-reflect/build.gradle.kts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
`maven-publish`
|
||||||
|
id("ts-gradle")
|
||||||
|
kotlin("plugin.allopen") version "1.5.21"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(project(":ts-core"))
|
||||||
|
api(project(":ts-core:ts-log"))
|
||||||
|
testApi(group = "junit", name = "junit", version = "4.13.2")
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacts {
|
||||||
|
archives(tasks["kotlinSourcesJar"])
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<KotlinCompile>().configureEach {
|
||||||
|
kotlinOptions.freeCompilerArgs += "-Xjvm-default=all"
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
|
package cn.tursom.reflect
|
||||||
|
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import java.lang.reflect.Method
|
||||||
|
|
||||||
|
inline fun <R> Class<*>.getDeclaredMethod(
|
||||||
|
returnType: Class<*>,
|
||||||
|
getMethod: Class<*>.() -> Method?,
|
||||||
|
staticReturn: (method: Method) -> R,
|
||||||
|
): R? {
|
||||||
|
val method = this.getDeclaredMethod(returnType, false, getMethod)
|
||||||
|
if (method != null) return staticReturn(method)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified R : Any> Any.getMethod(
|
||||||
|
name: String,
|
||||||
|
clazz: Class<*> = javaClass,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name)
|
||||||
|
},
|
||||||
|
): (() -> R)? = clazz.getDeclaredMethod(returnType, getMethod) { method ->
|
||||||
|
{ method(this).uncheckedCast() }
|
||||||
|
} ?: clazz.getStaticDeclaredMethod(name, returnType, getMethod)
|
||||||
|
|
||||||
|
inline fun <reified R : Any, reified T1> Any.getMethod1(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
arg1Type: Class<T1> = T1::class.java,
|
||||||
|
clazz: Class<*> = javaClass,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name, arg1Type)
|
||||||
|
},
|
||||||
|
): ((T1) -> R)? = clazz.getDeclaredMethod(returnType, getMethod) { method ->
|
||||||
|
{ method(this, it).uncheckedCast() }
|
||||||
|
} ?: clazz.getStaticDeclaredMethod1(name, returnType, arg1Type, getMethod)
|
||||||
|
|
||||||
|
inline fun <reified R : Any, reified T1, reified T2> Any.getMethod2(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
arg1Type: Class<T1> = T1::class.java,
|
||||||
|
arg2Type: Class<T2> = T2::class.java,
|
||||||
|
clazz: Class<*> = javaClass,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name, arg1Type, arg2Type)
|
||||||
|
},
|
||||||
|
): ((T1, T2) -> R)? = clazz.getDeclaredMethod(returnType, getMethod) { method ->
|
||||||
|
{ v1, v2 -> method(this, v1, v2).uncheckedCast() }
|
||||||
|
} ?: clazz.getStaticDeclaredMethod2(name, returnType, arg1Type, arg2Type, getMethod)
|
||||||
|
|
||||||
|
inline fun <reified R : Any, reified T1, reified T2, reified T3> Any.getMethod3(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
arg1Type: Class<T1> = T1::class.java,
|
||||||
|
arg2Type: Class<T2> = T2::class.java,
|
||||||
|
arg3Type: Class<T3> = T3::class.java,
|
||||||
|
clazz: Class<*> = javaClass,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name, arg1Type, arg2Type, arg3Type)
|
||||||
|
},
|
||||||
|
): ((T1, T2, T3) -> R)? = clazz.getDeclaredMethod(returnType, getMethod) { method ->
|
||||||
|
{ v1, v2, v3 -> method(this, v1, v2, v3).uncheckedCast() }
|
||||||
|
} ?: clazz.getStaticDeclaredMethod3(name, returnType, arg1Type, arg2Type, arg3Type, getMethod)
|
||||||
|
|
||||||
|
inline fun <reified R : Any, reified T1, reified T2, reified T3, reified T4> Any.getMethod4(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
arg1Type: Class<T1> = T1::class.java,
|
||||||
|
arg2Type: Class<T2> = T2::class.java,
|
||||||
|
arg3Type: Class<T3> = T3::class.java,
|
||||||
|
arg4Type: Class<T4> = T4::class.java,
|
||||||
|
clazz: Class<*> = javaClass,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name, arg1Type, arg2Type, arg3Type, arg4Type)
|
||||||
|
},
|
||||||
|
): ((T1, T2, T3, T4) -> R)? = clazz.getDeclaredMethod(returnType, getMethod) { method ->
|
||||||
|
{ v1, v2, v3, v4 -> method(this, v1, v2, v3, v4).uncheckedCast() }
|
||||||
|
} ?: clazz.getStaticDeclaredMethod4(name, returnType, arg1Type, arg2Type, arg3Type, arg4Type, getMethod)
|
||||||
|
|
||||||
|
inline fun <reified R, reified T1, reified T2, reified T3, reified T4, reified T5> Any.getMethod5(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
arg1Type: Class<T1> = T1::class.java,
|
||||||
|
arg2Type: Class<T2> = T2::class.java,
|
||||||
|
arg3Type: Class<T3> = T3::class.java,
|
||||||
|
arg4Type: Class<T4> = T4::class.java,
|
||||||
|
arg5Type: Class<T5> = T5::class.java,
|
||||||
|
clazz: Class<*> = javaClass,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name, arg1Type, arg2Type, arg3Type, arg4Type, arg5Type)
|
||||||
|
},
|
||||||
|
): ((T1, T2, T3, T4, T5) -> R)? = clazz.getDeclaredMethod(returnType, getMethod) { method ->
|
||||||
|
{ v1, v2, v3, v4, v5 -> method(this, v1, v2, v3, v4, v5).uncheckedCast() }
|
||||||
|
} ?: clazz.getStaticDeclaredMethod5(name, returnType, arg1Type, arg2Type, arg3Type, arg4Type, arg5Type, getMethod)
|
||||||
|
|
@ -0,0 +1,76 @@
|
|||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
|
package cn.tursom.reflect
|
||||||
|
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import java.lang.reflect.Method
|
||||||
|
|
||||||
|
inline fun <This, reified R> Class<*>.getMethod(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<out R> = R::class.java,
|
||||||
|
getMethod: Class<*>.() -> Method? = { getMethodFully(name) },
|
||||||
|
): (This.() -> R)? = getDeclaredMethod(returnType, getMethod) { method ->
|
||||||
|
{ method(this).uncheckedCast() }
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <This, reified R, reified T1> Class<*>.getMethod1(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<out R> = R::class.java,
|
||||||
|
arg1Type: Class<in T1> = T1::class.java,
|
||||||
|
getMethod: Class<*>.() -> Method? = { getMethodFully(name, arg1Type) },
|
||||||
|
): (This.(T1) -> R)? = getDeclaredMethod(returnType, getMethod) { method ->
|
||||||
|
{ method(this, it).uncheckedCast() }
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <This, reified R, reified T1, reified T2> Class<*>.getMethod2(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<out R> = R::class.java,
|
||||||
|
arg1Type: Class<in T1> = T1::class.java,
|
||||||
|
arg2Type: Class<in T2> = T2::class.java,
|
||||||
|
getMethod: Class<*>.() -> Method? = { getMethodFully(name, arg1Type, arg2Type) },
|
||||||
|
): (This.(T1, T2) -> R)? = getDeclaredMethod(returnType, getMethod) { method ->
|
||||||
|
{ v1, v2 -> method(this, v1, v2).uncheckedCast() }
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <This, reified R, reified T1, reified T2, reified T3> Class<*>.getMethod3(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<out R> = R::class.java,
|
||||||
|
arg1Type: Class<in T1> = T1::class.java,
|
||||||
|
arg2Type: Class<in T2> = T2::class.java,
|
||||||
|
arg3Type: Class<in T3> = T3::class.java,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name, arg1Type, arg2Type, arg3Type)
|
||||||
|
},
|
||||||
|
): (This.(T1, T2, T3) -> R)? = getDeclaredMethod(returnType, getMethod) { method ->
|
||||||
|
{ v1, v2, v3 -> method(this, v1, v2, v3).uncheckedCast() }
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <This, reified R, reified T1, reified T2, reified T3, reified T4> Class<*>.getMethod4(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<out R> = R::class.java,
|
||||||
|
arg1Type: Class<in T1> = T1::class.java,
|
||||||
|
arg2Type: Class<in T2> = T2::class.java,
|
||||||
|
arg3Type: Class<in T3> = T3::class.java,
|
||||||
|
arg4Type: Class<in T4> = T4::class.java,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name, arg1Type, arg2Type, arg3Type, arg4Type)
|
||||||
|
},
|
||||||
|
): (This.(T1, T2, T3, T4) -> R)? = getDeclaredMethod(returnType, getMethod) { method ->
|
||||||
|
{ v1, v2, v3, v4 -> method(this, v1, v2, v3, v4).uncheckedCast() }
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <This, reified R, reified T1, reified T2, reified T3, reified T4, reified T5> Class<*>.getMethod5(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<out R> = R::class.java,
|
||||||
|
arg1Type: Class<in T1> = T1::class.java,
|
||||||
|
arg2Type: Class<in T2> = T2::class.java,
|
||||||
|
arg3Type: Class<in T3> = T3::class.java,
|
||||||
|
arg4Type: Class<in T4> = T4::class.java,
|
||||||
|
arg5Type: Class<in T5> = T5::class.java,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name, arg1Type, arg2Type, arg3Type, arg4Type)
|
||||||
|
},
|
||||||
|
): (This.(T1, T2, T3, T4, T5) -> R)? = getDeclaredMethod(returnType, getMethod) { method ->
|
||||||
|
{ v1, v2, v3, v4, v5 -> method(this, v1, v2, v3, v4, v5).uncheckedCast() }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,198 @@
|
|||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
|
package cn.tursom.reflect
|
||||||
|
|
||||||
|
import cn.tursom.core.allMethodsSequence
|
||||||
|
import cn.tursom.core.companionObjectInstanceOrNull
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import java.lang.reflect.Method
|
||||||
|
|
||||||
|
inline fun <reified T> getType() = T::class.java
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
println(Int::class.java canCast getType<Byte>())
|
||||||
|
println(Int::class.java canCast getType<Int>())
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun Class<*>.canCast(target: Class<*>): Boolean {
|
||||||
|
return (target == Any::class.java || this == target) || (
|
||||||
|
(this == Void.TYPE || this == Void::class.java) &&
|
||||||
|
(target == Unit::class.java || target == Void.TYPE || target == Void::class.java)
|
||||||
|
) || (
|
||||||
|
(this == Byte::class.java || this == getType<Byte>()) &&
|
||||||
|
(target == Byte::class.java || target == getType<Byte>())
|
||||||
|
) || (
|
||||||
|
(this == Short::class.java || this == getType<Short>()) &&
|
||||||
|
(target == Short::class.java || target == getType<Short>())
|
||||||
|
) || (
|
||||||
|
(this == Int::class.java || this == getType<Int>()) &&
|
||||||
|
(target == Int::class.java || target == getType<Int>())
|
||||||
|
) || (
|
||||||
|
(this == Long::class.java || this == getType<Long>()) &&
|
||||||
|
(target == Long::class.java || target == getType<Long>())
|
||||||
|
) || (
|
||||||
|
(this == Float::class.java || this == getType<Float>()) &&
|
||||||
|
(target == Float::class.java || target == getType<Float>())
|
||||||
|
) || (
|
||||||
|
(this == Double::class.java || this == getType<Double>()) &&
|
||||||
|
(target == Double::class.java || target == getType<Double>())
|
||||||
|
) || (
|
||||||
|
(this == Boolean::class.java || this == getType<Boolean>()) &&
|
||||||
|
(target == Boolean::class.java || target == getType<Boolean>())
|
||||||
|
) || (
|
||||||
|
(this == Char::class.java || this == getType<Char>()) &&
|
||||||
|
(target == Char::class.java || target == getType<Char>())
|
||||||
|
) || target.isAssignableFrom(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Method.match(name: String, vararg type: Class<*>): Boolean {
|
||||||
|
if (this.name != name) return false
|
||||||
|
if (this.parameterTypes.size != type.size) return false
|
||||||
|
this.parameterTypes.forEachIndexed { index, clazz ->
|
||||||
|
if (!(type[index] canCast clazz)) return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Class<*>.getFirstMatchMethod(
|
||||||
|
name: String,
|
||||||
|
vararg type: Class<*>,
|
||||||
|
): Method? {
|
||||||
|
allMethodsSequence.forEach { method ->
|
||||||
|
if (method.match(name, *type)) {
|
||||||
|
return method
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Class<*>.getMethodFully(
|
||||||
|
name: String,
|
||||||
|
vararg type: Class<*>,
|
||||||
|
): Method? {
|
||||||
|
val scanMethod = scanMethod(name, *type)
|
||||||
|
return (scanMethod.firstOrNull { method ->
|
||||||
|
method.parameterTypes.forEachIndexed { index, clazz ->
|
||||||
|
if (type[index] != clazz) return@firstOrNull false
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} ?: scanMethod.firstOrNull())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Class<*>.scanMethod(
|
||||||
|
name: String,
|
||||||
|
vararg type: Class<*>,
|
||||||
|
): List<Method> {
|
||||||
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
|
return buildList {
|
||||||
|
allMethodsSequence.forEach { method ->
|
||||||
|
if (method.match(name, *type)) add(method)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun Class<*>.getDeclaredMethod(
|
||||||
|
returnType: Class<*>,
|
||||||
|
isStatic: Boolean = true,
|
||||||
|
getMethod: Class<*>.() -> Method?,
|
||||||
|
) = try {
|
||||||
|
val method = getMethod()
|
||||||
|
method?.isAccessible = true
|
||||||
|
if (method != null && method.isStatic() == isStatic && method.returnType canCast returnType) method
|
||||||
|
else null
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <R> Class<*>.getStaticDeclaredMethod(
|
||||||
|
returnType: Class<*>,
|
||||||
|
getMethod: Class<*>.() -> Method?,
|
||||||
|
staticReturn: (method: Method, companionObjectInstance: Any?) -> R,
|
||||||
|
): R? {
|
||||||
|
val method = getDeclaredMethod(returnType, true, getMethod)
|
||||||
|
if (method != null) return staticReturn(method, null)
|
||||||
|
|
||||||
|
val companionObjectInstance = kotlin.companionObjectInstanceOrNull ?: return null
|
||||||
|
val companionObjectClazz = companionObjectInstance.javaClass
|
||||||
|
val companionMethod = companionObjectClazz.getDeclaredMethod(returnType, false, getMethod)
|
||||||
|
if (companionMethod != null) return staticReturn(companionMethod, companionObjectInstance)
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified R : Any> Class<*>.getStaticDeclaredMethod(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name)
|
||||||
|
},
|
||||||
|
): (() -> R)? = getStaticDeclaredMethod(
|
||||||
|
returnType, getMethod
|
||||||
|
) { method, companion -> { method(companion).uncheckedCast() } }
|
||||||
|
|
||||||
|
inline fun <reified R, reified T1> Class<*>.getStaticDeclaredMethod1(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
arg1Type: Class<T1> = T1::class.java,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name, arg1Type)
|
||||||
|
},
|
||||||
|
): ((T1) -> R)? = getStaticDeclaredMethod(
|
||||||
|
returnType, getMethod
|
||||||
|
) { method, companion -> { v1 -> method(companion, v1).uncheckedCast() } }
|
||||||
|
|
||||||
|
inline fun <reified R, reified T1, reified T2> Class<*>.getStaticDeclaredMethod2(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
arg1Type: Class<T1> = T1::class.java,
|
||||||
|
arg2Type: Class<T2> = T2::class.java,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name, arg1Type, arg2Type)
|
||||||
|
},
|
||||||
|
): ((T1, T2) -> R)? = getStaticDeclaredMethod(
|
||||||
|
returnType, getMethod
|
||||||
|
) { method, companion -> { v1, v2 -> method(companion, v1, v2).uncheckedCast() } }
|
||||||
|
|
||||||
|
inline fun <reified R, reified T1, reified T2, reified T3> Class<*>.getStaticDeclaredMethod3(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
arg1Type: Class<T1> = T1::class.java,
|
||||||
|
arg2Type: Class<T2> = T2::class.java,
|
||||||
|
arg3Type: Class<T3> = T3::class.java,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name, arg1Type, arg2Type, arg3Type)
|
||||||
|
},
|
||||||
|
): ((T1, T2, T3) -> R)? = getStaticDeclaredMethod(
|
||||||
|
returnType, getMethod
|
||||||
|
) { method, companion -> { v1, v2, v3 -> method(companion, v1, v2, v3).uncheckedCast() } }
|
||||||
|
|
||||||
|
inline fun <reified R, reified T1, reified T2, reified T3, reified T4> Class<*>.getStaticDeclaredMethod4(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
arg1Type: Class<T1> = T1::class.java,
|
||||||
|
arg2Type: Class<T2> = T2::class.java,
|
||||||
|
arg3Type: Class<T3> = T3::class.java,
|
||||||
|
arg4Type: Class<T4> = T4::class.java,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name, arg1Type, arg2Type, arg3Type, arg4Type)
|
||||||
|
},
|
||||||
|
): ((T1, T2, T3, T4) -> R)? = getStaticDeclaredMethod(
|
||||||
|
returnType, getMethod
|
||||||
|
) { method, companion -> { v1, v2, v3, v4 -> method(companion, v1, v2, v3, v4).uncheckedCast() } }
|
||||||
|
|
||||||
|
inline fun <reified R, reified T1, reified T2, reified T3, reified T4, reified T5> Class<*>.getStaticDeclaredMethod5(
|
||||||
|
name: String,
|
||||||
|
returnType: Class<R> = R::class.java,
|
||||||
|
arg1Type: Class<T1> = T1::class.java,
|
||||||
|
arg2Type: Class<T2> = T2::class.java,
|
||||||
|
arg3Type: Class<T3> = T3::class.java,
|
||||||
|
arg4Type: Class<T4> = T4::class.java,
|
||||||
|
arg5Type: Class<T5> = T5::class.java,
|
||||||
|
getMethod: Class<*>.() -> Method? = {
|
||||||
|
getMethodFully(name, arg1Type, arg2Type, arg3Type, arg4Type, arg5Type)
|
||||||
|
},
|
||||||
|
): ((T1, T2, T3, T4, T5) -> R)? = getStaticDeclaredMethod(
|
||||||
|
returnType, getMethod
|
||||||
|
) { method, companion -> { v1, v2, v3, v4, v5 -> method(companion, v1, v2, v3, v4, v5).uncheckedCast() } }
|
||||||
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
|||||||
|
package cn.tursom.reflect
|
||||||
|
|
||||||
|
import cn.tursom.core.UncheckedCast
|
||||||
|
import cn.tursom.core.Unsafe
|
||||||
|
import cn.tursom.core.cast
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
object InstantAllocator {
|
||||||
|
enum class AllocateFunction { INSTANCE, UNSAFE, KOBJECT, NONE }
|
||||||
|
|
||||||
|
private val allocateFunctionMap = ConcurrentHashMap<Class<*>, AllocateFunction>()
|
||||||
|
|
||||||
|
@Throws(NoSuchMethodException::class)
|
||||||
|
operator fun <T> invoke(clazz: Class<out T>, unsafe: Boolean = true): T = get(clazz, unsafe)
|
||||||
|
|
||||||
|
@Throws(NoSuchMethodException::class)
|
||||||
|
inline operator fun <reified T : Any> invoke(unsafe: Boolean = true): T = get(T::class.java, unsafe)
|
||||||
|
|
||||||
|
@Throws(NoSuchMethodException::class)
|
||||||
|
operator fun <T : Any> get(clazz: KClass<out T>, unsafe: Boolean = true): T = get(clazz.java, unsafe)
|
||||||
|
|
||||||
|
@Throws(NoSuchMethodException::class)
|
||||||
|
operator fun <T> get(clazz: Class<out T>, unsafe: Boolean = true): T {
|
||||||
|
return when (allocateFunctionMap[clazz]) {
|
||||||
|
null -> try {
|
||||||
|
val newInstance = clazz.newInstance()
|
||||||
|
allocateFunctionMap[clazz] = AllocateFunction.INSTANCE
|
||||||
|
newInstance
|
||||||
|
} catch (e: Exception) {
|
||||||
|
val kClass = clazz.kotlin
|
||||||
|
val objectInstance = kClass.objectInstance
|
||||||
|
if (objectInstance != null) {
|
||||||
|
allocateFunctionMap[clazz] = AllocateFunction.KOBJECT
|
||||||
|
objectInstance
|
||||||
|
} else if (unsafe) try {
|
||||||
|
allocateFunctionMap[clazz] = AllocateFunction.UNSAFE
|
||||||
|
@OptIn(UncheckedCast::class)
|
||||||
|
Unsafe.unsafe.allocateInstance(clazz).cast<T>()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
allocateFunctionMap[clazz] = AllocateFunction.NONE
|
||||||
|
throw NoSuchMethodException("${clazz.name}:<init>()")
|
||||||
|
} else {
|
||||||
|
throw NoSuchMethodException("${clazz.name}:<init>()")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AllocateFunction.INSTANCE -> clazz.newInstance()
|
||||||
|
AllocateFunction.UNSAFE -> if (unsafe) {
|
||||||
|
Unsafe.unsafe.allocateInstance(clazz).uncheckedCast<T>()
|
||||||
|
} else {
|
||||||
|
throw NoSuchMethodException("${clazz.name}:<init>()")
|
||||||
|
}
|
||||||
|
AllocateFunction.KOBJECT -> clazz.kotlin.objectInstance!!
|
||||||
|
AllocateFunction.NONE -> throw NoSuchMethodException("${clazz.name}:<init>()")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
272
ts-core/ts-reflect/src/main/kotlin/cn/tursom/reflect/Members.kt
Normal file
272
ts-core/ts-reflect/src/main/kotlin/cn/tursom/reflect/Members.kt
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
|
package cn.tursom.reflect
|
||||||
|
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
import java.lang.reflect.Member
|
||||||
|
import java.lang.reflect.Modifier
|
||||||
|
|
||||||
|
|
||||||
|
private val fieldModifiersField: Field? = try {
|
||||||
|
Field::class.java.getDeclaredField("modifiers").apply {
|
||||||
|
isAccessible = true
|
||||||
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
var fieldModifiers: (Field, Int) -> Unit = { field, modifer ->
|
||||||
|
fieldModifiersField!!.set(field, modifer)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Field.public: Boolean
|
||||||
|
get() = Modifier.isPublic(this.modifiers)
|
||||||
|
set(value) {
|
||||||
|
val modifier = Modifier.PUBLIC
|
||||||
|
fieldModifiers(
|
||||||
|
this,
|
||||||
|
if (value) {
|
||||||
|
modifiers or modifier
|
||||||
|
} else {
|
||||||
|
modifiers and modifier.inv()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Field.private: Boolean
|
||||||
|
get() = Modifier.isPrivate(this.modifiers)
|
||||||
|
set(value) {
|
||||||
|
val modifier = Modifier.PRIVATE
|
||||||
|
fieldModifiers(
|
||||||
|
this,
|
||||||
|
if (value) {
|
||||||
|
modifiers or modifier
|
||||||
|
} else {
|
||||||
|
modifiers and modifier.inv()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Field.protected: Boolean
|
||||||
|
get() = Modifier.isProtected(this.modifiers)
|
||||||
|
set(value) {
|
||||||
|
val modifier = Modifier.PROTECTED
|
||||||
|
fieldModifiers(
|
||||||
|
this,
|
||||||
|
if (value) {
|
||||||
|
modifiers or modifier
|
||||||
|
} else {
|
||||||
|
modifiers and modifier.inv()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Field.static: Boolean
|
||||||
|
get() = Modifier.isStatic(this.modifiers)
|
||||||
|
set(value) {
|
||||||
|
val modifier = Modifier.STATIC
|
||||||
|
fieldModifiers(
|
||||||
|
this,
|
||||||
|
if (value) {
|
||||||
|
modifiers or modifier
|
||||||
|
} else {
|
||||||
|
modifiers and modifier.inv()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Field.final: Boolean
|
||||||
|
get() = Modifier.isFinal(this.modifiers)
|
||||||
|
set(value) {
|
||||||
|
val modifier = Modifier.FINAL
|
||||||
|
fieldModifiers(
|
||||||
|
this,
|
||||||
|
if (value) {
|
||||||
|
modifiers or modifier
|
||||||
|
} else {
|
||||||
|
modifiers and modifier.inv()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Field.synchronized: Boolean
|
||||||
|
get() = Modifier.isSynchronized(this.modifiers)
|
||||||
|
set(value) {
|
||||||
|
val modifier = Modifier.SYNCHRONIZED
|
||||||
|
fieldModifiers(
|
||||||
|
this,
|
||||||
|
if (value) {
|
||||||
|
modifiers or modifier
|
||||||
|
} else {
|
||||||
|
modifiers and modifier.inv()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Field.volatile: Boolean
|
||||||
|
get() = Modifier.isVolatile(this.modifiers)
|
||||||
|
set(value) {
|
||||||
|
val modifier = Modifier.VOLATILE
|
||||||
|
fieldModifiers(
|
||||||
|
this,
|
||||||
|
if (value) {
|
||||||
|
modifiers or modifier
|
||||||
|
} else {
|
||||||
|
modifiers and modifier.inv()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Field.transient: Boolean
|
||||||
|
get() = Modifier.isTransient(this.modifiers)
|
||||||
|
set(value) {
|
||||||
|
val modifier = Modifier.TRANSIENT
|
||||||
|
fieldModifiers(
|
||||||
|
this,
|
||||||
|
if (value) {
|
||||||
|
modifiers or modifier
|
||||||
|
} else {
|
||||||
|
modifiers and modifier.inv()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Field.native: Boolean
|
||||||
|
get() = Modifier.isNative(this.modifiers)
|
||||||
|
set(value) {
|
||||||
|
val modifier = Modifier.NATIVE
|
||||||
|
fieldModifiers(
|
||||||
|
this,
|
||||||
|
if (value) {
|
||||||
|
modifiers or modifier
|
||||||
|
} else {
|
||||||
|
modifiers and modifier.inv()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Field.`interface`: Boolean
|
||||||
|
get() = Modifier.isInterface(this.modifiers)
|
||||||
|
set(value) {
|
||||||
|
val modifier = Modifier.INTERFACE
|
||||||
|
fieldModifiers(
|
||||||
|
this,
|
||||||
|
if (value) {
|
||||||
|
modifiers or modifier
|
||||||
|
} else {
|
||||||
|
modifiers and modifier.inv()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Field.abstract: Boolean
|
||||||
|
get() = Modifier.isAbstract(this.modifiers)
|
||||||
|
set(value) {
|
||||||
|
val modifier = Modifier.ABSTRACT
|
||||||
|
fieldModifiers(
|
||||||
|
this,
|
||||||
|
if (value) {
|
||||||
|
modifiers or modifier
|
||||||
|
} else {
|
||||||
|
modifiers and modifier.inv()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Field.strict: Boolean
|
||||||
|
get() = Modifier.isStrict(this.modifiers)
|
||||||
|
set(value) {
|
||||||
|
val modifier = Modifier.STRICT
|
||||||
|
fieldModifiers(
|
||||||
|
this,
|
||||||
|
if (value) {
|
||||||
|
modifiers or modifier
|
||||||
|
} else {
|
||||||
|
modifiers and modifier.inv()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Member.isPublic(): Boolean {
|
||||||
|
return Modifier.isPublic(this.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Member.isPrivate(): Boolean {
|
||||||
|
return Modifier.isPrivate(this.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Member.isProtected(): Boolean {
|
||||||
|
return Modifier.isProtected(this.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Member.isStatic(): Boolean {
|
||||||
|
return Modifier.isStatic(this.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Member.isFinal(): Boolean {
|
||||||
|
return Modifier.isFinal(this.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Member.isSynchronized(): Boolean {
|
||||||
|
return Modifier.isSynchronized(this.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Member.isVolatile(): Boolean {
|
||||||
|
return Modifier.isVolatile(this.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Member.isTransient(): Boolean {
|
||||||
|
return Modifier.isTransient(this.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Member.isNative(): Boolean {
|
||||||
|
return Modifier.isNative(this.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Member.isInterface(): Boolean {
|
||||||
|
return Modifier.isInterface(this.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Member.isAbstract(): Boolean {
|
||||||
|
return Modifier.isAbstract(this.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Member.isStrict(): Boolean {
|
||||||
|
return Modifier.isStrict(this.modifiers)
|
||||||
|
}
|
||||||
|
|
||||||
|
val Class<*>.isPublic: Boolean
|
||||||
|
get() = Modifier.isPublic(this.modifiers)
|
||||||
|
|
||||||
|
val Class<*>.isPrivate: Boolean
|
||||||
|
get() = Modifier.isPrivate(this.modifiers)
|
||||||
|
|
||||||
|
val Class<*>.isProtected: Boolean
|
||||||
|
get() = Modifier.isProtected(this.modifiers)
|
||||||
|
|
||||||
|
val Class<*>.isStatic: Boolean
|
||||||
|
get() = Modifier.isStatic(this.modifiers)
|
||||||
|
|
||||||
|
val Class<*>.isFinal: Boolean
|
||||||
|
get() = Modifier.isFinal(this.modifiers)
|
||||||
|
|
||||||
|
val Class<*>.isSynchronized: Boolean
|
||||||
|
get() = Modifier.isSynchronized(this.modifiers)
|
||||||
|
|
||||||
|
val Class<*>.isVolatile: Boolean
|
||||||
|
get() = Modifier.isVolatile(this.modifiers)
|
||||||
|
|
||||||
|
val Class<*>.isTransient: Boolean
|
||||||
|
get() = Modifier.isTransient(this.modifiers)
|
||||||
|
|
||||||
|
val Class<*>.isNative: Boolean
|
||||||
|
get() = Modifier.isNative(this.modifiers)
|
||||||
|
|
||||||
|
//val Class<*>.isInterface: Boolean
|
||||||
|
// get() = Modifier.isInterface(this.modifiers)
|
||||||
|
|
||||||
|
val Class<*>.isAbstract
|
||||||
|
get() = Modifier.isAbstract(this.modifiers)
|
||||||
|
|
||||||
|
val Class<*>.isStrict
|
||||||
|
get() = Modifier.isStrict(this.modifiers)
|
@ -0,0 +1,36 @@
|
|||||||
|
package cn.tursom.reflect
|
||||||
|
|
||||||
|
import java.lang.reflect.Method
|
||||||
|
|
||||||
|
interface MethodFilter {
|
||||||
|
fun filterMethod(clazz: Class<*>): Sequence<Method>
|
||||||
|
|
||||||
|
companion object
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Arg1MethodFilter<R>(
|
||||||
|
val prevFilter: ReturnTypeMethodFilter<R>,
|
||||||
|
) : MethodFilter {
|
||||||
|
override fun filterMethod(clazz: Class<*>): Sequence<Method> {
|
||||||
|
return prevFilter.filterMethod(clazz).filter { method ->
|
||||||
|
method.parameterCount == 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> filter(clazz: Class<T>): Sequence<T.() -> R> {
|
||||||
|
return filterMethod(clazz).map {
|
||||||
|
{
|
||||||
|
it.invoke(this) as R
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun filter(obj: Any): Sequence<() -> R> {
|
||||||
|
return filterMethod(obj.javaClass).map {
|
||||||
|
{
|
||||||
|
it.invoke(obj) as R
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,456 @@
|
|||||||
|
package cn.tursom.reflect
|
||||||
|
|
||||||
|
import cn.tursom.core.UncheckedCast
|
||||||
|
import cn.tursom.core.cast
|
||||||
|
import cn.tursom.core.forAllMethods
|
||||||
|
import cn.tursom.log.impl.Slf4jImpl
|
||||||
|
import java.lang.reflect.Method
|
||||||
|
import java.lang.reflect.ParameterizedType
|
||||||
|
import kotlin.coroutines.Continuation
|
||||||
|
import kotlin.reflect.jvm.javaType
|
||||||
|
import kotlin.reflect.jvm.kotlinFunction
|
||||||
|
|
||||||
|
@Suppress("unused", "MemberVisibilityCanBePrivate")
|
||||||
|
object MethodInspector : Slf4jImpl() {
|
||||||
|
fun <R> forEachMethod(
|
||||||
|
clazz: Class<*>,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType: Array<Class<*>>,
|
||||||
|
self: Any? = null,
|
||||||
|
handler: (Method, (Array<Any?>) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
clazz.forAllMethods { method ->
|
||||||
|
val parameterTypes = method.parameterTypes
|
||||||
|
val methodReturnType = if (
|
||||||
|
method.returnType == Void.TYPE ||
|
||||||
|
method.returnType == Void::class.java
|
||||||
|
) Unit::class.java else method.returnType
|
||||||
|
|
||||||
|
val argumentTypeIterator = argumentType.iterator()
|
||||||
|
if (parameterTypes.size == argumentType.size &&
|
||||||
|
parameterTypes.all {
|
||||||
|
argumentTypeIterator.next().isAssignableFrom(it)
|
||||||
|
} &&
|
||||||
|
returnType.isAssignableFrom(methodReturnType)
|
||||||
|
) {
|
||||||
|
method.isAccessible = true
|
||||||
|
@OptIn(UncheckedCast::class)
|
||||||
|
handler(method) { method.invoke(self, *it).cast() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <R> forEachSuspendMethod(
|
||||||
|
clazz: Class<*>,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType: Array<Class<*>>,
|
||||||
|
self: Any? = null,
|
||||||
|
handler: (Method, suspend (Array<Any?>) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
clazz.forAllMethods { method ->
|
||||||
|
val parameterTypes = method.parameterTypes
|
||||||
|
val kotlinFunction = method.kotlinFunction ?: return@forAllMethods
|
||||||
|
var methodReturnType = kotlinFunction.returnType.javaType
|
||||||
|
while (methodReturnType is ParameterizedType) {
|
||||||
|
methodReturnType = methodReturnType.rawType
|
||||||
|
}
|
||||||
|
|
||||||
|
if (methodReturnType !is Class<*>) {
|
||||||
|
warn("method return type {}({}) is not Class", methodReturnType, methodReturnType.javaClass)
|
||||||
|
return@forAllMethods
|
||||||
|
}
|
||||||
|
|
||||||
|
val argumentTypeIterator = argumentType.iterator()
|
||||||
|
if (parameterTypes.size - 1 == argumentType.size &&
|
||||||
|
parameterTypes.dropLast(1).all {
|
||||||
|
argumentTypeIterator.next().isAssignableFrom(it)
|
||||||
|
} &&
|
||||||
|
Continuation::class.java.isAssignableFrom(parameterTypes.last()) &&
|
||||||
|
returnType.isAssignableFrom(methodReturnType)
|
||||||
|
) {
|
||||||
|
method.isAccessible = true
|
||||||
|
@OptIn(UncheckedCast::class)
|
||||||
|
handler(method, { it: Array<Any?>, cont: Continuation<*> -> method.invoke(self, *it, cont) }.cast())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forEachMethod(clazz: Class<*>, self: Any? = null, handler: (Method, () -> Unit) -> Unit) {
|
||||||
|
forEachMethod(clazz, Unit::class.java, self, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <R> forEachMethod(
|
||||||
|
clazz: Class<*>,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
self: Any? = null,
|
||||||
|
handler: (Method, () -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
clazz.javaClass.forAllMethods { method ->
|
||||||
|
val parameterTypes = method.parameterTypes
|
||||||
|
val methodReturnType = if (
|
||||||
|
method.returnType == Void.TYPE ||
|
||||||
|
method.returnType == Void::class.java
|
||||||
|
) Unit::class.java else method.returnType
|
||||||
|
if (parameterTypes.isEmpty() && returnType.isAssignableFrom(methodReturnType)) {
|
||||||
|
method.isAccessible = true
|
||||||
|
@OptIn(UncheckedCast::class)
|
||||||
|
handler(method) { method.invoke(self).cast() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T, R> forEachMethod(
|
||||||
|
clazz: Class<*>,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType: Class<T>,
|
||||||
|
self: Any? = null,
|
||||||
|
handler: (Method, (T) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachMethod(clazz, returnType, arrayOf(argumentType), self) { method: Method, m: (Array<Any?>) -> R ->
|
||||||
|
handler(method) {
|
||||||
|
m(arrayOf(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, R> forEachMethod(
|
||||||
|
clazz: Class<*>,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType1: Class<T1>,
|
||||||
|
argumentType2: Class<T2>,
|
||||||
|
self: Any? = null,
|
||||||
|
handler: (Method, (T1, T2) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachMethod(
|
||||||
|
clazz,
|
||||||
|
returnType,
|
||||||
|
arrayOf(argumentType1, argumentType2),
|
||||||
|
self
|
||||||
|
) { method: Method, m: (Array<Any?>) -> R ->
|
||||||
|
handler(method) { t1, t2 ->
|
||||||
|
m(arrayOf(t1, t2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, T3, R> forEachMethod(
|
||||||
|
clazz: Class<*>,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType1: Class<T1>,
|
||||||
|
argumentType2: Class<T2>,
|
||||||
|
argumentType3: Class<T3>,
|
||||||
|
self: Any? = null,
|
||||||
|
handler: (Method, (T1, T2, T3) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachMethod(
|
||||||
|
clazz,
|
||||||
|
returnType,
|
||||||
|
arrayOf(argumentType1, argumentType2, argumentType3),
|
||||||
|
self
|
||||||
|
) { method: Method, m: (Array<Any?>) -> R ->
|
||||||
|
handler(method) { t1, t2, t3 ->
|
||||||
|
m(arrayOf(t1, t2, t3))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, T3, T4, R> forEachMethod(
|
||||||
|
clazz: Class<*>,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType1: Class<T1>,
|
||||||
|
argumentType2: Class<T2>,
|
||||||
|
argumentType3: Class<T3>,
|
||||||
|
argumentType4: Class<T4>,
|
||||||
|
self: Any? = null,
|
||||||
|
handler: (Method, (T1, T2, T3, T4) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachMethod(
|
||||||
|
clazz,
|
||||||
|
returnType,
|
||||||
|
arrayOf(argumentType1, argumentType2, argumentType3, argumentType4),
|
||||||
|
self
|
||||||
|
) { method: Method, m: (Array<Any?>) -> R ->
|
||||||
|
handler(method) { t1, t2, t3, t4 ->
|
||||||
|
m(arrayOf(t1, t2, t3, t4))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forEachSuspendMethod(clazz: Class<*>, self: Any? = null, handler: (Method, suspend () -> Unit) -> Unit) {
|
||||||
|
forEachSuspendMethod(clazz, Unit::class.java, self, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <R> forEachSuspendMethod(
|
||||||
|
clazz: Class<*>,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
self: Any? = null,
|
||||||
|
handler: (Method, suspend () -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachSuspendMethod(clazz, returnType, arrayOf(), self) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||||
|
handler(method) {
|
||||||
|
m(arrayOf())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T, R> forEachSuspendMethod(
|
||||||
|
clazz: Class<*>,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType: Class<T>,
|
||||||
|
self: Any? = null,
|
||||||
|
handler: (Method, suspend (T) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachSuspendMethod(
|
||||||
|
clazz,
|
||||||
|
returnType,
|
||||||
|
arrayOf(argumentType),
|
||||||
|
self
|
||||||
|
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||||
|
handler(method) {
|
||||||
|
m(arrayOf(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, R> forEachSuspendMethod(
|
||||||
|
clazz: Class<*>,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType1: Class<T1>,
|
||||||
|
argumentType2: Class<T2>,
|
||||||
|
self: Any? = null,
|
||||||
|
handler: (Method, suspend (T1, T2) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachSuspendMethod(
|
||||||
|
clazz,
|
||||||
|
returnType,
|
||||||
|
arrayOf(argumentType1, argumentType2),
|
||||||
|
self
|
||||||
|
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||||
|
handler(method) { t1, t2 ->
|
||||||
|
m(arrayOf(t1, t2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, T3, R> forEachSuspendMethod(
|
||||||
|
clazz: Class<*>,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType1: Class<T1>,
|
||||||
|
argumentType2: Class<T2>,
|
||||||
|
argumentType3: Class<T3>,
|
||||||
|
self: Any? = null,
|
||||||
|
handler: (Method, suspend (T1, T2, T3) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachSuspendMethod(
|
||||||
|
clazz,
|
||||||
|
returnType,
|
||||||
|
arrayOf(argumentType1, argumentType2, argumentType3),
|
||||||
|
self
|
||||||
|
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||||
|
handler(method) { t1, t2, t3 ->
|
||||||
|
m(arrayOf(t1, t2, t3))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, T3, T4, R> forEachSuspendMethod(
|
||||||
|
clazz: Class<*>,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType1: Class<T1>,
|
||||||
|
argumentType2: Class<T2>,
|
||||||
|
argumentType3: Class<T3>,
|
||||||
|
argumentType4: Class<T4>,
|
||||||
|
self: Any? = null,
|
||||||
|
handler: (Method, suspend (T1, T2, T3, T4) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachSuspendMethod(
|
||||||
|
clazz,
|
||||||
|
returnType,
|
||||||
|
arrayOf(argumentType1, argumentType2, argumentType3, argumentType4),
|
||||||
|
self
|
||||||
|
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||||
|
handler(method) { t1, t2, t3, t4 ->
|
||||||
|
m(arrayOf(t1, t2, t3, t4))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun <R> forEachMethod(
|
||||||
|
self: Any,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType: Array<Class<*>>,
|
||||||
|
handler: (Method, (Array<Any?>) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachMethod(self.javaClass, returnType, argumentType, self, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <R> forEachSuspendMethod(
|
||||||
|
self: Any,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType: Array<Class<*>>,
|
||||||
|
handler: (Method, suspend (Array<Any?>) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachSuspendMethod(self.javaClass, returnType, argumentType, self, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forEachMethod(self: Any, handler: (Method, () -> Unit) -> Unit) {
|
||||||
|
forEachMethod(self, Unit::class.java, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <R> forEachMethod(self: Any, returnType: Class<out R>, handler: (Method, () -> R) -> Unit) {
|
||||||
|
forEachMethod(self.javaClass, returnType, self, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T, R> forEachMethod(
|
||||||
|
self: Any,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType: Class<T>,
|
||||||
|
handler: (Method, (T) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachMethod(self, returnType, arrayOf(argumentType)) { method: Method, m: (Array<Any?>) -> R ->
|
||||||
|
handler(method) {
|
||||||
|
m(arrayOf(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, R> forEachMethod(
|
||||||
|
self: Any,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType1: Class<T1>,
|
||||||
|
argumentType2: Class<T2>,
|
||||||
|
handler: (Method, (T1, T2) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachMethod(
|
||||||
|
self,
|
||||||
|
returnType,
|
||||||
|
arrayOf(argumentType1, argumentType2)
|
||||||
|
) { method: Method, m: (Array<Any?>) -> R ->
|
||||||
|
handler(method) { t1, t2 ->
|
||||||
|
m(arrayOf(t1, t2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, T3, R> forEachMethod(
|
||||||
|
self: Any,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType1: Class<T1>,
|
||||||
|
argumentType2: Class<T2>,
|
||||||
|
argumentType3: Class<T3>,
|
||||||
|
handler: (Method, (T1, T2, T3) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachMethod(
|
||||||
|
self,
|
||||||
|
returnType,
|
||||||
|
arrayOf(argumentType1, argumentType2, argumentType3)
|
||||||
|
) { method: Method, m: (Array<Any?>) -> R ->
|
||||||
|
handler(method) { t1, t2, t3 ->
|
||||||
|
m(arrayOf(t1, t2, t3))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, T3, T4, R> forEachMethod(
|
||||||
|
self: Any,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType1: Class<T1>,
|
||||||
|
argumentType2: Class<T2>,
|
||||||
|
argumentType3: Class<T3>,
|
||||||
|
argumentType4: Class<T4>,
|
||||||
|
handler: (Method, (T1, T2, T3, T4) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachMethod(
|
||||||
|
self,
|
||||||
|
returnType,
|
||||||
|
arrayOf(argumentType1, argumentType2, argumentType3, argumentType4)
|
||||||
|
) { method: Method, m: (Array<Any?>) -> R ->
|
||||||
|
handler(method) { t1, t2, t3, t4 ->
|
||||||
|
m(arrayOf(t1, t2, t3, t4))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forEachSuspendMethod(self: Any, handler: (Method, suspend () -> Unit) -> Unit) {
|
||||||
|
forEachSuspendMethod(self, Unit::class.java, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <R> forEachSuspendMethod(self: Any, returnType: Class<out R>, handler: (Method, suspend () -> R) -> Unit) {
|
||||||
|
forEachSuspendMethod(self, returnType, arrayOf()) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||||
|
handler(method) {
|
||||||
|
m(arrayOf())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T, R> forEachSuspendMethod(
|
||||||
|
self: Any,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType: Class<T>,
|
||||||
|
handler: (Method, suspend (T) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachSuspendMethod(self, returnType, arrayOf(argumentType)) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||||
|
handler(method) {
|
||||||
|
m(arrayOf(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, R> forEachSuspendMethod(
|
||||||
|
self: Any,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType1: Class<T1>,
|
||||||
|
argumentType2: Class<T2>,
|
||||||
|
handler: (Method, suspend (T1, T2) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachSuspendMethod(
|
||||||
|
self,
|
||||||
|
returnType,
|
||||||
|
arrayOf(argumentType1, argumentType2)
|
||||||
|
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||||
|
handler(method) { t1, t2 ->
|
||||||
|
m(arrayOf(t1, t2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, T3, R> forEachSuspendMethod(
|
||||||
|
self: Any,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType1: Class<T1>,
|
||||||
|
argumentType2: Class<T2>,
|
||||||
|
argumentType3: Class<T3>,
|
||||||
|
handler: (Method, suspend (T1, T2, T3) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachSuspendMethod(
|
||||||
|
self,
|
||||||
|
returnType,
|
||||||
|
arrayOf(argumentType1, argumentType2, argumentType3)
|
||||||
|
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||||
|
handler(method) { t1, t2, t3 ->
|
||||||
|
m(arrayOf(t1, t2, t3))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T1, T2, T3, T4, R> forEachSuspendMethod(
|
||||||
|
self: Any,
|
||||||
|
returnType: Class<out R>,
|
||||||
|
argumentType1: Class<T1>,
|
||||||
|
argumentType2: Class<T2>,
|
||||||
|
argumentType3: Class<T3>,
|
||||||
|
argumentType4: Class<T4>,
|
||||||
|
handler: (Method, suspend (T1, T2, T3, T4) -> R) -> Unit,
|
||||||
|
) {
|
||||||
|
forEachSuspendMethod(
|
||||||
|
self,
|
||||||
|
returnType,
|
||||||
|
arrayOf(argumentType1, argumentType2, argumentType3, argumentType4)
|
||||||
|
) { method: Method, m: suspend (Array<Any?>) -> R ->
|
||||||
|
handler(method) { t1, t2, t3, t4 ->
|
||||||
|
m(arrayOf(t1, t2, t3, t4))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package cn.tursom.reflect
|
||||||
|
|
||||||
|
import java.lang.reflect.Method
|
||||||
|
|
||||||
|
class NoargMethodFilter<R>(
|
||||||
|
val prevFilter: ReturnTypeMethodFilter<R>,
|
||||||
|
) : MethodFilter {
|
||||||
|
override fun filterMethod(clazz: Class<*>): Sequence<Method> {
|
||||||
|
return prevFilter.filterMethod(clazz).filter { method ->
|
||||||
|
method.parameterCount == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> filter(clazz: Class<T>): Sequence<T.() -> R> {
|
||||||
|
return filterMethod(clazz).map {
|
||||||
|
{
|
||||||
|
it.invoke(this) as R
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun filter(obj: Any): Sequence<() -> R> {
|
||||||
|
return filterMethod(obj.javaClass).map {
|
||||||
|
{
|
||||||
|
it.invoke(obj) as R
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <R> ReturnTypeMethodFilter<R>.noarg() = NoargMethodFilter(this)
|
210
ts-core/ts-reflect/src/main/kotlin/cn/tursom/reflect/Parser.kt
Normal file
210
ts-core/ts-reflect/src/main/kotlin/cn/tursom/reflect/Parser.kt
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
package cn.tursom.reflect
|
||||||
|
|
||||||
|
import cn.tursom.core.*
|
||||||
|
import java.lang.reflect.Array
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
import java.lang.reflect.Modifier
|
||||||
|
import java.lang.reflect.ParameterizedType
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
object Parser {
|
||||||
|
private val simpleDateFormat = ThreadLocalSimpleDateFormat()
|
||||||
|
private val Field.actualTypeArguments get() = (genericType as ParameterizedType).actualTypeArguments[0] as Class<*>
|
||||||
|
|
||||||
|
fun <T> parse(yaml: Any, clazz: Class<T>): T? {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
@OptIn(UncheckedCast::class)
|
||||||
|
return when {
|
||||||
|
clazz.isInstance(yaml) -> yaml.cast()
|
||||||
|
clazz.isInheritanceFrom(Enum::class.java) -> (clazz as Class<out Enum<*>>).valueOf(yaml.toString()) as? T?
|
||||||
|
clazz.isInheritanceFrom(Map::class.java) -> {
|
||||||
|
val map = try {
|
||||||
|
clazz.newInstance()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
try {
|
||||||
|
Unsafe.unsafe.allocateInstance(clazz)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
HashMap<Any?, Any?>()
|
||||||
|
}
|
||||||
|
}.cast<MutableMap<Any?, Any?>>()
|
||||||
|
if (yaml !is Map<*, *>) return null
|
||||||
|
yaml.forEach { (any, u) ->
|
||||||
|
map[any] = u
|
||||||
|
}
|
||||||
|
map.cast<T>()
|
||||||
|
}
|
||||||
|
yaml is List<*> && clazz.isArray -> parseArray(yaml, clazz) as T
|
||||||
|
else -> when (clazz) {
|
||||||
|
Any::class.java -> yaml
|
||||||
|
Int::class.java -> yaml.toInt()
|
||||||
|
Long::class.java -> yaml.toLong()
|
||||||
|
Float::class.java -> yaml.toFloat()
|
||||||
|
Double::class.java -> yaml.toDouble()
|
||||||
|
Boolean::class.java -> yaml.toBoolean()
|
||||||
|
|
||||||
|
getClazz<Int>() -> yaml.toInt()
|
||||||
|
getClazz<Long>() -> yaml.toLong()
|
||||||
|
getClazz<Float>() -> yaml.toFloat()
|
||||||
|
getClazz<Double>() -> yaml.toDouble()
|
||||||
|
getClazz<Boolean>() -> yaml.toBoolean()
|
||||||
|
Date::class.java -> yaml.toDate()
|
||||||
|
String::class.java -> yaml.toString()
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
if (yaml !is Map<*, *>) return null
|
||||||
|
val instance = try {
|
||||||
|
clazz.newInstance()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Unsafe.unsafe.allocateInstance(clazz)
|
||||||
|
}
|
||||||
|
val fields = clazz.declaredFields
|
||||||
|
fields.forEach {
|
||||||
|
if ((it.modifiers and (Modifier.STATIC or Modifier.TRANSIENT)) != 0) return@forEach
|
||||||
|
try {
|
||||||
|
val parse = parseField(yaml[it.name] ?: return@forEach, it) ?: return@forEach
|
||||||
|
it.isAccessible = true
|
||||||
|
it.set(instance, parse)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
instance
|
||||||
|
}
|
||||||
|
} as T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseField(yaml: Any, field: Field): Any? {
|
||||||
|
val clazz = field.type
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return when (yaml) {
|
||||||
|
is List<*> -> {
|
||||||
|
when {
|
||||||
|
clazz.isAssignableFrom(List::class.java) -> {
|
||||||
|
val type = field.actualTypeArguments
|
||||||
|
if (type == Any::class.java) {
|
||||||
|
yaml
|
||||||
|
} else {
|
||||||
|
val list = try {
|
||||||
|
clazz.newInstance() as MutableList<Any>
|
||||||
|
} catch (e: Exception) {
|
||||||
|
try {
|
||||||
|
Unsafe.unsafe.allocateInstance(clazz) as MutableList<Any>
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ArrayList<Any>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yaml.forEach {
|
||||||
|
list.add(parse(it ?: return@forEach, type) ?: return@forEach)
|
||||||
|
}
|
||||||
|
list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clazz.isAssignableFrom(Set::class.java) -> {
|
||||||
|
val type = field.actualTypeArguments
|
||||||
|
if (type == Any::class.java) {
|
||||||
|
yaml
|
||||||
|
} else {
|
||||||
|
val set: MutableSet<Any> = try {
|
||||||
|
clazz.newInstance() as MutableSet<Any>
|
||||||
|
} catch (e: Exception) {
|
||||||
|
try {
|
||||||
|
Unsafe.unsafe.allocateInstance(clazz) as MutableSet<Any>
|
||||||
|
} catch (e: Exception) {
|
||||||
|
HashSet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yaml.forEach {
|
||||||
|
set.add(parse(it ?: return@forEach, type) ?: return@forEach)
|
||||||
|
}
|
||||||
|
set
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clazz.isArray -> parseArray(yaml, clazz)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> parse(yaml, clazz)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> parseArray(yaml: List<Any?>, clazz: Class<T>): kotlin.Array<T>? {
|
||||||
|
val componentType = clazz.componentType
|
||||||
|
val list = ArrayList<Any>()
|
||||||
|
yaml.forEach {
|
||||||
|
list.add(parse(it ?: return@forEach, componentType) ?: return@forEach)
|
||||||
|
}
|
||||||
|
val instance = Array.newInstance(componentType, list.size)
|
||||||
|
list.forEachIndexed { index, any -> Array.set(instance, index, any) }
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return instance as kotlin.Array<T>?
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Any.toInt() = when (this) {
|
||||||
|
is Number -> toInt()
|
||||||
|
is Boolean -> if (this) 1 else 0
|
||||||
|
is String -> toIntOrNull()
|
||||||
|
is Iterable<*> -> null
|
||||||
|
is Iterator<*> -> null
|
||||||
|
is Map<*, *> -> null
|
||||||
|
else -> toString().toIntOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Any.toLong() = when (this) {
|
||||||
|
is Number -> toLong()
|
||||||
|
is Boolean -> if (this) 1L else 0L
|
||||||
|
is String -> toLongOrNull()
|
||||||
|
is Iterable<*> -> null
|
||||||
|
is Iterator<*> -> null
|
||||||
|
is Map<*, *> -> null
|
||||||
|
else -> toString().toLongOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Any.toFloat() = when (this) {
|
||||||
|
is Number -> toFloat()
|
||||||
|
is Boolean -> if (this) 1.0f else 0.0f
|
||||||
|
is String -> toFloatOrNull()
|
||||||
|
is Iterable<*> -> null
|
||||||
|
is Iterator<*> -> null
|
||||||
|
is Map<*, *> -> null
|
||||||
|
else -> toString().toFloatOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Any.toDouble() = when (this) {
|
||||||
|
is Number -> toDouble()
|
||||||
|
is Boolean -> if (this) 1.0 else 0.0
|
||||||
|
is String -> toDoubleOrNull()
|
||||||
|
is Iterable<*> -> null
|
||||||
|
is Iterator<*> -> null
|
||||||
|
is Map<*, *> -> null
|
||||||
|
else -> toString().toDoubleOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Any.toBoolean(): Boolean? = when (this) {
|
||||||
|
is Boolean -> this
|
||||||
|
is Number -> 0 != toInt()
|
||||||
|
is String -> equals("t", true) || equals("true", true)
|
||||||
|
is Iterable<*> -> null
|
||||||
|
is Iterator<*> -> null
|
||||||
|
is Map<*, *> -> null
|
||||||
|
else -> toString().toBoolean()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Any.toDate(): Date? = when (this) {
|
||||||
|
is Number -> Date(toLong())
|
||||||
|
is Boolean -> null
|
||||||
|
is String -> when (val time = toLongOrNull()) {
|
||||||
|
null -> simpleDateFormat.get().parse(this)
|
||||||
|
else -> Date(time)
|
||||||
|
}
|
||||||
|
is Iterable<*> -> null
|
||||||
|
is Iterator<*> -> null
|
||||||
|
is Map<*, *> -> null
|
||||||
|
else -> {
|
||||||
|
val str = toString()
|
||||||
|
when (val time = str.toLongOrNull()) {
|
||||||
|
null -> simpleDateFormat.get().parse(str)
|
||||||
|
else -> Date(time)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package cn.tursom.reflect
|
||||||
|
|
||||||
|
import cn.tursom.core.allMethodsSequence
|
||||||
|
import java.lang.reflect.Method
|
||||||
|
|
||||||
|
class ReturnTypeMethodFilter<R>(
|
||||||
|
val returnType: Class<R>,
|
||||||
|
) : MethodFilter {
|
||||||
|
override fun filterMethod(clazz: Class<*>): Sequence<Method> {
|
||||||
|
return clazz.allMethodsSequence.filter { method ->
|
||||||
|
val methodReturnType = if (
|
||||||
|
method.returnType == Void.TYPE ||
|
||||||
|
method.returnType == Void::class.java
|
||||||
|
) Unit::class.java else method.returnType
|
||||||
|
returnType.isAssignableFrom(methodReturnType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified R> MethodFilter.Companion.returnType() = ReturnTypeMethodFilter(R::class.java)
|
@ -0,0 +1,47 @@
|
|||||||
|
package cn.tursom.reflect
|
||||||
|
|
||||||
|
import cn.tursom.core.Unsafe.get
|
||||||
|
import cn.tursom.core.companionObjectInstanceOrNull
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
import java.lang.reflect.Method
|
||||||
|
|
||||||
|
inline fun <reified T : Annotation> Class<*>.getAnnotation(): T? = getAnnotation(T::class.java)
|
||||||
|
inline fun <reified T : Annotation> Field.getAnnotation(): T? = getAnnotation(T::class.java)
|
||||||
|
inline fun <reified T : Annotation> Method.getAnnotation(): T? = getAnnotation(T::class.java)
|
||||||
|
|
||||||
|
operator fun Class<*>.contains(obj: Any): Boolean = isInstance(obj)
|
||||||
|
|
||||||
|
fun <T> Class<*>.getStaticField(name: String): T? {
|
||||||
|
val staticField = getDeclaredField(name)
|
||||||
|
if (staticField.isStatic()) {
|
||||||
|
staticField.isAccessible = true
|
||||||
|
return staticField.get(null).uncheckedCast()
|
||||||
|
}
|
||||||
|
|
||||||
|
val companionObjectInstance = kotlin.companionObjectInstanceOrNull
|
||||||
|
if (companionObjectInstance != null) {
|
||||||
|
return companionObjectInstance[name]?.uncheckedCast()
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified C : Any, T> getStaticField(name: String): T? {
|
||||||
|
return C::class.java.getStaticField(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
fun <T : Enum<out T>> Class<out T>.valueOf(value: String): T? {
|
||||||
|
var valueOf: Method? = null
|
||||||
|
return try {
|
||||||
|
valueOf = getDeclaredMethod("valueOf", String::class.java)
|
||||||
|
valueOf.invoke(null, value) as T
|
||||||
|
} catch (e: Exception) {
|
||||||
|
try {
|
||||||
|
valueOf?.invoke(null, value.toUpperCase()) as? T?
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package cn.tursom.database.ktorm
|
||||||
|
|
||||||
|
import org.ktorm.dsl.AssignmentsBuilder
|
||||||
|
import org.ktorm.schema.ColumnDeclaring
|
||||||
|
import kotlin.reflect.KProperty1
|
||||||
|
|
||||||
|
inline fun <reified T : Any, C : Any> AssignmentsBuilder.set(
|
||||||
|
column: KProperty1<T, C?>,
|
||||||
|
value: C?,
|
||||||
|
) {
|
||||||
|
set(AutoTable[T::class.java][column], value)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : Any, C : Any> AssignmentsBuilder.set(
|
||||||
|
column: KProperty1<T, C?>,
|
||||||
|
expr: ColumnDeclaring<C>,
|
||||||
|
) {
|
||||||
|
set(AutoTable[T::class.java][column], expr)
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package cn.tursom.database.ktorm
|
||||||
|
|
||||||
|
import org.ktorm.dsl.QueryRowSet
|
||||||
|
import kotlin.reflect.KProperty1
|
||||||
|
|
||||||
|
inline operator fun <reified T : Any, C : Any> QueryRowSet.get(column: KProperty1<in T, C?>) =
|
||||||
|
get(AutoTable[T::class.java][column])
|
Loading…
Reference in New Issue
Block a user