All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
run.smt.ktest.util.reflection.annotations.kt Maven / Gradle / Ivy
package run.smt.ktest.util.reflection
import java.lang.reflect.Method
import java.lang.reflect.Proxy
import kotlin.reflect.KClass
import java.lang.reflect.Array as ReflectArray
inline fun a(valueArg: Any?): T = a(T::class, valueArg)
inline fun a(args: Map): T = a(T::class, args)
inline fun a(vararg args: Pair = emptyArray()): T = a(mapOf(*args))
fun a(clazz: KClass, args: Map) = createAnnotationStub(
clazz,
{ args.containsKey(it?.name) },
{ _, method, _ -> args[method?.name] }
)
fun a(clazz: KClass, valueArg: Any?): T = createAnnotationStub(
clazz,
{ it?.name == "value" },
{ _, _, _ -> valueArg }
)
@Suppress("UNCHECKED_CAST")
private inline fun createAnnotationStub(
clazz: KClass,
crossinline handledCase: (Method?) -> Boolean,
crossinline handler: (T, Method?, Array?) -> Any?
): T {
return Proxy.newProxyInstance(clazz.java.classLoader, arrayOf(clazz.java)) { proxy, method, args: Array? ->
val self = proxy as T
handleCommonAnnotationMethods(clazz, self, method, args) ?:
if (handledCase(method)) {
val result = handler(self, method, args)
val methodReturn = method?.returnType
if (methodReturn?.isArray == true && result?.javaClass != methodReturn && result != null) {
val arrayResult = ReflectArray.newInstance(methodReturn.componentType, 1)
ReflectArray.set(arrayResult, 0, result)
arrayResult
} else {
result
}
} else {
extractDefaultsIfAny(method)
}
} as T
}
private fun extractDefaultsIfAny(method: Method): Any? {
return when {
method.defaultValue != null -> method.defaultValue
method.returnType.isArray -> ReflectArray.newInstance(method.returnType.componentType, 0)
else -> null
}
}
private fun handleCommonAnnotationMethods(clazz: KClass, instance: T, currentMethod: Method?, args: Array?)
= when (currentMethod?.name) {
"annotationType" -> clazz.java
"equals" -> {
val compareTo = args?.firstOrNull()
compareTo != null && compareTo is Annotation && extractAnnotationValues(instance).toList() == extractAnnotationValues(compareTo).toList()
}
"toString" -> "@" + clazz.java.canonicalName + "(" + extractAnnotationValues(instance).map { it.first + "=" + it.second }.joinToString(", ") + ")"
"hashCode" -> instance.toString().hashCode()
else -> null
}
private fun extractAnnotationValues(annotation: Annotation): Sequence> {
return annotation.annotationClass.java.declaredMethods.asSequence()
.filter { it.name !in arrayOf("equals", "hashCode", "toString", "annotationType") }
.filter { it.parameterTypes.isEmpty() }
.map({ it.name to it.invoke(annotation) })
}