add reflect utils

This commit is contained in:
tursom 2021-07-08 22:05:26 +08:00
parent 1cbc2a0c12
commit 7f462da93e
16 changed files with 1244 additions and 7 deletions

View File

@ -0,0 +1,96 @@
@file:Suppress("unused")
package cn.tursom.core.reflect
import cn.tursom.core.uncheckedCast
import java.lang.reflect.Method
inline fun <R> Class<*>.getStaticDeclaredMethod(
returnType: Class<*>,
getMethod: Class<*>.() -> Method?,
staticReturn: (method: Method) -> R,
): R? {
val method = getStaticDeclaredMethod(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.getStaticDeclaredMethod(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.getStaticDeclaredMethod(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.getStaticDeclaredMethod(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.getStaticDeclaredMethod(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.getStaticDeclaredMethod(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.getStaticDeclaredMethod(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)

View File

@ -0,0 +1,76 @@
@file:Suppress("unused")
package cn.tursom.core.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)? = getStaticDeclaredMethod(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)? = getStaticDeclaredMethod(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)? = getStaticDeclaredMethod(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)? = getStaticDeclaredMethod(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)? = getStaticDeclaredMethod(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)? = getStaticDeclaredMethod(returnType, getMethod) { method ->
{ v1, v2, v3, v4, v5 -> method(this, v1, v2, v3, v4, v5).uncheckedCast() }
}

View File

@ -0,0 +1,215 @@
@file:Suppress("unused")
package cn.tursom.core.reflect
import cn.tursom.core.allMethodsSequence
import cn.tursom.core.companionObjectInstanceOrNull
import cn.tursom.core.uncheckedCast
import com.ddbes.kotlin.isStatic
import java.lang.reflect.Method
private var lastGetMethodThreadLocal = ThreadLocal<Method?>()
private val lastGetMethod get() = lastGetMethodThreadLocal.get()
inline fun <reified T> getType() = T::class.java
infix fun Class<*>.canCast(target: Class<*>): Boolean {
if (target == Any::class.java || this == target) return true
if ((this == Void.TYPE || this == Void::class.java) &&
(target == Unit::class.java || target == Void.TYPE || target == Void::class.java)
) return true
if ((this == Byte::class.java || this == getType<Byte>()) &&
(target == Byte::class.java || target == Byte::class.java)
) return true
if ((this == Short::class.java || this == getType<Short>()) &&
(target == Short::class.java || target == Short::class.java)
) return true
if ((this == Int::class.java || this == getType<Int>()) &&
(target == Int::class.java || target == getType<Int>())
) return true
if ((this == Long::class.java || this == getType<Long>()) &&
(target == Long::class.java || target == getType<Long>())
) return true
if ((this == Float::class.java || this == getType<Float>()) &&
(target == Float::class.java || target == getType<Float>())
) return true
if ((this == Double::class.java || this == getType<Double>()) &&
(target == Double::class.java || target == getType<Double>())
) return true
if ((this == Boolean::class.java || this == getType<Boolean>()) &&
(target == Boolean::class.java || target == getType<Boolean>())
) return true
if ((this == Char::class.java || this == getType<Char>()) &&
(target == Char::class.java || target == getType<Char>())
) return true
return 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? {
lastGetMethodThreadLocal.remove()
allMethodsSequence.forEach { method ->
if (method.match(name, *type)) {
lastGetMethodThreadLocal.set(method)
return method
}
}
return null
}
fun Class<*>.getMethodFully(
name: String,
vararg type: Class<*>,
): Method? {
lastGetMethodThreadLocal.remove()
val scanMethod = scanMethod(name, *type)
return (scanMethod.firstOrNull { method ->
method.parameterTypes.forEachIndexed { index, clazz ->
if (type[index] != clazz) return@firstOrNull false
}
true
} ?: scanMethod.firstOrNull()).also {
lastGetMethodThreadLocal.set(it)
}
}
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<*>.getStaticDeclaredMethod(
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 = getStaticDeclaredMethod(returnType, true, getMethod)
if (method != null) return staticReturn(method, null)
val companionObjectInstance = kotlin.companionObjectInstanceOrNull ?: return null
val companionObjectClazz = companionObjectInstance.javaClass
val companionMethod = companionObjectClazz.getStaticDeclaredMethod(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() } }
)

View File

@ -1,5 +1,7 @@
package cn.tursom.core
package cn.tursom.core.reflect
import cn.tursom.core.Unsafe
import cn.tursom.core.uncheckedCast
import java.util.concurrent.ConcurrentHashMap
import kotlin.reflect.KClass

View File

@ -0,0 +1,272 @@
@file:Suppress("unused")
package com.ddbes.kotlin
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)

View File

@ -0,0 +1,36 @@
package cn.tursom.core.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
}
}
}
}

View File

@ -0,0 +1,458 @@
package cn.tursom.core.reflect
import cn.tursom.core.UncheckedCast
import cn.tursom.core.cast
import cn.tursom.core.forAllMethods
import org.slf4j.LoggerFactory
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 {
private val logger = LoggerFactory.getLogger(MethodInspector::class.java)
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<*>) {
logger.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))
}
}
}
}

View File

@ -1,12 +1,19 @@
package cn.tursom.core
package cn.tursom.core.reflect
import cn.tursom.core.ThreadLocalSimpleDateFormat
import cn.tursom.core.Unsafe.unsafe
import cn.tursom.core.cast
import cn.tursom.core.getClazz
import cn.tursom.core.isInheritanceFrom
import java.lang.reflect.Array
import java.lang.reflect.Field
import java.lang.reflect.Modifier
import java.lang.reflect.ParameterizedType
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.set
object Parser {
private val dateFormat = ThreadLocalSimpleDateFormat()

View File

@ -0,0 +1,22 @@
package cn.tursom.core.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)

View File

@ -0,0 +1,48 @@
package cn.tursom.core.reflect
import cn.tursom.core.Unsafe.get
import cn.tursom.core.companionObjectInstanceOrNull
import cn.tursom.core.isStatic
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
}
}
}

View File

@ -2,6 +2,7 @@ package cn.tursom.core.clone
import cn.tursom.core.*
import cn.tursom.core.datastruct.ArrayMap
import cn.tursom.core.reflect.InstantAllocator
import cn.tursom.log.impl.Slf4jImpl
import kotlin.reflect.KClass
import kotlin.reflect.KProperty1

View File

@ -1,8 +1,12 @@
package cn.tursom.core.clone
import cn.tursom.core.*
import cn.tursom.core.Unsafe
import cn.tursom.core.allMemberProperties
import cn.tursom.core.datastruct.KPropertyValueMap
import cn.tursom.core.datastruct.SoftArrayMap
import cn.tursom.core.reflect.InstantAllocator
import cn.tursom.core.unaryPlus
import cn.tursom.core.uncheckedCast
import cn.tursom.log.impl.Slf4jImpl
import java.util.concurrent.ConcurrentHashMap
import kotlin.collections.component1

View File

@ -1,7 +1,7 @@
package cn.tursom.yaml
import cn.tursom.core.Parser
import cn.tursom.core.ThreadLocalSimpleDateFormat
import cn.tursom.core.reflect.Parser
import org.yaml.snakeyaml.Yaml
import java.lang.reflect.Modifier
import java.util.*

View File

@ -1,7 +1,7 @@
package cn.tursom.database
import cn.tursom.core.InstantAllocator
import cn.tursom.core.getClassByPackage
import cn.tursom.core.reflect.InstantAllocator
import cn.tursom.core.uncheckedCast
import org.ktorm.schema.BaseTable
import org.ktorm.schema.Column

View File

@ -1,6 +1,6 @@
package cn.tursom.database.mongodb
import cn.tursom.core.Parser
import cn.tursom.core.reflect.Parser
import org.bson.Document
interface BsonFactory<T> {

View File

@ -1,6 +1,6 @@
package cn.tursom.database.mongodb.spring
import cn.tursom.core.Parser
import cn.tursom.core.reflect.Parser
import org.bson.Document
interface BsonFactory<T> {