mirror of
https://github.com/tursom/TursomServer.git
synced 2025-02-07 02:01:19 +08:00
Merge remote-tracking branch 'origin/master' into master
This commit is contained in:
commit
eeacd926b2
@ -17,7 +17,7 @@ ext["excludeTest"] = { project: Project, tasks: TaskContainer ->
|
|||||||
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("jvm") version "1.4.31"
|
kotlin("jvm") version "1.4.32"
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +44,12 @@ allprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType<KotlinCompile>().configureEach {
|
||||||
|
kotlinOptions.jvmTarget = "1.8"
|
||||||
|
kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
|
||||||
|
//kotlinOptions.useIR = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.Suppress("UNCHECKED_CAST")
|
@kotlin.Suppress("UNCHECKED_CAST")
|
||||||
@ -53,9 +59,10 @@ dependencies {
|
|||||||
api(kotlin("stdlib-jdk8"))
|
api(kotlin("stdlib-jdk8"))
|
||||||
api(kotlin("reflect"))
|
api(kotlin("reflect"))
|
||||||
testImplementation(group = "junit", name = "junit", version = "4.12")
|
testImplementation(group = "junit", name = "junit", version = "4.12")
|
||||||
|
}
|
||||||
|
|
||||||
val commonVersion = "1.0.RELEASE"
|
artifacts {
|
||||||
api("com.ddbes", "common-kotlin", commonVersion)
|
archives(tasks["kotlinSourcesJar"])
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("install") {
|
tasks.register("install") {
|
||||||
@ -71,7 +78,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ include("ts-core:ts-pool")
|
|||||||
include("ts-core:ts-hash")
|
include("ts-core:ts-hash")
|
||||||
include("ts-core:ts-log")
|
include("ts-core:ts-log")
|
||||||
include("ts-core:ts-delegation")
|
include("ts-core:ts-delegation")
|
||||||
|
include("ts-core:ts-delegation:ts-observer")
|
||||||
include("ts-core:ts-clone")
|
include("ts-core:ts-clone")
|
||||||
include("ts-core:ts-mail")
|
include("ts-core:ts-mail")
|
||||||
include("ts-core:ts-coroutine")
|
include("ts-core:ts-coroutine")
|
||||||
@ -14,10 +15,16 @@ include("ts-core:ts-coroutine:ts-coroutine-lock")
|
|||||||
include("ts-core:ts-ws-client")
|
include("ts-core:ts-ws-client")
|
||||||
include("ts-core:ts-yaml")
|
include("ts-core:ts-yaml")
|
||||||
include("ts-core:ts-json")
|
include("ts-core:ts-json")
|
||||||
|
include("ts-core:ts-xml")
|
||||||
|
include("ts-core:ts-async-http")
|
||||||
include("ts-socket")
|
include("ts-socket")
|
||||||
include("ts-web")
|
include("ts-web")
|
||||||
include("ts-web:ts-web-netty")
|
include("ts-web:ts-web-netty")
|
||||||
include("ts-web:ts-web-coroutine")
|
include("ts-web:ts-web-coroutine")
|
||||||
|
include("ts-database")
|
||||||
|
include("ts-database:ts-mongodb")
|
||||||
|
include("ts-database:ts-mongodb:ts-mongodb-spring")
|
||||||
|
include("ts-database:ts-redis")
|
||||||
//include("web", "aop", "database", "utils", "utils:xml", "utils:async-http", "web:netty-web")
|
//include("web", "aop", "database", "utils", "utils:xml", "utils:async-http", "web:netty-web")
|
||||||
//include("socket", "socket:socket-async")
|
//include("socket", "socket:socket-async")
|
||||||
//include("AsyncSocket")
|
//include("AsyncSocket")
|
||||||
|
@ -4,7 +4,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":"))
|
api(project(":"))
|
||||||
compileOnly(group = "com.google.code.gson", name = "gson", version = "2.8.6")
|
compileOnly(group = "com.google.code.gson", name = "gson", version = "2.8.6")
|
||||||
compileOnly(group = "io.netty", name = "netty-all", version = "4.1.43.Final")
|
compileOnly(group = "io.netty", name = "netty-all", version = "4.1.43.Final")
|
||||||
}
|
}
|
||||||
@ -25,7 +25,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
53
ts-core/src/main/kotlin/cn/tursom/core/InstantAllocator.kt
Normal file
53
ts-core/src/main/kotlin/cn/tursom/core/InstantAllocator.kt
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package cn.tursom.core
|
||||||
|
|
||||||
|
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
|
||||||
|
Unsafe.unsafe.allocateInstance(clazz).uncheckedCast<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>()")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -66,11 +66,8 @@ object Parser {
|
|||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
if (yaml !is Map<*, *>) return null
|
if (yaml !is Map<*, *>) return null
|
||||||
val instance = try {
|
|
||||||
clazz.newInstance()
|
val instance = InstantAllocator[clazz]
|
||||||
} catch (e: Exception) {
|
|
||||||
unsafe.allocateInstance(clazz)
|
|
||||||
}
|
|
||||||
val fields = clazz.declaredFields
|
val fields = clazz.declaredFields
|
||||||
fields.forEach {
|
fields.forEach {
|
||||||
if ((it.modifiers and (Modifier.STATIC or Modifier.TRANSIENT)) != 0) return@forEach
|
if ((it.modifiers and (Modifier.STATIC or Modifier.TRANSIENT)) != 0) return@forEach
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package cn.tursom.core
|
||||||
|
|
||||||
|
import java.util.concurrent.*
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
|
class ScheduledExecutorPool(
|
||||||
|
private val threadCount: Int = Runtime.getRuntime().availableProcessors() * 2,
|
||||||
|
private val threadFactory: ThreadFactory = Executors.defaultThreadFactory(),
|
||||||
|
) {
|
||||||
|
private val scheduledExecutorQueue = ConcurrentLinkedDeque<Pair<Thread, ScheduledExecutorService>>()
|
||||||
|
private var initCount = AtomicInteger()
|
||||||
|
|
||||||
|
init {
|
||||||
|
initOne()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initOne() {
|
||||||
|
if (initCount.incrementAndGet() < threadCount) {
|
||||||
|
val executor: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor {
|
||||||
|
threadFactory.newThread(it)
|
||||||
|
}
|
||||||
|
val countDownLatch = CountDownLatch(1)
|
||||||
|
executor.execute {
|
||||||
|
scheduledExecutorQueue.addFirst(Thread.currentThread() to executor)
|
||||||
|
countDownLatch.countDown()
|
||||||
|
}
|
||||||
|
countDownLatch.await(3, TimeUnit.SECONDS)
|
||||||
|
} else {
|
||||||
|
initCount.decrementAndGet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(): Pair<Thread, ScheduledExecutorService> {
|
||||||
|
if (initCount.get() < threadCount) {
|
||||||
|
initOne()
|
||||||
|
}
|
||||||
|
val pair = scheduledExecutorQueue.poll()
|
||||||
|
scheduledExecutorQueue.add(pair)
|
||||||
|
return pair
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,26 @@
|
|||||||
package cn.tursom.core
|
package cn.tursom.core
|
||||||
|
|
||||||
open class SimpThreadLocal<T>(private val new: () -> T) : ThreadLocal<T>() {
|
open class SimpThreadLocal<T : Any>(
|
||||||
override fun get(): T = super.get() ?: update()
|
private val threadLocal: ThreadLocal<T?>? = null,
|
||||||
|
val new: () -> T,
|
||||||
|
) : ThreadLocal<T>() {
|
||||||
|
override fun get(): T {
|
||||||
|
var value = if (threadLocal != null) threadLocal.get() else super.get()
|
||||||
|
return if (value == null) {
|
||||||
|
value = new()
|
||||||
|
set(value)
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun update(): T {
|
override fun set(value: T) {
|
||||||
val value = new()
|
if (threadLocal != null) threadLocal.set(value) else super.set(value)
|
||||||
set(value)
|
}
|
||||||
return value
|
|
||||||
|
override fun remove() {
|
||||||
|
if (threadLocal != null) threadLocal.remove() else super.remove()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
123
ts-core/src/main/kotlin/cn/tursom/core/TextColor.kt
Normal file
123
ts-core/src/main/kotlin/cn/tursom/core/TextColor.kt
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
package cn.tursom.core
|
||||||
|
|
||||||
|
object TextColor {
|
||||||
|
const val reset = "\u001b[0m"
|
||||||
|
|
||||||
|
enum class DisplayType(val code: Int) {
|
||||||
|
DEFAULT(0), HIGHLIGHT(1), INTENSITY(2), ITALIC(3), UNDERLINE(4),
|
||||||
|
SLOW_BLINK(5), RAPID_BLINK(6), REVERSE(7), INVISIBLE(8), CROSSED_OUT(9),
|
||||||
|
UNDERLINE_OFF(24), BLINK_OFF(25), REVERSE_OFF(27), INVISIBLE_OFF(28), CROSSED_OUT_OFF(29),
|
||||||
|
OVER_LINE(53), OVER_LINE_OFF(55);
|
||||||
|
|
||||||
|
val strCode = "\u001b[${code}m"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun textColor(displayType: DisplayType, textColor: Int, backgroundColor: Int) =
|
||||||
|
"\u001B[${displayType.code};$textColor;${backgroundColor}m"
|
||||||
|
|
||||||
|
fun rgbTextColor(r: Int, g: Int, b: Int, displayType: DisplayType = DisplayType.DEFAULT) =
|
||||||
|
"\u001B[${displayType.code};38;2;$r;$g;${b}m"
|
||||||
|
|
||||||
|
fun rgbBackgroundColor(r: Int, g: Int, b: Int, displayType: DisplayType = DisplayType.DEFAULT) =
|
||||||
|
"\u001B[${displayType.code};48;2;$r;$g;${b}m"
|
||||||
|
|
||||||
|
const val black = "\u001b[30m"
|
||||||
|
const val red = "\u001b[31m"
|
||||||
|
const val green = "\u001b[32m"
|
||||||
|
const val yellow = "\u001b[33m"
|
||||||
|
const val blue = "\u001b[34m"
|
||||||
|
const val magenta = "\u001b[35m"
|
||||||
|
const val cyan = "\u001b[36m"
|
||||||
|
const val white = "\u001b[37m"
|
||||||
|
|
||||||
|
const val brightBlack = "\u001b[30;1m"
|
||||||
|
const val brightRed = "\u001b[31;1m"
|
||||||
|
const val brightGreen = "\u001b[32;1m"
|
||||||
|
const val brightYellow = "\u001b[33;1m"
|
||||||
|
const val brightBlue = "\u001b[34;1m"
|
||||||
|
const val brightMagenta = "\u001b[35;1m"
|
||||||
|
const val brightCyan = "\u001b[36;1m"
|
||||||
|
const val brightWhite = "\u001b[37;1m"
|
||||||
|
|
||||||
|
val textColor = Array(256) {
|
||||||
|
"\u001b[38;5;${it}m"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun textColor(color: Int) = textColor[color]
|
||||||
|
fun textColor(color: Int, displayType: DisplayType = DisplayType.DEFAULT) =
|
||||||
|
"\u001B[${displayType.code};38;5;${color}m"
|
||||||
|
|
||||||
|
const val blackBackground = "\u001b[40m"
|
||||||
|
const val redBackground = "\u001b[41m"
|
||||||
|
const val greenBackground = "\u001b[42m"
|
||||||
|
const val yellowBackground = "\u001b[43m"
|
||||||
|
const val blueBackground = "\u001b[44m"
|
||||||
|
const val magentaBackground = "\u001b[45m"
|
||||||
|
const val cyanBackground = "\u001b[46m"
|
||||||
|
const val whiteBackground = "\u001b[47m"
|
||||||
|
|
||||||
|
const val brightBlackBackground = "\u001b[40;1m"
|
||||||
|
const val brightRedBackground = "\u001b[41;1m"
|
||||||
|
const val brightGreenBackground = "\u001b[42;1m"
|
||||||
|
const val brightYellowBackground = "\u001b[43;1m"
|
||||||
|
const val brightBlueBackground = "\u001b[44;1m"
|
||||||
|
const val brightMagentaBackground = "\u001b[45;1m"
|
||||||
|
const val brightCyanBackground = "\u001b[46;1m"
|
||||||
|
const val brightWhiteBackground = "\u001b[47;1m"
|
||||||
|
|
||||||
|
val backgroundColor = Array(256) {
|
||||||
|
"\u001b[48;5;${it}m"
|
||||||
|
}
|
||||||
|
|
||||||
|
const val bold = "\u001b[1m"
|
||||||
|
const val underline = "\u001b[4m"
|
||||||
|
const val reverseColor = "\u001b[7m"
|
||||||
|
|
||||||
|
const val up = "\u001b[1A"
|
||||||
|
const val down = "\u001b[1B"
|
||||||
|
const val left = "\u001b[1C"
|
||||||
|
const val right = "\u001b[1D"
|
||||||
|
|
||||||
|
const val downToNextLine = "\u001b[1E"
|
||||||
|
const val upToPrevLine = "\u001b[1F"
|
||||||
|
|
||||||
|
fun up(step: Int) = "\u001b[${step}A"
|
||||||
|
fun down(step: Int) = "\u001b[${step}B"
|
||||||
|
fun left(step: Int) = "\u001b[${step}C"
|
||||||
|
fun right(step: Int) = "\u001b[${step}D"
|
||||||
|
|
||||||
|
fun downToNextLine(step: Int) = "\u001b[${step}E"
|
||||||
|
fun upToPrevLine(step: Int) = "\u001b[${step}F"
|
||||||
|
|
||||||
|
fun jumpToLine(line: Int) = "\u001b[${line}G"
|
||||||
|
fun jump(line: Int, row: Int) = "\u001b[${line};${row}H"
|
||||||
|
|
||||||
|
const val cleanScreenToEnd = "\u001b[0J"
|
||||||
|
const val cleanScreenFromStart = "\u001b[1J"
|
||||||
|
const val cleanScreen = "\u001b[2J"
|
||||||
|
|
||||||
|
const val cleanLineToEnd = "\u001b[0K"
|
||||||
|
const val cleanLineFromStart = "\u001b[1K"
|
||||||
|
const val cleanLine = "\u001b[2K"
|
||||||
|
|
||||||
|
const val savePosition = "\u001b[s"
|
||||||
|
const val loadPosition = "\u001b[u"
|
||||||
|
|
||||||
|
fun rgbTo8Color(R: Int, G: Int, B: Int): Int {
|
||||||
|
//8色化处理,取RGB的高1位相与。
|
||||||
|
val r1 = R shr 5 and 0x4
|
||||||
|
val g1 = G shr 6 and 0x2
|
||||||
|
val b1 = B shr 7
|
||||||
|
return (r1 or g1 or b1) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun rgbTo16Color(R: Int, G: Int, B: Int): Int {
|
||||||
|
//16色化处理,取R、G的高1位和B的高2位相与
|
||||||
|
val r1 = R shr 4 and 0x8
|
||||||
|
val g1 = G shr 5 and 0x4
|
||||||
|
val b1 = B shr 6 and 0x3
|
||||||
|
return (r1 or g1 or b1) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun rgbTo256Color(r: Int, g: Int, b: Int): Int = ((r / 32 shl 5) + (g / 32 shl 2) + b / 64) and 0xFF
|
||||||
|
}
|
@ -4,8 +4,8 @@ import java.text.SimpleDateFormat
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class ThreadLocalSimpleDateFormat(
|
class ThreadLocalSimpleDateFormat(
|
||||||
val format: String = "YYYY-MM-dd'T'HH:mm:ssZZ"
|
val format: String = "YYYY-MM-dd'T'HH:mm:ssZZ",
|
||||||
) : SimpThreadLocal<SimpleDateFormat>({
|
) : SimpThreadLocal<SimpleDateFormat>(null, {
|
||||||
SimpleDateFormat(format)
|
SimpleDateFormat(format)
|
||||||
}) {
|
}) {
|
||||||
fun format(date: Any) = get().format(date)
|
fun format(date: Any) = get().format(date)
|
||||||
|
@ -53,8 +53,12 @@ object Utils {
|
|||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("SpellCheckingInspection")
|
||||||
internal val UPPER_HEX_ARRAY = "0123456789ABCDEF".toCharArray()
|
internal val UPPER_HEX_ARRAY = "0123456789ABCDEF".toCharArray()
|
||||||
|
|
||||||
|
@Suppress("SpellCheckingInspection")
|
||||||
internal val LOWER_HEX_ARRAY = "0123456789abcdef".toCharArray()
|
internal val LOWER_HEX_ARRAY = "0123456789abcdef".toCharArray()
|
||||||
|
|
||||||
val md5 by lazy { MessageDigest.getInstance("MD5")!! }
|
val md5 by lazy { MessageDigest.getInstance("MD5")!! }
|
||||||
val sha256 by lazy { MessageDigest.getInstance("SHA-256")!! }
|
val sha256 by lazy { MessageDigest.getInstance("SHA-256")!! }
|
||||||
val sha by lazy { MessageDigest.getInstance("SHA")!! }
|
val sha by lazy { MessageDigest.getInstance("SHA")!! }
|
||||||
@ -62,6 +66,7 @@ object Utils {
|
|||||||
val sha384 by lazy { MessageDigest.getInstance("SHA-384")!! }
|
val sha384 by lazy { MessageDigest.getInstance("SHA-384")!! }
|
||||||
val sha512 by lazy { MessageDigest.getInstance("SHA-512")!! }
|
val sha512 by lazy { MessageDigest.getInstance("SHA-512")!! }
|
||||||
|
|
||||||
|
@Suppress("SpellCheckingInspection")
|
||||||
internal val DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray()
|
internal val DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray()
|
||||||
|
|
||||||
val receiverField: Field by lazy {
|
val receiverField: Field by lazy {
|
||||||
@ -112,9 +117,18 @@ inline fun <T, R : Any> Iterable<T>.toSetNotNull(transform: (T) -> R?): Set<R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
//@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
||||||
|
annotation class UncheckedCast
|
||||||
|
|
||||||
|
@UncheckedCast
|
||||||
@Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST")
|
@Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST")
|
||||||
inline fun <T> Any?.cast() = this as T
|
inline fun <T> Any?.cast() = this as T
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST")
|
||||||
|
inline fun <T> Any?.uncheckedCast() = this as T
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST")
|
@Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST")
|
||||||
inline fun <reified T> Any?.castOrNull() = if (this is T) this else null
|
inline fun <reified T> Any?.castOrNull() = if (this is T) this else null
|
||||||
|
|
||||||
@ -126,7 +140,7 @@ inline fun <T> T?.checkNull(ifNull: () -> Exception): T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.emptyToNull() = if (isEmpty()) null else this
|
fun String.emptyToNull() = ifEmpty { null }
|
||||||
|
|
||||||
inline fun <reified T> getClazz() = T::class.java
|
inline fun <reified T> getClazz() = T::class.java
|
||||||
|
|
||||||
@ -242,7 +256,7 @@ fun <A : Annotation, V : Any> A.changeAnnotationValue(field: KProperty1<A, V>, v
|
|||||||
val h = Proxy.getInvocationHandler(this)
|
val h = Proxy.getInvocationHandler(this)
|
||||||
val memberValuesField = h.javaClass.getDeclaredField("memberValues")
|
val memberValuesField = h.javaClass.getDeclaredField("memberValues")
|
||||||
memberValuesField.isAccessible = true
|
memberValuesField.isAccessible = true
|
||||||
val memberValues = memberValuesField[h].cast<MutableMap<String, Any>>()
|
val memberValues = memberValuesField[h].uncheckedCast<MutableMap<String, Any>>()
|
||||||
memberValues[field.name] = value
|
memberValues[field.name] = value
|
||||||
true
|
true
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@ -280,12 +294,7 @@ inline fun usingNanoTime(action: () -> Unit): Long {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fun Class<*>.forAllFields(action: (Field) -> Unit) {
|
inline fun Class<*>.forAllFields(action: (Field) -> Unit) {
|
||||||
var clazz = this
|
allFieldsSequence.forEach(action)
|
||||||
while (clazz != Any::class.java) {
|
|
||||||
clazz.declaredFields.forEach(action)
|
|
||||||
clazz = clazz.superclass
|
|
||||||
}
|
|
||||||
clazz.declaredFields.forEach(action)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val Class<*>.allFields: List<Field>
|
val Class<*>.allFields: List<Field>
|
||||||
@ -295,6 +304,17 @@ val Class<*>.allFields: List<Field>
|
|||||||
return fieldList
|
return fieldList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val Class<*>.allFieldsSequence: Sequence<Field>
|
||||||
|
get() = sequence {
|
||||||
|
var clazz = this@allFieldsSequence
|
||||||
|
while (clazz != Any::class.java) {
|
||||||
|
clazz.declaredFields.forEach { field ->
|
||||||
|
yield(field)
|
||||||
|
}
|
||||||
|
clazz = clazz.superclass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun Class<*>.getFieldForAll(name: String): Field? {
|
fun Class<*>.getFieldForAll(name: String): Field? {
|
||||||
forAllFields {
|
forAllFields {
|
||||||
if (it.name == name) return it
|
if (it.name == name) return it
|
||||||
@ -303,12 +323,7 @@ fun Class<*>.getFieldForAll(name: String): Field? {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline fun Class<*>.forAllMethods(action: (Method) -> Unit) {
|
inline fun Class<*>.forAllMethods(action: (Method) -> Unit) {
|
||||||
var clazz = this
|
allMethodsSequence.forEach(action)
|
||||||
while (clazz != Any::class.java) {
|
|
||||||
clazz.declaredMethods.forEach(action)
|
|
||||||
clazz = clazz.superclass
|
|
||||||
}
|
|
||||||
clazz.declaredMethods.forEach(action)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Class<*>.getMethodForAll(name: String, vararg parameterTypes: Class<*>?): Method? {
|
fun Class<*>.getMethodForAll(name: String, vararg parameterTypes: Class<*>?): Method? {
|
||||||
@ -325,6 +340,20 @@ val Class<*>.allMethods: List<Method>
|
|||||||
return fieldList
|
return fieldList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val Class<*>.allMethodsSequence: Sequence<Method>
|
||||||
|
get() = sequence {
|
||||||
|
var clazz = this@allMethodsSequence
|
||||||
|
while (clazz != Any::class.java) {
|
||||||
|
clazz.declaredMethods.forEach {
|
||||||
|
yield(it)
|
||||||
|
}
|
||||||
|
clazz = clazz.superclass
|
||||||
|
}
|
||||||
|
clazz.declaredMethods.forEach {
|
||||||
|
yield(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取一个 KProperty<*> 对应的对象
|
* 获取一个 KProperty<*> 对应的对象
|
||||||
*/
|
*/
|
||||||
@ -342,7 +371,7 @@ val KProperty<*>.receiver: Any?
|
|||||||
|
|
||||||
val KProperty<*>.owner: Class<*>?
|
val KProperty<*>.owner: Class<*>?
|
||||||
get() = try {
|
get() = try {
|
||||||
Utils.ownerField.get(this)?.cast<Class<*>>()
|
Utils.ownerField.get(this)?.uncheckedCast<Class<*>>()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
null
|
null
|
||||||
} ?: javaClass.getFieldForAll("owner")?.let {
|
} ?: javaClass.getFieldForAll("owner")?.let {
|
||||||
@ -382,16 +411,6 @@ fun Any.serialize(): ByteArray {
|
|||||||
return outputStream.toByteArray()
|
return outputStream.toByteArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline infix fun String.ifEmpty(ifEmpty: () -> String) = if (isNotEmpty()) this else ifEmpty()
|
|
||||||
inline infix fun String.ifBlank(ifBlank: () -> String) = if (isNotBlank()) this else ifBlank()
|
|
||||||
|
|
||||||
@JvmName("ifEmptyNullable")
|
|
||||||
inline fun String.ifEmpty(ifEmpty: () -> String?) = if (isNotEmpty()) this else ifEmpty()
|
|
||||||
|
|
||||||
@JvmName("ifBlankNullable")
|
|
||||||
inline fun String.ifBlank(ifBlank: () -> String?) = if (isNotBlank()) this else ifBlank()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用 condition 做条件判断,如果返回 true 则使用 then 生成结果,否则范湖自身
|
* 使用 condition 做条件判断,如果返回 true 则使用 then 生成结果,否则范湖自身
|
||||||
*/
|
*/
|
||||||
@ -428,9 +447,9 @@ inline val KClass<*>.companionObjectInstanceOrNull: Any?
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
inline val <K : Any, V> Map<K?, V>.notNullKey get() = cast<Map<K, V>>()
|
inline val <K : Any, V> Map<K?, V>.notNullKey get() = uncheckedCast<Map<K, V>>()
|
||||||
inline val <K, V : Any> Map<K, V?>.notNullValue get() = cast<Map<K, V>>()
|
inline val <K, V : Any> Map<K, V?>.notNullValue get() = uncheckedCast<Map<K, V>>()
|
||||||
inline val <K : Any, V : Any> Map<K?, V?>.notNullEntry get() = cast<Map<K, V>>()
|
inline val <K : Any, V : Any> Map<K?, V?>.notNullEntry get() = uncheckedCast<Map<K, V>>()
|
||||||
|
|
||||||
inline val <K : Any, V> Map<K?, V>.filterNullKey get() = filter { it.key != null }.notNullKey
|
inline val <K : Any, V> Map<K?, V>.filterNullKey get() = filter { it.key != null }.notNullKey
|
||||||
inline val <K, V : Any> Map<K, V?>.filterNullValue get() = filter { it.value != null }.notNullValue
|
inline val <K, V : Any> Map<K, V?>.filterNullValue get() = filter { it.value != null }.notNullValue
|
||||||
@ -442,7 +461,7 @@ val <T : Any> KClass<T>.allMemberProperties: List<KProperty1<T, *>>
|
|||||||
!it.java.isInterface
|
!it.java.isInterface
|
||||||
}
|
}
|
||||||
while (superClass != null) {
|
while (superClass != null) {
|
||||||
propertiesList.addAll(superClass.memberProperties.cast())
|
propertiesList.addAll(superClass.memberProperties.uncheckedCast())
|
||||||
superClass = superClass.superclasses.firstOrNull {
|
superClass = superClass.superclasses.firstOrNull {
|
||||||
!it.java.isInterface
|
!it.java.isInterface
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,48 @@
|
|||||||
dependencies {
|
plugins {
|
||||||
implementation(project(":"))
|
kotlin("jvm")
|
||||||
implementation(project(":utils"))
|
`maven-publish`
|
||||||
api project (":utils:xml")
|
}
|
||||||
|
|
||||||
// kotlin 协程
|
dependencies {
|
||||||
compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2'
|
api(project(":"))
|
||||||
// kotlin 反射
|
api(project(":ts-core"))
|
||||||
//implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
api(project(":ts-core:ts-buffer"))
|
||||||
// OkHttp
|
implementation(project(":ts-core:ts-xml"))
|
||||||
//implementation("com.squareup.okhttp3:okhttp:3.14.1")
|
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2")
|
||||||
//implementation group: 'cglib', name: 'cglib', version: '3.3.0'
|
api(group = "com.squareup.retrofit2", name = "converter-gson", version = "2.9.0")
|
||||||
// https://mvnrepository.com/artifact/com.squareup.retrofit2/converter-gson
|
|
||||||
api group : 'com.squareup.retrofit2', name: 'converter-gson', version: '2.9.0'
|
|
||||||
// https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit
|
// https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit
|
||||||
compile group : 'com.squareup.retrofit2', name: 'retrofit', version: '2.9.0'
|
api(group = "com.squareup.retrofit2", name = "retrofit", version = "2.9.0")
|
||||||
|
|
||||||
// https://mvnrepository.com/artifact/org.jsoup/jsoup
|
// https://mvnrepository.com/artifact/org.jsoup/jsoup
|
||||||
api group : 'org.jsoup', name: 'jsoup', version: '1.13.1'
|
api(group = "org.jsoup", name = "jsoup", version = "1.13.1")
|
||||||
|
|
||||||
|
|
||||||
|
testImplementation(project(":ts-core:ts-coroutine"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Suppress("UNCHECKED_CAST")
|
||||||
|
(rootProject.ext["excludeTest"] as (Project, TaskContainer) -> Unit)(project, tasks)
|
||||||
|
|
||||||
|
tasks.register("install") {
|
||||||
|
finalizedBy(tasks["publishToMavenLocal"])
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacts {
|
||||||
|
archives(tasks["kotlinSourcesJar"])
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
create<MavenPublication>("maven") {
|
||||||
|
groupId = project.group.toString()
|
||||||
|
artifactId = project.name
|
||||||
|
version = project.version.toString()
|
||||||
|
|
||||||
|
from(components["java"])
|
||||||
|
try {
|
||||||
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package cn.tursom.http
|
package cn.tursom.http
|
||||||
|
|
||||||
import cn.tursom.core.isInheritanceFrom
|
import cn.tursom.core.isInheritanceFrom
|
||||||
import cn.tursom.utils.xml.Xml
|
import cn.tursom.core.xml.Xml
|
||||||
import okhttp3.MediaType
|
import okhttp3.MediaType
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package cn.tursom.http
|
package cn.tursom.http
|
||||||
|
|
||||||
import cn.tursom.utils.coroutine.MainDispatcher
|
import cn.tursom.core.Utils.gson
|
||||||
import cn.tursom.utils.gson
|
import cn.tursom.core.coroutine.MainDispatcher
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -15,6 +15,10 @@ tasks.register("install") {
|
|||||||
finalizedBy(tasks["publishToMavenLocal"])
|
finalizedBy(tasks["publishToMavenLocal"])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
artifacts {
|
||||||
|
archives(tasks["kotlinSourcesJar"])
|
||||||
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
create<MavenPublication>("maven") {
|
create<MavenPublication>("maven") {
|
||||||
@ -24,7 +28,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ plugins {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":"))
|
implementation(project(":"))
|
||||||
implementation(project(":ts-core"))
|
implementation(project(":ts-core"))
|
||||||
|
implementation(project(":ts-core:ts-log"))
|
||||||
implementation(project(":ts-core:ts-datastruct"))
|
implementation(project(":ts-core:ts-datastruct"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import kotlin.reflect.KClass
|
|||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
@Target(AnnotationTarget.FIELD)
|
@Target(AnnotationTarget.FIELD)
|
||||||
annotation class Key(
|
annotation class Key(
|
||||||
val key: String = "",
|
val key: String = "",
|
||||||
val clazz: KClass<*> = Any::class,
|
val clazz: KClass<*> = Any::class,
|
||||||
val handler: String = ""
|
val handler: String = "",
|
||||||
)
|
)
|
||||||
|
@ -5,5 +5,5 @@ import kotlin.reflect.KClass
|
|||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
@Target(AnnotationTarget.CLASS)
|
@Target(AnnotationTarget.CLASS)
|
||||||
annotation class NoPropertyClone(
|
annotation class NoPropertyClone(
|
||||||
vararg val classList: KClass<*>
|
vararg val classList: KClass<*>,
|
||||||
)
|
)
|
@ -5,11 +5,11 @@ import kotlin.reflect.KClass
|
|||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
@Target(AnnotationTarget.FIELD)
|
@Target(AnnotationTarget.FIELD)
|
||||||
annotation class Relation(
|
annotation class Relation(
|
||||||
val clazz: KClass<*>,
|
val clazz: KClass<*>,
|
||||||
val property: String = "",
|
val property: String = "",
|
||||||
val skip: Boolean = false,
|
val skip: Boolean = false,
|
||||||
val handler: String = "",
|
val handler: String = "",
|
||||||
val handleClass: KClass<*> = Any::class
|
val handleClass: KClass<*> = Any::class,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,5 +3,5 @@ package cn.tursom.core.clone
|
|||||||
@Retention(AnnotationRetention.RUNTIME)
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
@Target(AnnotationTarget.FIELD)
|
@Target(AnnotationTarget.FIELD)
|
||||||
annotation class Relations(
|
annotation class Relations(
|
||||||
vararg val relations: Relation
|
vararg val relations: Relation,
|
||||||
)
|
)
|
@ -1,110 +1,22 @@
|
|||||||
@file:Suppress("unused")
|
|
||||||
|
|
||||||
package cn.tursom.core.clone
|
package cn.tursom.core.clone
|
||||||
|
|
||||||
import cn.tursom.core.Unsafe
|
import cn.tursom.core.*
|
||||||
import cn.tursom.core.cast
|
|
||||||
import cn.tursom.core.datastruct.ArrayMap
|
import cn.tursom.core.datastruct.ArrayMap
|
||||||
import cn.tursom.core.datastruct.KPropertyValueMap
|
import cn.tursom.log.impl.Slf4jImpl
|
||||||
import cn.tursom.core.datastruct.ReadWriteMap
|
|
||||||
import cn.tursom.core.datastruct.SoftArrayMap
|
|
||||||
import cn.tursom.core.final
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KMutableProperty1
|
|
||||||
import kotlin.reflect.KProperty1
|
import kotlin.reflect.KProperty1
|
||||||
import kotlin.reflect.full.findAnnotation
|
import kotlin.reflect.full.findAnnotation
|
||||||
import kotlin.reflect.full.memberProperties
|
|
||||||
import kotlin.reflect.jvm.isAccessible
|
|
||||||
import kotlin.reflect.jvm.javaField
|
|
||||||
import kotlin.reflect.jvm.javaType
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clone 使用的日志对象
|
||||||
|
*/
|
||||||
|
private val logger = Slf4jImpl.getLogger()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clone 使用的对象属性类型
|
||||||
|
*/
|
||||||
typealias Property<T> = KProperty1<T, Any?>
|
typealias Property<T> = KProperty1<T, Any?>
|
||||||
|
|
||||||
val Any.valueMap: Map<String, Any?>
|
|
||||||
get() = if (this is Map<*, *>) {
|
|
||||||
cast()
|
|
||||||
} else {
|
|
||||||
KPropertyValueMap(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val injectMapCache = ReadWriteMap<KClass<*>, ArrayMap<String, Property<*>?>>(SoftArrayMap(HashMap()))
|
|
||||||
|
|
||||||
val <T : Any> KClass<T>.injectMap: ArrayMap<String, Property<T>?>
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
get() = let {
|
|
||||||
var valueMap = injectMapCache[it] as ArrayMap<String, Property<T>?>?
|
|
||||||
if (valueMap == null) {
|
|
||||||
val properties = it.memberProperties
|
|
||||||
valueMap = ArrayMap(properties.size)
|
|
||||||
(properties as Collection<Property<T>>).forEach { property ->
|
|
||||||
property.isAccessible = true
|
|
||||||
valueMap[property.name] = property
|
|
||||||
}
|
|
||||||
injectMapCache[it] = valueMap as ArrayMap<String, Property<*>?>
|
|
||||||
}
|
|
||||||
valueMap.copy()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val <T : Any> T.injectMap: ArrayMap<String, Property<T>?>
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
get() = (this::class as KClass<T>).injectMap
|
|
||||||
|
|
||||||
private val <T> Array<out Pair<Property<*>, Property<T>?>>.injectMap get() = iterator().injectMap
|
|
||||||
private val <T> Iterator<Pair<Property<*>, Property<T>?>>.injectMap
|
|
||||||
get() = let {
|
|
||||||
val valueMap = ArrayMap<String, Property<T>?>()
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
forEach { (k, field) ->
|
|
||||||
field?.isAccessible = true
|
|
||||||
valueMap[k.name] = field
|
|
||||||
}
|
|
||||||
//logger.trace("Iterator.injectMap: {}", valueMap)
|
|
||||||
valueMap
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <T : Any> T.injectMap(clazz: KClass<*>?): ArrayMap<String, Property<T>?> = this::class
|
|
||||||
.cast<KClass<T>>()
|
|
||||||
.injectMap
|
|
||||||
.also {
|
|
||||||
if (clazz == null) return@also
|
|
||||||
val clazzThis = this::class.java
|
|
||||||
|
|
||||||
fun import(relation: Relation, property: Property<T>) {
|
|
||||||
if (relation.clazz != clazz) return
|
|
||||||
//logger.trace("relation {} to {}", relation.property, property.name)
|
|
||||||
it[relation.property] = when {
|
|
||||||
relation.skip -> null
|
|
||||||
relation.handler.isEmpty() -> property
|
|
||||||
else -> try {
|
|
||||||
val handler = clazzThis.getDeclaredMethod(relation.handler, relation.handleClass.java)
|
|
||||||
handler.isAccessible = true
|
|
||||||
object : KMutableProperty1<T, Any?>, KProperty1<T, Any?> by property {
|
|
||||||
override val setter: KMutableProperty1.Setter<T, Any?> get() = TODO()
|
|
||||||
override fun set(receiver: T, value: Any?) =
|
|
||||||
handler(this@injectMap, value).inject(receiver, property)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
//logger.warn("an exception caused on generate inject handler", e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun parseAnnotation(annotation: Annotation, property: Property<T>) {
|
|
||||||
when (annotation) {
|
|
||||||
is Relation -> import(annotation, property)
|
|
||||||
is Relations -> annotation.relations.forEach { relation -> import(relation, property) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this::class.memberProperties.cast<Collection<KProperty1<T, *>>>().forEach { property ->
|
|
||||||
property.annotations.forEach { annotation -> parseAnnotation(annotation, property) }
|
|
||||||
(property.javaField ?: return@forEach).annotations.forEach { annotation ->
|
|
||||||
parseAnnotation(annotation, property)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用于形式化的将List中的数据映射到实体类上
|
* 用于形式化的将List中的数据映射到实体类上
|
||||||
@ -122,7 +34,7 @@ private fun <T : Any> T.injectMap(clazz: KClass<*>?): ArrayMap<String, Property<
|
|||||||
*/
|
*/
|
||||||
inline fun <reified T : Any, S : Any> List<S?>.clone(
|
inline fun <reified T : Any, S : Any> List<S?>.clone(
|
||||||
unsafe: Boolean = true,
|
unsafe: Boolean = true,
|
||||||
vararg relation: Pair<Property<S>, Property<T>?>
|
vararg relation: Pair<Property<S>, Property<T>?>,
|
||||||
): List<T> {
|
): List<T> {
|
||||||
val list = ArrayList<T>(size)
|
val list = ArrayList<T>(size)
|
||||||
val memberMap = T::class.injectMap
|
val memberMap = T::class.injectMap
|
||||||
@ -131,25 +43,28 @@ inline fun <reified T : Any, S : Any> List<S?>.clone(
|
|||||||
}
|
}
|
||||||
forEach {
|
forEach {
|
||||||
it ?: return@forEach
|
it ?: return@forEach
|
||||||
val target = instance<T>(unsafe) ?: return@forEach
|
try {
|
||||||
list.add(it.inject(target, memberMap.iterator()))
|
val target = InstantAllocator[T::class.java, unsafe]
|
||||||
|
list.add(it.inject(target, memberMap.iterator()))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : Any> List<Any?>.clone(
|
inline fun <reified T : Any> List<Any?>.clone(
|
||||||
unsafe: Boolean = true,
|
unsafe: Boolean = true,
|
||||||
vararg relation: Property<T>?
|
vararg relation: Property<T>?,
|
||||||
): T = clone(instance<T>(unsafe)!!, relation.iterator())
|
): T = clone(InstantAllocator[T::class.java, unsafe], relation.iterator())
|
||||||
|
|
||||||
fun <T : Any> List<Any?>.clone(
|
fun <T : Any> List<Any?>.clone(
|
||||||
target: T,
|
target: T,
|
||||||
vararg relation: Property<T>?
|
vararg relation: Property<T>?,
|
||||||
): T = clone(target, relation.iterator())
|
): T = clone(target, relation.iterator())
|
||||||
|
|
||||||
fun <T : Any> List<Any?>.clone(
|
fun <T : Any> List<Any?>.clone(
|
||||||
target: T,
|
target: T,
|
||||||
relation: Iterator<Property<T>?>
|
relation: Iterator<Property<T>?>,
|
||||||
): T = relation.mapIndexed { index, kProperty1 ->
|
): T = relation.mapIndexed { index, kProperty1 ->
|
||||||
(kProperty1 ?: return@mapIndexed null).name to this[index]
|
(kProperty1 ?: return@mapIndexed null).name to this[index]
|
||||||
}.clone(target)
|
}.clone(target)
|
||||||
@ -157,29 +72,30 @@ fun <T : Any> List<Any?>.clone(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 新建并拷贝
|
* 新建并拷贝
|
||||||
|
* @author 王景阔
|
||||||
* 创建类型 T 的实例
|
* 创建类型 T 的实例
|
||||||
* 并将对象两个的所有同名字段拷贝进新建的实例中
|
* 并将对象两个的所有同名字段拷贝进新建的实例中
|
||||||
* @return 新建的实例
|
* @return 新建的实例
|
||||||
* @param unsafe 是否允许使用 Unsafe 创建对象,unsafe 不需调用构造函数,可以在没有默认构造函数的情况下生成对象
|
* @param unsafe 是否允许使用 Unsafe 创建对象,unsafe 不需调用构造函数,可以在没有默认构造函数的情况下生成对象
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline fun <reified T : Any> Any.clone(unsafe: Boolean = true): T = clone(instance<T>(unsafe)!!)
|
inline fun <reified T : Any> Any.clone(unsafe: Boolean = true): T = clone(InstantAllocator[T::class.java, unsafe])
|
||||||
|
|
||||||
fun <T : Any> Any.clone(clazz: Class<T>, unsafe: Boolean = true): T = clone(instance(unsafe, clazz)!!)
|
fun <T : Any> Any.clone(clazz: Class<T>, unsafe: Boolean = true): T = clone(InstantAllocator[clazz, unsafe])
|
||||||
|
|
||||||
@JvmName("unsafeClone")
|
@JvmName("unsafeClone")
|
||||||
inline fun <reified T : Any> Any.clone(
|
inline fun <reified T : Any> Any.clone(
|
||||||
unsafe: Boolean = true,
|
unsafe: Boolean = true,
|
||||||
vararg relation: Pair<String, Property<T>?>
|
vararg relation: Pair<String, Property<T>?>,
|
||||||
): T = clone(instance<T>(unsafe)!!, relation.iterator())
|
): T = clone(InstantAllocator[T::class.java, unsafe], relation.iterator())
|
||||||
|
|
||||||
inline fun <reified T : Any, S : Any> S.clone(
|
inline fun <reified T : Any, S : Any> S.clone(
|
||||||
unsafe: Boolean = true,
|
unsafe: Boolean = true,
|
||||||
vararg relation: Pair<Property<S>, Property<T>?>
|
vararg relation: Pair<Property<S>, Property<T>?>,
|
||||||
): T = clone(instance<T>(unsafe)!!, relation.iterator())
|
): T = clone(InstantAllocator[T::class.java, unsafe], relation.iterator())
|
||||||
|
|
||||||
fun Any.cloneMap(): Map<in String, Any?> = when (this) {
|
fun Any.cloneMap(): Map<in String, Any?> = when (this) {
|
||||||
is Map<*, *> -> @Suppress("UNCHECKED_CAST") (this as Map<Any?, Any?>).mapKeys { it.key.toString() }
|
is Map<*, *> -> uncheckedCast<Map<Any?, Any?>>().mapKeys { it.key.toString() }
|
||||||
is Iterator<*> -> {
|
is Iterator<*> -> {
|
||||||
val valueMap = HashMap<String, Any?>()
|
val valueMap = HashMap<String, Any?>()
|
||||||
(this as Iterator<Any?>).forEach {
|
(this as Iterator<Any?>).forEach {
|
||||||
@ -201,22 +117,22 @@ fun <T : Any> Any.clone(target: T): T = apply { injectWithoutProperty(target) }.
|
|||||||
|
|
||||||
fun <T : Any, S : Any> S.clone(
|
fun <T : Any, S : Any> S.clone(
|
||||||
target: T,
|
target: T,
|
||||||
iterator: Iterator<Pair<Property<S>, Property<T>?>>
|
iterator: Iterator<Pair<Property<S>, Property<T>?>>,
|
||||||
): T = apply { injectWithoutProperty(target) }.checkPropertyClone(target) {
|
): T = apply { injectWithoutProperty(target) }.checkPropertyClone(target) {
|
||||||
valueMap
|
valueMap
|
||||||
//.also { logger.trace("clone {} into {}, value map:{}", this, target, it) }
|
.also { logger.trace("clone {} into {}, value map:{}", this, target, it) }
|
||||||
.clone(target, iterator.injectMap.iterator(), this::class)
|
.clone(target, iterator.injectMap.iterator(), this::class)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Any> Any.clone(
|
fun <T : Any> Any.clone(
|
||||||
target: T,
|
target: T,
|
||||||
vararg relation: Pair<String, Property<T>?>
|
vararg relation: Pair<String, Property<T>?>,
|
||||||
): T = clone(target, relation.iterator())
|
): T = clone(target, relation.iterator())
|
||||||
|
|
||||||
@JvmName("unsafeClone")
|
@JvmName("unsafeClone")
|
||||||
fun <T : Any> Any.clone(
|
fun <T : Any> Any.clone(
|
||||||
target: T,
|
target: T,
|
||||||
iterator: Iterator<Pair<String, Property<T>?>>
|
iterator: Iterator<Pair<String, Property<T>?>>,
|
||||||
): T = apply { injectWithoutProperty(target) }.checkPropertyClone(target) {
|
): T = apply { injectWithoutProperty(target) }.checkPropertyClone(target) {
|
||||||
valueMap.clone(target, iterator, this::class)
|
valueMap.clone(target, iterator, this::class)
|
||||||
}
|
}
|
||||||
@ -225,9 +141,9 @@ fun <T : Any> Any.clone(
|
|||||||
fun <T : Any> Map<in String, Any?>.clone(
|
fun <T : Any> Map<in String, Any?>.clone(
|
||||||
target: T,
|
target: T,
|
||||||
iterator: Iterator<Pair<String, Property<T>?>>,
|
iterator: Iterator<Pair<String, Property<T>?>>,
|
||||||
clazz: KClass<*>? = null
|
clazz: KClass<*>? = null,
|
||||||
): T {
|
): T {
|
||||||
val memberMap = target.injectMap(clazz) as MutableMap<String, Property<T>?>
|
val memberMap = target.injectMap(clazz)
|
||||||
iterator.forEach { (k, v) ->
|
iterator.forEach { (k, v) ->
|
||||||
memberMap[k] = v
|
memberMap[k] = v
|
||||||
}
|
}
|
||||||
@ -238,9 +154,9 @@ fun <T : Any> Map<in String, Any?>.clone(
|
|||||||
fun <T : Any> Map<in String, Any?>.clone(
|
fun <T : Any> Map<in String, Any?>.clone(
|
||||||
target: T,
|
target: T,
|
||||||
iterator: Iterator<Pair<Property<T>, Property<T>?>>,
|
iterator: Iterator<Pair<Property<T>, Property<T>?>>,
|
||||||
clazz: KClass<*>? = null
|
clazz: KClass<*>? = null,
|
||||||
): T {
|
): T {
|
||||||
val memberMap = target.injectMap(clazz) as MutableMap<String, Property<T>?>
|
val memberMap = target.injectMap(clazz)
|
||||||
iterator.forEach { (k, v) ->
|
iterator.forEach { (k, v) ->
|
||||||
memberMap[k.get(target)?.toString() ?: return@forEach] = v
|
memberMap[k.get(target)?.toString() ?: return@forEach] = v
|
||||||
}
|
}
|
||||||
@ -251,13 +167,13 @@ fun <T : Any> Map<in String, Any?>.clone(
|
|||||||
fun <T : Any> Map<in String, Any?>.clone(
|
fun <T : Any> Map<in String, Any?>.clone(
|
||||||
target: T,
|
target: T,
|
||||||
iterator: Iterator<Map.Entry<String?, Property<T>?>>,
|
iterator: Iterator<Map.Entry<String?, Property<T>?>>,
|
||||||
clazz: KClass<*>? = null
|
clazz: KClass<*>? = null,
|
||||||
): T {
|
): T {
|
||||||
val memberMap = target.injectMap(clazz)
|
val memberMap = target.injectMap(clazz)
|
||||||
iterator.forEach { (k, v) ->
|
iterator.forEach { (k, v) ->
|
||||||
memberMap[k ?: return@forEach] = v
|
memberMap[k ?: return@forEach] = v
|
||||||
}
|
}
|
||||||
//logger.trace("inject {} into {}, mapping: {}", this, target, memberMap)
|
logger.trace("inject {} into {}, mapping: {}", this, target, memberMap)
|
||||||
return inject(target, memberMap.iterator())
|
return inject(target, memberMap.iterator())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,229 +184,6 @@ fun <T : Any> Any.checkPropertyClone(target: T, ifClone: () -> T): T =
|
|||||||
target
|
target
|
||||||
}
|
}
|
||||||
|
|
||||||
//fun <T> Any.checkPropertyClone(targetClass: KClass<out Any>, ifClone: () -> T): T {
|
|
||||||
// if (targetClass.findAnnotation<NoPropertyClone>()?.classList?.contains(this::class) != true)
|
|
||||||
// ifClone()
|
|
||||||
//}
|
|
||||||
|
|
||||||
fun <T : Any> Any.injectWithoutProperty(target: T): T {
|
|
||||||
fun parseAnnotation(relation: Relation, property: KProperty1<Any, *>) {
|
|
||||||
if (relation.property.isEmpty() && relation.clazz.java.isInstance(this)) try {
|
|
||||||
val handler = target::class.java.getDeclaredMethod(relation.handler, relation.clazz.java)
|
|
||||||
handler.isAccessible = true
|
|
||||||
handler(target, this)?.inject(target, property)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
//logger.warn("an exception caused on global inject", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
target::class.memberProperties
|
|
||||||
.cast<Collection<KProperty1<Any, *>>>()
|
|
||||||
.forEach { property ->
|
|
||||||
property.annotations.forEach { annotation ->
|
|
||||||
when (annotation) {
|
|
||||||
is Relation -> parseAnnotation(annotation, property)
|
|
||||||
is Relations -> annotation.relations.forEach { parseAnnotation(it, property) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
property.javaField?.annotations?.forEach { annotation ->
|
|
||||||
when (annotation) {
|
|
||||||
is Relation -> parseAnnotation(annotation, property)
|
|
||||||
is Relations -> annotation.relations.forEach { parseAnnotation(it, property) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : Any> Any.inject(
|
|
||||||
target: T,
|
|
||||||
iterator: Iterator<Pair<String?, Property<T>?>>
|
|
||||||
): T = apply { injectWithoutProperty(target) }.checkPropertyClone(target) { valueMap.inject(target, iterator) }
|
|
||||||
|
|
||||||
@JvmName("injectMap")
|
|
||||||
fun <T : Any> Any.inject(
|
|
||||||
target: T,
|
|
||||||
iterator: Iterator<Map.Entry<String?, Property<T>?>>
|
|
||||||
): T = apply { injectWithoutProperty(target) }.checkPropertyClone(target) { valueMap.inject(target, iterator) }
|
|
||||||
|
|
||||||
fun <T : Any> Map<in String, Any?>.inject(
|
|
||||||
target: T,
|
|
||||||
iterator: Iterator<Pair<String, Property<T>?>>
|
|
||||||
): T {
|
|
||||||
iterator.forEach { (k, t) ->
|
|
||||||
val value = this[k] ?: return@forEach
|
|
||||||
value.inject(target, t ?: return@forEach)
|
|
||||||
}
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : Any> Map<in String, Any?>.p2pInject(
|
|
||||||
target: T,
|
|
||||||
iterator: Iterator<Pair<Property<T>, Property<T>?>>
|
|
||||||
): T {
|
|
||||||
iterator.forEach { (k, t) ->
|
|
||||||
val value = this[k(target)?.toString() ?: return@forEach] ?: return@forEach
|
|
||||||
value.inject(target, t ?: return@forEach)
|
|
||||||
}
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmName("injectMap")
|
|
||||||
fun <T : Any> Map<in String, Any?>.inject(
|
|
||||||
target: T,
|
|
||||||
iterator: Iterator<Map.Entry<String, Property<T>?>>
|
|
||||||
): T {
|
|
||||||
iterator.forEach { (k, t) ->
|
|
||||||
val value = this[k] ?: return@forEach
|
|
||||||
value.inject(target, t ?: return@forEach)
|
|
||||||
}
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : Any> Any.inject(target: T, property: Property<T>) {
|
|
||||||
//logger.trace("inject {} into {}.{}", this, +{ target::class.simpleName }, property.name)
|
|
||||||
when (property) {
|
|
||||||
is KMutableProperty1<*, *> -> {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
property as KMutableProperty1<T, Any?>
|
|
||||||
property.isAccessible = true
|
|
||||||
try {
|
|
||||||
property.set(target, cast(this, property.returnType.javaType.cast()) ?: return)
|
|
||||||
} catch (e: ClassCastException) {
|
|
||||||
//logger.trace("inject failed", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
val field = property.javaField ?: return
|
|
||||||
field.isAccessible = true
|
|
||||||
field.final = false
|
|
||||||
try {
|
|
||||||
field.set(target, cast(this, field.type) ?: return)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
//logger.trace("inject failed", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun cast(source: Any, target: Class<*>): Any? = if (target.isInstance(source)) {
|
|
||||||
source
|
|
||||||
} else when (target) {
|
|
||||||
Byte::class.java -> if (source is Number) source.toByte() else source.toString().toByteOrNull()
|
|
||||||
Char::class.java -> if (source is Number) source.toChar() else source.toString().toIntOrNull()?.toChar()
|
|
||||||
Short::class.java -> if (source is Number) source.toShort() else source.toString().toShortOrNull()
|
|
||||||
Int::class.java -> if (source is Number) source.toInt() else source.toString().toIntOrNull()
|
|
||||||
Long::class.java -> if (source is Number) source.toLong() else source.toString().toLongOrNull()
|
|
||||||
Float::class.java -> if (source is Number) source.toFloat() else source.toString().toFloatOrNull()
|
|
||||||
Double::class.java -> if (source is Number) source.toDouble() else source.toString().toDoubleOrNull()
|
|
||||||
Boolean::class.java -> if (source is Number) source != 0 else source.toString().toBoolean()
|
|
||||||
|
|
||||||
java.lang.Byte::class.java -> if (source is Number) source.toByte() else source.toString().toByteOrNull()
|
|
||||||
java.lang.Character::class.java -> if (source is Number) source.toChar() else source.toString().toIntOrNull()
|
|
||||||
?.toChar()
|
|
||||||
java.lang.Short::class.java -> if (source is Number) source.toShort() else source.toString().toShortOrNull()
|
|
||||||
java.lang.Integer::class.java -> if (source is Number) source.toInt() else source.toString().toIntOrNull()
|
|
||||||
java.lang.Long::class.java -> if (source is Number) source.toLong() else source.toString().toLongOrNull()
|
|
||||||
java.lang.Float::class.java -> if (source is Number) source.toFloat() else source.toString().toFloatOrNull()
|
|
||||||
java.lang.Double::class.java -> if (source is Number) source.toDouble() else source.toString().toDoubleOrNull()
|
|
||||||
java.lang.Boolean::class.java -> if (source is Number) source != 0 else source.toString().toBoolean()
|
|
||||||
|
|
||||||
String::class.java -> source.toString()
|
|
||||||
|
|
||||||
else -> source
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : Any> T.read(source: Any?): T = source?.clone(this) ?: this
|
|
||||||
|
|
||||||
fun <T : Any, S : Any> T.read(
|
|
||||||
source: S?,
|
|
||||||
vararg relation: Pair<Property<S>, Property<T>?>
|
|
||||||
): T = source?.clone(this, relation.iterator()) ?: this
|
|
||||||
|
|
||||||
fun <T : Any> T.read(
|
|
||||||
source: Map<in String, Any?>?,
|
|
||||||
vararg relation: Pair<String, Property<T>?>
|
|
||||||
): T = source?.clone(this, relation.iterator()) ?: this
|
|
||||||
|
|
||||||
|
|
||||||
fun <T : Any> T.p2pRead(
|
|
||||||
source: Map<in String, Any?>?,
|
|
||||||
vararg relation: Pair<Property<T>, Property<T>?>
|
|
||||||
): T {
|
|
||||||
//logger.trace("p2p read, source:{}, relation: {}", source, relation)
|
|
||||||
return source?.p2pInject(this, relation.iterator()) ?: this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : Any> T.p2pRead(
|
|
||||||
source: Map<in String, Any?>?
|
|
||||||
): T {
|
|
||||||
source ?: return this
|
|
||||||
val properties = this::class.memberProperties.cast<Collection<KProperty1<T, *>>>()
|
|
||||||
val relation = properties.mapNotNull { property ->
|
|
||||||
val key = property.javaField?.getAnnotation(Key::class.java)?.key ?: return@mapNotNull null
|
|
||||||
val keyProperty = properties.find { it.name == key } ?: return@mapNotNull null
|
|
||||||
keyProperty to property
|
|
||||||
}
|
|
||||||
//logger.trace("p2p read, source:{}, relation: {}", source, relation)
|
|
||||||
return source.p2pInject(this, relation.iterator())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : Any> T.p2pRead(
|
|
||||||
source: Any?
|
|
||||||
): T {
|
|
||||||
source ?: return this
|
|
||||||
val properties = this::class.memberProperties.cast<Collection<KProperty1<T, *>>>()
|
|
||||||
properties.forEach { property ->
|
|
||||||
val keyAnnotation = property.javaField?.getAnnotation(Key::class.java) ?: return@forEach
|
|
||||||
if (keyAnnotation.handler.isEmpty()) return@forEach
|
|
||||||
if (keyAnnotation.clazz.isInstance(source).not()) return@forEach
|
|
||||||
val handler = this::class.java.getDeclaredMethod(keyAnnotation.handler, keyAnnotation.clazz.java)
|
|
||||||
(handler(this, source) ?: return@forEach).inject(this, property)
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : Any, S : Any> List<T>.read(
|
|
||||||
source: List<S>,
|
|
||||||
vararg relation: Pair<Property<S>, Property<T>?>
|
|
||||||
): List<T> {
|
|
||||||
val memberMap = this[0].injectMap as MutableMap<String, Property<T>?>
|
|
||||||
relation.forEach { (k, v) ->
|
|
||||||
memberMap[k.name] = v
|
|
||||||
}
|
|
||||||
return source.mapIndexed { index, it -> it.inject(this[index], memberMap.iterator()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified T : Any> read(vararg values: Any, unsafe: Boolean = true): T {
|
|
||||||
val instance = instance<T>(unsafe)!!
|
|
||||||
values.forEach {
|
|
||||||
it.clone(instance)
|
|
||||||
}
|
|
||||||
return instance
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified T : Any> read(value: Any, unsafe: Boolean = true): T = value.clone(unsafe)
|
|
||||||
|
|
||||||
fun <T : Any> T.readWithoutProperty(vararg values: Any): T {
|
|
||||||
values.forEach {
|
|
||||||
it.injectWithoutProperty(this)
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <reified T> instance(unsafe: Boolean = true) = instance(unsafe, T::class.java)
|
|
||||||
|
|
||||||
fun <T> instance(unsafe: Boolean = true, clazz: Class<T>): T? = try {
|
|
||||||
clazz.newInstance()!!
|
|
||||||
} catch (e: Exception) {
|
|
||||||
if (unsafe) {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
Unsafe.unsafe.allocateInstance(clazz) as T?
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <T, K : Comparable<K>, V> Iterator<T>.mapIndexed(action: (Int, T) -> Pair<K, V>?): Map<K, V> {
|
inline fun <T, K : Comparable<K>, V> Iterator<T>.mapIndexed(action: (Int, T) -> Pair<K, V>?): Map<K, V> {
|
||||||
val map = ArrayMap<K, V>()
|
val map = ArrayMap<K, V>()
|
||||||
@ -502,6 +195,113 @@ inline fun <T, K : Comparable<K>, V> Iterator<T>.mapIndexed(action: (Int, T) ->
|
|||||||
return map
|
return map
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Any> T.mapRead(map: Map<in String, Any?>, key: KProperty1<T, *>): T {
|
fun <T : Any, F : Any?> T.set(field: KProperty1<T, F>, value: F): T {
|
||||||
return read(map[key.get(this)?.toString() ?: return this] ?: return this)
|
(value as Any?)?.inject(this, field as Property<T>)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Any> T.deepClone(): T = when (this) {
|
||||||
|
is Char, is Boolean, is Byte, is Short, is Int, is Long, is Float, is Double, is Class<*> -> this
|
||||||
|
is CharArray -> copyOf().uncheckedCast()
|
||||||
|
is BooleanArray -> copyOf().uncheckedCast()
|
||||||
|
is ByteArray -> copyOf().uncheckedCast()
|
||||||
|
is ShortArray -> copyOf().uncheckedCast()
|
||||||
|
is IntArray -> copyOf().uncheckedCast()
|
||||||
|
is LongArray -> copyOf().uncheckedCast()
|
||||||
|
is FloatArray -> copyOf().uncheckedCast()
|
||||||
|
is DoubleArray -> copyOf().uncheckedCast()
|
||||||
|
else -> deepClone(HashMap())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T : Any> T.deepClone(clonedMap: MutableMap<Any, Any>): T =
|
||||||
|
clonedMap[this]?.uncheckedCast<T>() ?: when (this) {
|
||||||
|
is Char, is Boolean, is Byte, is Short, is Int, is Long, is Float, is Double, is Class<*> -> this
|
||||||
|
is CharArray -> copyOf().uncheckedCast()
|
||||||
|
is BooleanArray -> copyOf().uncheckedCast()
|
||||||
|
is ByteArray -> copyOf().uncheckedCast()
|
||||||
|
is ShortArray -> copyOf().uncheckedCast()
|
||||||
|
is IntArray -> copyOf().uncheckedCast()
|
||||||
|
is LongArray -> copyOf().uncheckedCast()
|
||||||
|
is FloatArray -> copyOf().uncheckedCast()
|
||||||
|
is DoubleArray -> copyOf().uncheckedCast()
|
||||||
|
is Array<*> -> {
|
||||||
|
val instance = java.lang.reflect.Array.newInstance(javaClass.componentType, size).uncheckedCast<Array<Any?>>()
|
||||||
|
forEachIndexed { index, it ->
|
||||||
|
instance[index] = it?.deepClone(clonedMap)
|
||||||
|
}
|
||||||
|
instance.uncheckedCast()
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val clazz = javaClass
|
||||||
|
val newInstance = unsafeInstance(clazz)!!
|
||||||
|
clonedMap[this] = newInstance
|
||||||
|
clazz.forAllFields { field ->
|
||||||
|
if (field.isStatic()) return@forAllFields
|
||||||
|
field.isAccessible = true
|
||||||
|
field.set(newInstance, field.get(this)?.deepClone(clonedMap))
|
||||||
|
}
|
||||||
|
newInstance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Any?.details(name: String = "", skipStatic: Boolean = true) = buildString {
|
||||||
|
this@details.details(HashMap(), this, "", name, skipStatic)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Any?.details(
|
||||||
|
map: MutableMap<Any, Int>,
|
||||||
|
builder: StringBuilder,
|
||||||
|
indentation: String,
|
||||||
|
name: String = "",
|
||||||
|
skipStatic: Boolean = true,
|
||||||
|
directValue: String = "|- ",
|
||||||
|
objectValue: String = "/- ",
|
||||||
|
hint: String = "${TextColor.red}|${TextColor.reset} ",
|
||||||
|
tmpIndentation: String = "",
|
||||||
|
type: String? = null,
|
||||||
|
) {
|
||||||
|
when (this) {
|
||||||
|
null, is Char, is Boolean, is Byte, is Short, is Int, is Long, is Float, is Double, is Class<*>, is String ->
|
||||||
|
builder.append("$indentation$tmpIndentation$directValue$name(${type ?: this?.javaClass?.name ?: "null"}): $this\n")
|
||||||
|
is CharArray -> builder.append("$indentation$tmpIndentation$directValue$name(CharArray): ${String(this)}\n")
|
||||||
|
is BooleanArray -> builder.append("$indentation$tmpIndentation$directValue$name(BooleanArray): ${asList()}\n")
|
||||||
|
is ByteArray -> builder.append("$indentation$tmpIndentation$directValue$name(ByteArray): 0x${toHexString()}\n")
|
||||||
|
is ShortArray -> builder.append("$indentation$tmpIndentation$directValue$name(ShortArray): ${asList()}\n")
|
||||||
|
is IntArray -> builder.append("$indentation$tmpIndentation$directValue$name(IntArray): ${asList()}\n")
|
||||||
|
is LongArray -> builder.append("$indentation$tmpIndentation$directValue$name(LongArray): ${asList()}\n")
|
||||||
|
is FloatArray -> builder.append("$indentation$tmpIndentation$directValue$name(FloatArray): ${asList()}\n")
|
||||||
|
is DoubleArray -> builder.append("$indentation$tmpIndentation$directValue$name(DoubleArray): ${asList()}\n")
|
||||||
|
is Array<*> -> {
|
||||||
|
builder.append("$indentation$tmpIndentation$objectValue$name: (Array<${javaClass.componentType.name}>, ${hashCode()})\n")
|
||||||
|
if (this !in map) {
|
||||||
|
map[this] = hashCode()
|
||||||
|
val newIndentation = "$indentation$hint"
|
||||||
|
forEachIndexed { index, it ->
|
||||||
|
val newTmpIndentation = "|- ${name.ifEmpty { "array" }}[$index]"
|
||||||
|
it.details(
|
||||||
|
map, builder, newIndentation,
|
||||||
|
skipStatic = skipStatic,
|
||||||
|
directValue = " = ",
|
||||||
|
objectValue = " = /- ",
|
||||||
|
hint = "${TextColor.red}|${TextColor.reset} ${" ".repeat(newTmpIndentation.length + 1)}${TextColor.red}|${TextColor.reset} ",
|
||||||
|
tmpIndentation = newTmpIndentation
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in map -> builder.append("$indentation$tmpIndentation$directValue$name${if (name.isNotEmpty()) ": " else ""}(${javaClass.name}, ${map[this]}, generated)\n")
|
||||||
|
else -> {
|
||||||
|
map[this] = this.hashCode()
|
||||||
|
builder.append("$indentation$tmpIndentation$objectValue$name${if (name.isNotEmpty()) ": " else ""}(${javaClass.name}, ${hashCode()})\n")
|
||||||
|
val newIndentation = "$indentation$hint"
|
||||||
|
javaClass.forAllFields { field ->
|
||||||
|
if (skipStatic && field.isStatic()) {
|
||||||
|
return@forAllFields
|
||||||
|
}
|
||||||
|
field.isAccessible = true
|
||||||
|
val value = field.get(this)
|
||||||
|
value.details(map, builder, newIndentation, field.name, skipStatic, type = field.type.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,267 @@
|
|||||||
|
package cn.tursom.core.clone
|
||||||
|
|
||||||
|
import cn.tursom.core.*
|
||||||
|
import cn.tursom.core.datastruct.KPropertyValueMap
|
||||||
|
import cn.tursom.core.datastruct.SoftArrayMap
|
||||||
|
import cn.tursom.log.impl.Slf4jImpl
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import kotlin.collections.component1
|
||||||
|
import kotlin.collections.component2
|
||||||
|
import kotlin.collections.set
|
||||||
|
import kotlin.reflect.*
|
||||||
|
import kotlin.reflect.full.memberProperties
|
||||||
|
import kotlin.reflect.jvm.isAccessible
|
||||||
|
import kotlin.reflect.jvm.javaField
|
||||||
|
import kotlin.reflect.jvm.javaType
|
||||||
|
|
||||||
|
private val logger = Slf4jImpl().logger
|
||||||
|
|
||||||
|
val Any.valueMap: Map<String, Any?>
|
||||||
|
get() = if (this is Map<*, *>) {
|
||||||
|
uncheckedCast()
|
||||||
|
} else {
|
||||||
|
KPropertyValueMap(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val injectMapCache = SoftArrayMap<KClass<*>, Map<String, Property<*>?>>(ConcurrentHashMap())
|
||||||
|
|
||||||
|
val <T : Any> KClass<T>.injectMap: MutableMap<String, Property<T>?>
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
get() {
|
||||||
|
var injectMap = injectMapCache[this] as Map<String, Property<T>?>?
|
||||||
|
if (injectMap == null) {
|
||||||
|
injectMap = allMemberProperties.associateByTo(HashMap()) { property ->
|
||||||
|
property.isAccessible = true
|
||||||
|
property.name
|
||||||
|
}
|
||||||
|
injectMapCache[this] = injectMap as Map<String, Property<*>?>
|
||||||
|
}
|
||||||
|
return HashMap(injectMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val <T : Any> T.injectMap: MutableMap<String, Property<T>?>
|
||||||
|
get() = this::class.uncheckedCast<KClass<T>>().injectMap
|
||||||
|
|
||||||
|
internal val <T> Iterator<Pair<Property<*>, Property<T>?>>.injectMap
|
||||||
|
get() = let {
|
||||||
|
val valueMap = HashMap<String, Property<T>?>()
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
forEach { (k, field) ->
|
||||||
|
field?.isAccessible = true
|
||||||
|
valueMap[k.name] = field
|
||||||
|
}
|
||||||
|
logger.trace("Iterator.injectMap: {}", valueMap)
|
||||||
|
valueMap
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun <T : Any> T.injectMap(targetClazz: KClass<*>?): MutableMap<String, Property<T>?> = this::class
|
||||||
|
.uncheckedCast<KClass<T>>()
|
||||||
|
.injectMap
|
||||||
|
.also { injectMap ->
|
||||||
|
if (targetClazz == null) return@also
|
||||||
|
val clazzThis = this::class.java
|
||||||
|
|
||||||
|
fun import(relation: Relation, property: Property<T>) {
|
||||||
|
if (relation.clazz != targetClazz) return
|
||||||
|
var propertyName = relation.property
|
||||||
|
if (propertyName.isBlank()) {
|
||||||
|
propertyName = property.name
|
||||||
|
}
|
||||||
|
logger.trace("relation {} to {}", propertyName, property.name)
|
||||||
|
injectMap[propertyName] = when {
|
||||||
|
relation.skip -> null
|
||||||
|
relation.handler.isEmpty() -> property
|
||||||
|
else -> try {
|
||||||
|
val handler = clazzThis.getDeclaredMethod(relation.handler, relation.handleClass.java)
|
||||||
|
handler.isAccessible = true
|
||||||
|
object : KMutableProperty1<T, Any?>, KProperty1<T, Any?> by property {
|
||||||
|
override val setter: KMutableProperty1.Setter<T, Any?>
|
||||||
|
get() = object : KMutableProperty1.Setter<T, Any?>, KCallable<Unit> by property.uncheckedCast() {
|
||||||
|
override val isExternal: Boolean get() = false
|
||||||
|
override val isInfix: Boolean get() = false
|
||||||
|
override val isInline: Boolean get() = false
|
||||||
|
override val isOperator: Boolean get() = false
|
||||||
|
override val isSuspend: Boolean get() = false
|
||||||
|
override val property: KProperty<Any?> get() = property
|
||||||
|
override fun invoke(receiver: T, value: Any?) =
|
||||||
|
handler(this@injectMap, value).inject(receiver, property)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun set(receiver: T, value: Any?) = try {
|
||||||
|
handler(this@injectMap, value).inject(receiver, property)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.trace("", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.warn("an exception caused on generate inject handler", e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseAnnotation(annotation: Annotation, property: Property<T>) {
|
||||||
|
when (annotation) {
|
||||||
|
is Relation -> import(annotation, property)
|
||||||
|
is Relations -> annotation.relations.forEach { relation -> import(relation, property) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this::class.memberProperties.uncheckedCast<Collection<KProperty1<T, *>>>().forEach { property ->
|
||||||
|
property.annotations.forEach { annotation -> parseAnnotation(annotation, property) }
|
||||||
|
(property.javaField ?: return@forEach).annotations.forEach { annotation ->
|
||||||
|
parseAnnotation(annotation, property)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Any> Any.injectWithoutProperty(target: T): T {
|
||||||
|
fun parseAnnotation(relation: Relation, property: KProperty1<Any, *>) {
|
||||||
|
if (relation.property.isEmpty() && relation.clazz.java.isInstance(this)) try {
|
||||||
|
val handler = target::class.java.getDeclaredMethod(relation.handler, relation.clazz.java)
|
||||||
|
handler.isAccessible = true
|
||||||
|
handler(target, this)?.inject(target, property)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.trace("an exception caused on global inject", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
target::class.memberProperties
|
||||||
|
.uncheckedCast<Collection<KProperty1<Any, *>>>()
|
||||||
|
.forEach { property ->
|
||||||
|
property.annotations.forEach { annotation ->
|
||||||
|
when (annotation) {
|
||||||
|
is Relation -> parseAnnotation(annotation, property)
|
||||||
|
is Relations -> annotation.relations.forEach { parseAnnotation(it, property) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
property.javaField?.annotations?.forEach { annotation ->
|
||||||
|
when (annotation) {
|
||||||
|
is Relation -> parseAnnotation(annotation, property)
|
||||||
|
is Relations -> annotation.relations.forEach { parseAnnotation(it, property) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Any> Any.inject(
|
||||||
|
target: T,
|
||||||
|
iterator: Iterator<Pair<String?, Property<T>?>>,
|
||||||
|
): T = apply { injectWithoutProperty(target) }.checkPropertyClone(target) { valueMap.inject(target, iterator) }
|
||||||
|
|
||||||
|
@JvmName("injectMap")
|
||||||
|
fun <T : Any> Any.inject(
|
||||||
|
target: T,
|
||||||
|
iterator: Iterator<Map.Entry<String?, Property<T>?>>,
|
||||||
|
): T = apply { injectWithoutProperty(target) }.checkPropertyClone(target) { valueMap.inject(target, iterator) }
|
||||||
|
|
||||||
|
fun <T : Any> Map<in String, Any?>.inject(
|
||||||
|
target: T,
|
||||||
|
iterator: Iterator<Pair<String, Property<T>?>>,
|
||||||
|
): T {
|
||||||
|
iterator.forEach { (k, t) ->
|
||||||
|
val value = this[k] ?: return@forEach
|
||||||
|
value.inject(target, t ?: return@forEach)
|
||||||
|
}
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* point to point inject
|
||||||
|
* 通过指定映射关系,从本map中取出数据并注入到目标对象中
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
fun <T : Any> Map<in String, Any?>.p2pInject(
|
||||||
|
target: T,
|
||||||
|
iterator: Iterator<Pair<Property<T>, Property<T>?>>,
|
||||||
|
): T {
|
||||||
|
iterator.forEach { (k, t) ->
|
||||||
|
val value = this[k(target)?.toString() ?: return@forEach] ?: return@forEach
|
||||||
|
value.inject(target, t ?: return@forEach)
|
||||||
|
}
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("injectMap")
|
||||||
|
fun <T : Any> Map<in String, Any?>.inject(
|
||||||
|
target: T,
|
||||||
|
iterator: Iterator<Map.Entry<String, Property<T>?>>,
|
||||||
|
): T {
|
||||||
|
iterator.forEach { (k, t) ->
|
||||||
|
val value = this[k] ?: return@forEach
|
||||||
|
value.inject(target, t ?: return@forEach)
|
||||||
|
}
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Any> Any.inject(target: T, property: Property<T>) {
|
||||||
|
logger.trace("inject {} into {}.{}", this, +{ target::class.simpleName }, property.name)
|
||||||
|
when (property) {
|
||||||
|
is KMutableProperty1<*, *> -> {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
property as KMutableProperty1<T, Any?>
|
||||||
|
property.isAccessible = true
|
||||||
|
try {
|
||||||
|
property.set(target, cast(this, property.returnType.javaType.uncheckedCast()) ?: return)
|
||||||
|
} catch (e: ClassCastException) {
|
||||||
|
if (logger.isTraceEnabled) {
|
||||||
|
logger.trace("inject {} failed", property.name, e)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.error("inject {} failed", property.name, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val field = property.javaField ?: return
|
||||||
|
field.isAccessible = true
|
||||||
|
try {
|
||||||
|
field.set(target, cast(this, field.type) ?: return)
|
||||||
|
} catch (e: ClassCastException) {
|
||||||
|
if (logger.isTraceEnabled) {
|
||||||
|
logger.trace("inject {} failed", property.name, e)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.error("inject {} failed", property.name, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun cast(source: Any, target: Class<*>): Any? = if (target.isInstance(source)) {
|
||||||
|
source
|
||||||
|
} else when (target) {
|
||||||
|
Byte::class.java -> if (source is Number) source.toByte() else source.toString().toByteOrNull()
|
||||||
|
Char::class.java -> if (source is Number) source.toChar() else source.toString().toIntOrNull()?.toChar()
|
||||||
|
Short::class.java -> if (source is Number) source.toShort() else source.toString().toShortOrNull()
|
||||||
|
Int::class.java -> if (source is Number) source.toInt() else source.toString().toIntOrNull()
|
||||||
|
Long::class.java -> if (source is Number) source.toLong() else source.toString().toLongOrNull()
|
||||||
|
Float::class.java -> if (source is Number) source.toFloat() else source.toString().toFloatOrNull()
|
||||||
|
Double::class.java -> if (source is Number) source.toDouble() else source.toString().toDoubleOrNull()
|
||||||
|
Boolean::class.java -> if (source is Number) source != 0 else source.toString().toBoolean()
|
||||||
|
|
||||||
|
java.lang.Byte::class.java -> if (source is Number) source.toByte() else source.toString().toByteOrNull()
|
||||||
|
java.lang.Character::class.java -> if (source is Number) source.toChar() else source.toString().toIntOrNull()
|
||||||
|
?.toChar()
|
||||||
|
java.lang.Short::class.java -> if (source is Number) source.toShort() else source.toString().toShortOrNull()
|
||||||
|
java.lang.Integer::class.java -> if (source is Number) source.toInt() else source.toString().toIntOrNull()
|
||||||
|
java.lang.Long::class.java -> if (source is Number) source.toLong() else source.toString().toLongOrNull()
|
||||||
|
java.lang.Float::class.java -> if (source is Number) source.toFloat() else source.toString().toFloatOrNull()
|
||||||
|
java.lang.Double::class.java -> if (source is Number) source.toDouble() else source.toString().toDoubleOrNull()
|
||||||
|
java.lang.Boolean::class.java -> if (source is Number) source != 0 else source.toString().toBoolean()
|
||||||
|
|
||||||
|
String::class.java -> source.toString()
|
||||||
|
|
||||||
|
else -> source
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T> instance(unsafe: Boolean = true) = instance(unsafe, T::class.java)
|
||||||
|
|
||||||
|
fun <T> instance(unsafe: Boolean = true, clazz: Class<T>): T = InstantAllocator[clazz, unsafe]
|
||||||
|
|
||||||
|
fun <T> unsafeInstance(clazz: Class<T>, unsafe: Boolean = true): T? = if (unsafe) {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
Unsafe.unsafe.allocateInstance(clazz) as T?
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
@ -24,7 +24,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ plugins {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":ts-core"))
|
implementation(project(":ts-core"))
|
||||||
|
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2")
|
||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.Suppress("UNCHECKED_CAST")
|
@kotlin.Suppress("UNCHECKED_CAST")
|
||||||
@ -23,7 +24,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package cn.tursom.core.datastruct
|
package cn.tursom.core.datastruct
|
||||||
|
|
||||||
import cn.tursom.core.cast
|
import cn.tursom.core.uncheckedCast
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
open class ArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> {
|
open class ArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> {
|
||||||
@ -149,7 +149,7 @@ open class ArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> {
|
|||||||
override fun setValue(newValue: V): V = value.also { value = newValue }
|
override fun setValue(newValue: V): V = value.also { value = newValue }
|
||||||
override fun compareTo(other: K): Int {
|
override fun compareTo(other: K): Int {
|
||||||
return if (key is Comparable<*>) {
|
return if (key is Comparable<*>) {
|
||||||
key.cast<Comparable<K>>().compareTo(other)
|
key.uncheckedCast<Comparable<K>>().compareTo(other)
|
||||||
} else {
|
} else {
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.utils
|
package cn.tursom.core.datastruct
|
||||||
|
|
||||||
interface AsyncIterator<T> {
|
interface AsyncIterator<T> {
|
||||||
/**
|
/**
|
@ -1,11 +1,11 @@
|
|||||||
package cn.tursom.core.datastruct
|
package cn.tursom.core.datastruct
|
||||||
|
|
||||||
import cn.tursom.core.cast
|
import cn.tursom.core.uncheckedCast
|
||||||
|
|
||||||
class DefaultValueMap<K, V>(
|
class DefaultValueMap<K, V>(
|
||||||
private val map: Map<K, V?>,
|
private val map: Map<K, V?>,
|
||||||
private val defaultValue: (K) -> V
|
private val defaultValue: (K) -> V,
|
||||||
) : Map<K, V> by map.cast() {
|
) : Map<K, V> by map.uncheckedCast() {
|
||||||
override val entries: Set<Map.Entry<K, V>> get() = Entry()
|
override val entries: Set<Map.Entry<K, V>> get() = Entry()
|
||||||
override val values: Collection<V> get() = Values()
|
override val values: Collection<V> get() = Values()
|
||||||
|
|
||||||
@ -21,8 +21,8 @@ class DefaultValueMap<K, V>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
inner class Entry(
|
inner class Entry(
|
||||||
private val entries: Set<Map.Entry<K, V?>> = map.entries
|
private val entries: Set<Map.Entry<K, V?>> = map.entries,
|
||||||
) : Set<Map.Entry<K, V>> by entries.cast() {
|
) : Set<Map.Entry<K, V>> by entries.uncheckedCast() {
|
||||||
override val size: Int get() = entries.count { it.value != null }
|
override val size: Int get() = entries.count { it.value != null }
|
||||||
override fun isEmpty(): Boolean = entries.firstOrNull { it.value != null } == null
|
override fun isEmpty(): Boolean = entries.firstOrNull { it.value != null } == null
|
||||||
override fun iterator(): Iterator<Map.Entry<K, V>> = EntryIterator()
|
override fun iterator(): Iterator<Map.Entry<K, V>> = EntryIterator()
|
||||||
@ -32,7 +32,7 @@ class DefaultValueMap<K, V>(
|
|||||||
private var next: Map.Entry<K, V>? = null
|
private var next: Map.Entry<K, V>? = null
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean {
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
next = iterator.next().cast()
|
next = iterator.next().uncheckedCast()
|
||||||
if (next?.value != null) {
|
if (next?.value != null) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -44,13 +44,13 @@ class DefaultValueMap<K, V>(
|
|||||||
next != null -> next
|
next != null -> next
|
||||||
hasNext() -> next
|
hasNext() -> next
|
||||||
else -> throw NoSuchElementException()
|
else -> throw NoSuchElementException()
|
||||||
}.cast()
|
}.uncheckedCast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class Values(
|
inner class Values(
|
||||||
private val values: Collection<V?> = map.values
|
private val values: Collection<V?> = map.values,
|
||||||
) : Collection<V> by values.cast() {
|
) : Collection<V> by values.uncheckedCast() {
|
||||||
override val size: Int get() = values.count { it != null }
|
override val size: Int get() = values.count { it != null }
|
||||||
override fun isEmpty(): Boolean = values.first { it != null } == null
|
override fun isEmpty(): Boolean = values.first { it != null } == null
|
||||||
override fun iterator(): Iterator<V> = ValuesIterator()
|
override fun iterator(): Iterator<V> = ValuesIterator()
|
||||||
@ -61,7 +61,7 @@ class DefaultValueMap<K, V>(
|
|||||||
|
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean {
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
next = iterator.next().cast()
|
next = iterator.next().uncheckedCast()
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ class DefaultValueMap<K, V>(
|
|||||||
next != null -> next
|
next != null -> next
|
||||||
hasNext() -> next
|
hasNext() -> next
|
||||||
else -> throw NoSuchElementException()
|
else -> throw NoSuchElementException()
|
||||||
}.cast()
|
}.uncheckedCast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package cn.tursom.core.datastruct
|
package cn.tursom.core.datastruct
|
||||||
|
|
||||||
import cn.tursom.core.cast
|
import cn.tursom.core.uncheckedCast
|
||||||
|
|
||||||
class DefaultValueMutableMap<K, V>(
|
class DefaultValueMutableMap<K, V>(
|
||||||
private val map: MutableMap<K, V?>,
|
private val map: MutableMap<K, V?>,
|
||||||
private val defaultValue: (K) -> V
|
private val defaultValue: (K) -> V,
|
||||||
) : MutableMap<K, V> by map.cast() {
|
) : MutableMap<K, V> by map.uncheckedCast() {
|
||||||
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> get() = Entry()
|
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> get() = Entry()
|
||||||
override val values: MutableCollection<V> get() = Values()
|
override val values: MutableCollection<V> get() = Values()
|
||||||
|
|
||||||
@ -19,19 +19,19 @@ class DefaultValueMutableMap<K, V>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
inner class Entry(
|
inner class Entry(
|
||||||
private val entries: MutableSet<MutableMap.MutableEntry<K, V?>> = map.entries
|
private val entries: MutableSet<MutableMap.MutableEntry<K, V?>> = map.entries,
|
||||||
) : MutableSet<MutableMap.MutableEntry<K, V>> by entries.cast() {
|
) : MutableSet<MutableMap.MutableEntry<K, V>> by entries.uncheckedCast() {
|
||||||
override val size: Int get() = entries.count { it.value != null }
|
override val size: Int get() = entries.count { it.value != null }
|
||||||
override fun isEmpty(): Boolean = entries.firstOrNull { it.value != null } == null
|
override fun isEmpty(): Boolean = entries.firstOrNull { it.value != null } == null
|
||||||
override fun iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> = EntryIterator()
|
override fun iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> = EntryIterator()
|
||||||
|
|
||||||
inner class EntryIterator(
|
inner class EntryIterator(
|
||||||
private val iterator: MutableIterator<MutableMap.MutableEntry<K, V?>> = entries.iterator()
|
private val iterator: MutableIterator<MutableMap.MutableEntry<K, V?>> = entries.iterator(),
|
||||||
) : MutableIterator<MutableMap.MutableEntry<K, V>> by iterator.cast() {
|
) : MutableIterator<MutableMap.MutableEntry<K, V>> by iterator.uncheckedCast() {
|
||||||
private var next: Map.Entry<K, V>? = null
|
private var next: Map.Entry<K, V>? = null
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean {
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
next = iterator.next().cast()
|
next = iterator.next().uncheckedCast()
|
||||||
if (next?.value != null) {
|
if (next?.value != null) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -43,25 +43,25 @@ class DefaultValueMutableMap<K, V>(
|
|||||||
next != null -> next
|
next != null -> next
|
||||||
hasNext() -> next
|
hasNext() -> next
|
||||||
else -> throw NoSuchElementException()
|
else -> throw NoSuchElementException()
|
||||||
}.cast()
|
}.uncheckedCast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class Values(
|
inner class Values(
|
||||||
private val values: MutableCollection<V?> = map.values
|
private val values: MutableCollection<V?> = map.values,
|
||||||
) : MutableCollection<V> by values.cast() {
|
) : MutableCollection<V> by values.uncheckedCast() {
|
||||||
override val size: Int get() = values.count { it != null }
|
override val size: Int get() = values.count { it != null }
|
||||||
override fun isEmpty(): Boolean = values.first { it != null } == null
|
override fun isEmpty(): Boolean = values.first { it != null } == null
|
||||||
override fun iterator(): MutableIterator<V> = ValuesIterator()
|
override fun iterator(): MutableIterator<V> = ValuesIterator()
|
||||||
|
|
||||||
inner class ValuesIterator(
|
inner class ValuesIterator(
|
||||||
private val iterator: MutableIterator<V?> = values.iterator()
|
private val iterator: MutableIterator<V?> = values.iterator(),
|
||||||
) : MutableIterator<V> by iterator.cast() {
|
) : MutableIterator<V> by iterator.uncheckedCast() {
|
||||||
private var next: V? = null
|
private var next: V? = null
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean {
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
next = iterator.next().cast()
|
next = iterator.next().uncheckedCast()
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ class DefaultValueMutableMap<K, V>(
|
|||||||
next != null -> next
|
next != null -> next
|
||||||
hasNext() -> next
|
hasNext() -> next
|
||||||
else -> throw NoSuchElementException()
|
else -> throw NoSuchElementException()
|
||||||
}.cast()
|
}.uncheckedCast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package cn.tursom.core.datastruct
|
package cn.tursom.core.datastruct
|
||||||
|
|
||||||
import cn.tursom.core.cast
|
import cn.tursom.core.uncheckedCast
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KProperty1
|
import kotlin.reflect.KProperty1
|
||||||
import kotlin.reflect.full.memberProperties
|
import kotlin.reflect.full.memberProperties
|
||||||
@ -23,7 +23,7 @@ class KPropertyValueMap(val target: Any) : Map<String, Any?> {
|
|||||||
operator fun get(clazz: KClass<*>): SoftArrayMap<String, KProperty1<Any, *>> {
|
operator fun get(clazz: KClass<*>): SoftArrayMap<String, KProperty1<Any, *>> {
|
||||||
var map = propertiesMapCache[clazz]
|
var map = propertiesMapCache[clazz]
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
map = clazz.memberProperties.cast<Collection<KProperty1<Any, *>>>().let { properties ->
|
map = clazz.memberProperties.uncheckedCast<Collection<KProperty1<Any, *>>>().let { properties ->
|
||||||
val valueMap = SoftArrayMap<String, KProperty1<Any, *>>(properties.size)
|
val valueMap = SoftArrayMap<String, KProperty1<Any, *>>(properties.size)
|
||||||
properties.forEach {
|
properties.forEach {
|
||||||
it.isAccessible = true
|
it.isAccessible = true
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package cn.tursom.core.datastruct
|
package cn.tursom.core.datastruct
|
||||||
|
|
||||||
import cn.tursom.core.cast
|
import cn.tursom.core.uncheckedCast
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
open class ParallelArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> {
|
open class ParallelArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> {
|
||||||
@ -17,8 +17,8 @@ open class ParallelArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> {
|
|||||||
|
|
||||||
@Suppress("LeakingThis")
|
@Suppress("LeakingThis")
|
||||||
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> = EntrySet(this)
|
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> = EntrySet(this)
|
||||||
override val keys: MutableSet<K> get() = arrValue.asList().subList(0, end).toMutableSet().cast()
|
override val keys: MutableSet<K> get() = arrValue.asList().subList(0, end).toMutableSet().uncheckedCast()
|
||||||
override val values: MutableCollection<V> get() = arrValue.asList().cast<MutableList<V>>().subList(0, end)
|
override val values: MutableCollection<V> get() = arrValue.asList().uncheckedCast<MutableList<V>>().subList(0, end)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param key 查找的键
|
* @param key 查找的键
|
||||||
@ -59,7 +59,7 @@ open class ParallelArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> {
|
|||||||
fun setByIndex(index: Int, value: V): V? {
|
fun setByIndex(index: Int, value: V): V? {
|
||||||
val oldValue = arrValue[end]
|
val oldValue = arrValue[end]
|
||||||
arrValue[index] = value
|
arrValue[index] = value
|
||||||
return oldValue.cast()
|
return oldValue.uncheckedCast()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun delete(key: K): V? {
|
override fun delete(key: K): V? {
|
||||||
@ -72,7 +72,7 @@ open class ParallelArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> {
|
|||||||
System.arraycopy(arr, index + 1, arr, index, end - index - 1)
|
System.arraycopy(arr, index + 1, arr, index, end - index - 1)
|
||||||
System.arraycopy(arrValue, index + 1, arrValue, index, end - index - 1)
|
System.arraycopy(arrValue, index + 1, arrValue, index, end - index - 1)
|
||||||
end--
|
end--
|
||||||
return oldValue.cast()
|
return oldValue.uncheckedCast()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clear() {
|
override fun clear() {
|
||||||
@ -83,7 +83,7 @@ open class ParallelArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> {
|
|||||||
return if (end <= 0) {
|
return if (end <= 0) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
arrValue[0].cast()
|
arrValue[0].uncheckedCast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ open class ParallelArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> {
|
|||||||
return if (index < 0 || index >= end) {
|
return if (index < 0 || index >= end) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
arr[index].cast()
|
arr[index].uncheckedCast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ open class ParallelArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> {
|
|||||||
return if (index < 0 || index >= end) {
|
return if (index < 0 || index >= end) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
arrValue[index].cast()
|
arrValue[index].uncheckedCast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,10 +194,10 @@ open class ParallelArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> {
|
|||||||
val map: ParallelArrayMap<K, V>,
|
val map: ParallelArrayMap<K, V>,
|
||||||
val index: Int
|
val index: Int
|
||||||
) : MutableMap.MutableEntry<K, V> {
|
) : MutableMap.MutableEntry<K, V> {
|
||||||
override val key: K get() = map.getKeyByIndex(index).cast()
|
override val key: K get() = map.getKeyByIndex(index).uncheckedCast()
|
||||||
override val value: V get() = map.getByIndex(index).cast()
|
override val value: V get() = map.getByIndex(index).uncheckedCast()
|
||||||
override fun setValue(newValue: V): V {
|
override fun setValue(newValue: V): V {
|
||||||
return map.setByIndex(index, newValue).cast()
|
return map.setByIndex(index, newValue).uncheckedCast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当从上一级 MutableDelegatedField 获得到空值时
|
||||||
|
* 自动调用updateValue方法更新值
|
||||||
|
*/
|
||||||
|
class AutoUpdatableMutableDelegatedField<in T, V : Any>(
|
||||||
|
override val delegatedField: MutableDelegatedField<T, V?>,
|
||||||
|
val updateValue: T.(property: KProperty<*>) -> V,
|
||||||
|
) : MutableDelegatedField<T, V> by delegatedField.uncheckedCast(),
|
||||||
|
DecoratorMutableDelegatedField<T, V?> {
|
||||||
|
override fun getValue(thisRef: T, property: KProperty<*>): V {
|
||||||
|
var value = delegatedField.getValue(thisRef, property)
|
||||||
|
if (value == null) {
|
||||||
|
value = thisRef.updateValue(property)
|
||||||
|
delegatedField.setValue(thisRef, property, value)
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T, V : Any> MutableDelegatedField<T, V?>.autoUpdate(
|
||||||
|
updateValue: T.(property: KProperty<*>) -> V,
|
||||||
|
): MutableDelegatedField<T, V> {
|
||||||
|
return AutoUpdatableMutableDelegatedField(this, updateValue)
|
||||||
|
}
|
@ -1,9 +1,12 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
interface DecoratorDelegateProvider<in T, out V> :
|
interface DecoratorDelegateProvider<in T, out V> :
|
||||||
DelegateProvider<T, DelegatedField<T, V>>,
|
DelegateProvider<T, DelegatedField<T, V>>,
|
||||||
DecoratorDelegatedField<T, V> {
|
DecoratorDelegatedField<T, V> {
|
||||||
override operator fun provideDelegate(thisRef: T, prop: KProperty<*>): DelegatedField<T, V> = delegatedField
|
override operator fun provideDelegate(
|
||||||
|
thisRef: T,
|
||||||
|
prop: KProperty<*>,
|
||||||
|
): DelegatedField<T, V> = delegatedField
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
interface DecoratorDelegatedField<in T, out V> {
|
interface DecoratorDelegatedField<in T, out V> {
|
||||||
val delegatedField: DelegatedField<T, V>
|
val delegatedField: DelegatedField<T, V>
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
@ -7,5 +7,5 @@ interface DecoratorMutableDelegateProvider<in T, V> :
|
|||||||
//DecoratorProvideDelegate<T, V>,
|
//DecoratorProvideDelegate<T, V>,
|
||||||
DecoratorMutableDelegatedField<T, V> {
|
DecoratorMutableDelegatedField<T, V> {
|
||||||
override operator fun provideDelegate(thisRef: T, prop: KProperty<*>): MutableDelegatedField<T, V> =
|
override operator fun provideDelegate(thisRef: T, prop: KProperty<*>): MutableDelegatedField<T, V> =
|
||||||
mutableDelegatedField
|
delegatedField
|
||||||
}
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
|
interface DecoratorMutableDelegatedField<in T, V> : DecoratorDelegatedField<T, V> {
|
||||||
|
override val delegatedField: MutableDelegatedField<T, V>
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
@ -0,0 +1,8 @@
|
|||||||
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
|
import kotlin.reflect.KProperty0
|
||||||
|
|
||||||
|
interface DelegatedFieldAttachmentKey<V> {
|
||||||
|
operator fun get(delegatedField: DelegatedField<*, *>) = delegatedField[this]
|
||||||
|
operator fun get(property0: KProperty0<*>) = property0.getDelegatedAttachmentValue(this)
|
||||||
|
}
|
@ -1,20 +1,20 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import java.util.concurrent.Executor
|
import java.util.concurrent.Executor
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
class ExecutorMutableDelegatedField<in T, V>(
|
class ExecutorMutableDelegatedField<in T, V>(
|
||||||
override val mutableDelegatedField: MutableDelegatedField<T, V>,
|
override val delegatedField: MutableDelegatedField<T, V>,
|
||||||
private val executor: Executor,
|
private val executor: Executor,
|
||||||
) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> {
|
) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> {
|
||||||
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {
|
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {
|
||||||
executor.execute {
|
executor.execute {
|
||||||
mutableDelegatedField.valueOnSet(thisRef, property, value, oldValue)
|
delegatedField.valueOnSet(thisRef, property, value, oldValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
|
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
|
||||||
valueOnSet(thisRef, property, value, getValue())
|
valueOnSet(thisRef, property, value, getValue())
|
||||||
mutableDelegatedField.setValue(value)
|
delegatedField.setValue(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
class ExpirableMutableDelegatedField<in T, V : Any>(
|
||||||
|
override val delegatedField: MutableDelegatedField<T, V>,
|
||||||
|
val expireMS: Long,
|
||||||
|
) : MutableDelegatedField<T, V?> by delegatedField.uncheckedCast(),
|
||||||
|
DecoratorMutableDelegatedField<T, V> {
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
private var setTime: Long = 0L
|
||||||
|
|
||||||
|
override fun getValue(thisRef: T, property: KProperty<*>): V? {
|
||||||
|
return if (System.currentTimeMillis() - setTime < expireMS) {
|
||||||
|
delegatedField.uncheckedCast<MutableDelegatedField<T, V?>>().getValue(thisRef, property)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setValue(thisRef: T, property: KProperty<*>, value: V?) {
|
||||||
|
if (value != null) {
|
||||||
|
delegatedField.setValue(value)
|
||||||
|
setTime = System.currentTimeMillis()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T, V : Any> MutableDelegatedField<T, V>.expirable(
|
||||||
|
expireTime: Long,
|
||||||
|
timeUnit: TimeUnit = TimeUnit.MILLISECONDS,
|
||||||
|
): MutableDelegatedField<T, V?> {
|
||||||
|
return ExpirableMutableDelegatedField(this, timeUnit.toMillis(expireTime))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("expirableTV?")
|
||||||
|
fun <T, V : Any> MutableDelegatedField<T, V?>.expirable(
|
||||||
|
expireTime: Long,
|
||||||
|
timeUnit: TimeUnit = TimeUnit.MILLISECONDS,
|
||||||
|
): MutableDelegatedField<T, V?> {
|
||||||
|
return ExpirableMutableDelegatedField(uncheckedCast(), timeUnit.toMillis(expireTime))
|
||||||
|
}
|
||||||
|
|
@ -1,18 +1,18 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import cn.tursom.core.cast
|
import cn.tursom.core.uncheckedCast
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
class FilterDelegatedField<in T, V>(
|
class FilterDelegatedField<in T, V>(
|
||||||
override val mutableDelegatedField: MutableDelegatedField<T, V>,
|
override val delegatedField: MutableDelegatedField<T, V>,
|
||||||
private val filter: T.(old: V, new: V) -> Boolean,
|
private val filter: T.(old: V, new: V) -> Boolean,
|
||||||
) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> {
|
) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> {
|
||||||
companion object Key : DelegatedFieldAttachmentKey<Boolean>
|
companion object Key : DelegatedFieldAttachmentKey<Boolean>
|
||||||
|
|
||||||
private var filterResult = false
|
private var filterResult = false
|
||||||
|
|
||||||
override fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? {
|
override fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? {
|
||||||
return if (key == Key) filterResult.cast() else super.get(key)
|
return if (key == Key) filterResult.uncheckedCast() else super.get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
|
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
|
||||||
@ -20,7 +20,7 @@ class FilterDelegatedField<in T, V>(
|
|||||||
if (!filterResult) {
|
if (!filterResult) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mutableDelegatedField.setValue(thisRef, property, value)
|
delegatedField.setValue(thisRef, property, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {
|
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {
|
||||||
@ -28,6 +28,6 @@ class FilterDelegatedField<in T, V>(
|
|||||||
if (!filterResult) {
|
if (!filterResult) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mutableDelegatedField.valueOnSet(thisRef, property, value, oldValue)
|
delegatedField.valueOnSet(thisRef, property, value, oldValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
@ -0,0 +1,10 @@
|
|||||||
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
class GetterMutableDelegatedField<in T, V>(
|
||||||
|
override val delegatedField: MutableDelegatedField<T, V>,
|
||||||
|
private val getter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V,
|
||||||
|
) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> {
|
||||||
|
override fun getValue(thisRef: T, property: KProperty<*>): V = delegatedField.getter(thisRef, property)
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import kotlin.reflect.KProperty0
|
import kotlin.reflect.KProperty0
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import kotlin.reflect.KMutableProperty0
|
import kotlin.reflect.KMutableProperty0
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import java.util.concurrent.locks.Lock
|
import java.util.concurrent.locks.Lock
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
@ -6,23 +6,23 @@ import kotlin.concurrent.withLock
|
|||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
class LockMutableDelegatedField<in T, V>(
|
class LockMutableDelegatedField<in T, V>(
|
||||||
override val mutableDelegatedField: MutableDelegatedField<T, V>,
|
override val delegatedField: MutableDelegatedField<T, V>,
|
||||||
private val lock: Lock = ReentrantLock(),
|
private val lock: Lock = ReentrantLock(),
|
||||||
) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> {
|
) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> {
|
||||||
constructor(
|
constructor(
|
||||||
initValue: V,
|
initValue: V,
|
||||||
lock: Lock = ReentrantLock(),
|
lock: Lock = ReentrantLock(),
|
||||||
) : this(MutableDelegatedFieldValue(initValue), lock)
|
) : this(MutableDelegatedFieldValue(initValue), lock)
|
||||||
|
|
||||||
override fun getValue(thisRef: T, property: KProperty<*>): V = lock.withLock {
|
override fun getValue(thisRef: T, property: KProperty<*>): V = lock.withLock {
|
||||||
mutableDelegatedField.getValue(thisRef, property)
|
delegatedField.getValue(thisRef, property)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setValue(thisRef: T, property: KProperty<*>, value: V) = lock.withLock {
|
override fun setValue(thisRef: T, property: KProperty<*>, value: V) = lock.withLock {
|
||||||
mutableDelegatedField.setValue(thisRef, property, value)
|
delegatedField.setValue(thisRef, property, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) = lock.withLock {
|
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) = lock.withLock {
|
||||||
mutableDelegatedField.valueOnSet(thisRef, property, value, oldValue)
|
delegatedField.valueOnSet(thisRef, property, value, oldValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
open class MutableDelegatedFieldValue<in T, V>(
|
open class MutableDelegatedFieldValue<in T, V>(
|
||||||
private var initValue: V
|
private var initValue: V,
|
||||||
) : MutableDelegatedField<T, V> {
|
) : MutableDelegatedField<T, V> {
|
||||||
override fun getValue(): V = initValue
|
override fun getValue(): V = initValue
|
||||||
override fun getValue(thisRef: T, property: KProperty<*>): V = initValue
|
override fun getValue(thisRef: T, property: KProperty<*>): V = initValue
|
@ -0,0 +1,27 @@
|
|||||||
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
class NotNullDelegatedField<in T, out V : Any>(
|
||||||
|
override val delegatedField: DelegatedField<T, V?>,
|
||||||
|
val ifNull: () -> Nothing = { throw NullPointerException() },
|
||||||
|
) : DelegatedField<T, V> by delegatedField.uncheckedCast(), DecoratorDelegatedField<T, V?> {
|
||||||
|
override fun getValue(): V {
|
||||||
|
val value = delegatedField.getValue()
|
||||||
|
if (value == null) {
|
||||||
|
ifNull()
|
||||||
|
} else {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getValue(thisRef: T, property: KProperty<*>): V {
|
||||||
|
val value = delegatedField.getValue(thisRef, property)
|
||||||
|
if (value == null) {
|
||||||
|
ifNull()
|
||||||
|
} else {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
class NotNullMutableDelegatedField<in T, V : Any>(
|
||||||
|
override val delegatedField: MutableDelegatedField<T, V?>,
|
||||||
|
val ifNull: () -> Nothing = { throw NullPointerException() },
|
||||||
|
) : MutableDelegatedField<T, V> by delegatedField.uncheckedCast(), DecoratorMutableDelegatedField<T, V?> {
|
||||||
|
override fun getValue(): V {
|
||||||
|
val value = delegatedField.getValue()
|
||||||
|
if (value == null) {
|
||||||
|
ifNull()
|
||||||
|
} else {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getValue(thisRef: T, property: KProperty<*>): V {
|
||||||
|
val value = delegatedField.getValue(thisRef, property)
|
||||||
|
if (value == null) {
|
||||||
|
ifNull()
|
||||||
|
} else {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import java.util.concurrent.locks.ReadWriteLock
|
import java.util.concurrent.locks.ReadWriteLock
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
@ -7,9 +7,9 @@ import kotlin.concurrent.write
|
|||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
class ReadWriteLockMutableDelegatedField<in T, V>(
|
class ReadWriteLockMutableDelegatedField<in T, V>(
|
||||||
override val mutableDelegatedField: MutableDelegatedField<T, V>,
|
override val delegatedField: MutableDelegatedField<T, V>,
|
||||||
private val readWriteLock: ReadWriteLock = ReentrantReadWriteLock(),
|
private val readWriteLock: ReadWriteLock = ReentrantReadWriteLock(),
|
||||||
) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> {
|
) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> {
|
||||||
constructor(
|
constructor(
|
||||||
initValue: V,
|
initValue: V,
|
||||||
readWriteLock: ReadWriteLock = ReentrantReadWriteLock(),
|
readWriteLock: ReadWriteLock = ReentrantReadWriteLock(),
|
||||||
@ -19,7 +19,7 @@ class ReadWriteLockMutableDelegatedField<in T, V>(
|
|||||||
val rl = readWriteLock.readLock()
|
val rl = readWriteLock.readLock()
|
||||||
rl.lock()
|
rl.lock()
|
||||||
try {
|
try {
|
||||||
return mutableDelegatedField.getValue(thisRef, property)
|
return delegatedField.getValue(thisRef, property)
|
||||||
} finally {
|
} finally {
|
||||||
rl.unlock()
|
rl.unlock()
|
||||||
}
|
}
|
||||||
@ -27,17 +27,17 @@ class ReadWriteLockMutableDelegatedField<in T, V>(
|
|||||||
|
|
||||||
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
|
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
|
||||||
if (readWriteLock is ReentrantReadWriteLock) readWriteLock.write {
|
if (readWriteLock is ReentrantReadWriteLock) readWriteLock.write {
|
||||||
mutableDelegatedField.setValue(thisRef, property, value)
|
delegatedField.setValue(thisRef, property, value)
|
||||||
} else readWriteLock.writeLock().withLock {
|
} else readWriteLock.writeLock().withLock {
|
||||||
mutableDelegatedField.setValue(thisRef, property, value)
|
delegatedField.setValue(thisRef, property, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {
|
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {
|
||||||
if (readWriteLock is ReentrantReadWriteLock) readWriteLock.write {
|
if (readWriteLock is ReentrantReadWriteLock) readWriteLock.write {
|
||||||
mutableDelegatedField.valueOnSet(thisRef, property, value, oldValue)
|
delegatedField.valueOnSet(thisRef, property, value, oldValue)
|
||||||
} else readWriteLock.writeLock().withLock {
|
} else readWriteLock.writeLock().withLock {
|
||||||
mutableDelegatedField.setValue(thisRef, property, value)
|
delegatedField.setValue(thisRef, property, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
|
import cn.tursom.core.getFieldForAll
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
|
||||||
|
class ReflectionDelegatedField<in T, V>(
|
||||||
|
private val receiver: T,
|
||||||
|
private val field: Field,
|
||||||
|
) : MutableDelegatedField<T, V> {
|
||||||
|
init {
|
||||||
|
field.isAccessible = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getValue(): V = field.get(receiver).uncheckedCast()
|
||||||
|
|
||||||
|
override fun setValue(value: V) {
|
||||||
|
field.set(receiver, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun <T : Any, V> T.superField(
|
||||||
|
fieldName: String,
|
||||||
|
): MutableDelegatedField<T, V> {
|
||||||
|
return ReflectionDelegatedField(this, this.javaClass.getFieldForAll(fieldName)!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T, V> T.field(
|
||||||
|
field: Field,
|
||||||
|
): MutableDelegatedField<T, V> {
|
||||||
|
return ReflectionDelegatedField(this, field)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T, V> T.field(
|
||||||
|
field: Field,
|
||||||
|
type: V,
|
||||||
|
): MutableDelegatedField<T, V> {
|
||||||
|
return ReflectionDelegatedField(this, field)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <T, V> T.field(
|
||||||
|
field: Field,
|
||||||
|
type: () -> V,
|
||||||
|
): MutableDelegatedField<T, V> {
|
||||||
|
return ReflectionDelegatedField(this, field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
class SetterDelegatedField<T, V>(
|
class SetterDelegatedField<T, V>(
|
||||||
override val delegatedField: DelegatedField<T, V>,
|
override val delegatedField: DelegatedField<T, V>,
|
@ -0,0 +1,12 @@
|
|||||||
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
class SetterMutableDelegatedField<T, V>(
|
||||||
|
override val delegatedField: MutableDelegatedField<T, V>,
|
||||||
|
val setter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>, value: V) -> Unit,
|
||||||
|
) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> {
|
||||||
|
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
|
||||||
|
delegatedField.setter(thisRef, property, value)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
|
import cn.tursom.core.SimpThreadLocal
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import kotlin.reflect.KProperty0
|
||||||
|
|
||||||
|
class SimpThreadLocalMutableDelegatedField<in T, V : Any>(
|
||||||
|
private val threadLocal: SimpThreadLocal<V>,
|
||||||
|
) : MutableDelegatedField<T, V> {
|
||||||
|
constructor(new: () -> V) : this(SimpThreadLocal(new = new))
|
||||||
|
|
||||||
|
|
||||||
|
override fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? {
|
||||||
|
return if (key == Companion || key == ThreadLocalMutableDelegatedField) {
|
||||||
|
threadLocal.uncheckedCast()
|
||||||
|
} else {
|
||||||
|
super.get(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setValue(value: V) = threadLocal.set(value)
|
||||||
|
override fun getValue(): V = threadLocal.get()
|
||||||
|
|
||||||
|
companion object : DelegatedFieldAttachmentKey<SimpThreadLocal<*>> {
|
||||||
|
fun <T : Any> getKey() = this.uncheckedCast<DelegatedFieldAttachmentKey<SimpThreadLocal<T>>>()
|
||||||
|
fun <T : Any> getKey(property: KProperty0<T>) =
|
||||||
|
this.uncheckedCast<DelegatedFieldAttachmentKey<SimpThreadLocal<T>>>()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import kotlin.reflect.KProperty0
|
||||||
|
|
||||||
|
class ThreadLocalMutableDelegatedField<in T, V>(
|
||||||
|
private val threadLocal: ThreadLocal<V?> = ThreadLocal(),
|
||||||
|
) : MutableDelegatedField<T, V?> {
|
||||||
|
|
||||||
|
override fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? {
|
||||||
|
return if (key == Companion) {
|
||||||
|
threadLocal.uncheckedCast()
|
||||||
|
} else {
|
||||||
|
super.get(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setValue(value: V?) = threadLocal.set(value)
|
||||||
|
override fun getValue(): V? = threadLocal.get()
|
||||||
|
|
||||||
|
companion object : DelegatedFieldAttachmentKey<ThreadLocal<*>> {
|
||||||
|
fun <T> getKey() = this.uncheckedCast<DelegatedFieldAttachmentKey<ThreadLocal<T>>>()
|
||||||
|
fun <T> getKey(property: KProperty0<T>) = this.uncheckedCast<DelegatedFieldAttachmentKey<ThreadLocal<T>>>()
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
@file:Suppress("unused")
|
@file:Suppress("unused")
|
||||||
|
|
||||||
package cn.tursom.delegation
|
package cn.tursom.core.delegation
|
||||||
|
|
||||||
import cn.tursom.core.SimpThreadLocal
|
import cn.tursom.core.SimpThreadLocal
|
||||||
import cn.tursom.core.cast
|
|
||||||
import cn.tursom.core.castOrNull
|
import cn.tursom.core.castOrNull
|
||||||
import cn.tursom.core.receiver
|
import cn.tursom.core.receiver
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
import java.util.concurrent.Executor
|
import java.util.concurrent.Executor
|
||||||
import java.util.concurrent.locks.Lock
|
import java.util.concurrent.locks.Lock
|
||||||
import java.util.concurrent.locks.ReadWriteLock
|
import java.util.concurrent.locks.ReadWriteLock
|
||||||
@ -19,26 +19,37 @@ import kotlin.reflect.full.memberProperties
|
|||||||
import kotlin.reflect.jvm.isAccessible
|
import kotlin.reflect.jvm.isAccessible
|
||||||
|
|
||||||
fun getDelegate(obj: Any?, field: String): DelegatedField<*, *>? {
|
fun getDelegate(obj: Any?, field: String): DelegatedField<*, *>? {
|
||||||
obj ?: return null
|
obj ?: return null
|
||||||
val kProperty1 = obj.javaClass.kotlin.memberProperties.firstOrNull { it.name == field }
|
val kProperty1 = obj.javaClass.kotlin.memberProperties.firstOrNull { it.name == field }
|
||||||
kProperty1?.isAccessible = true
|
kProperty1?.isAccessible = true
|
||||||
val delegate = kProperty1?.getDelegate(obj)
|
val delegate = kProperty1?.getDelegate(obj)
|
||||||
return delegate.castOrNull()
|
return delegate.castOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
val <V> KProperty0<V>.getOwnerDelegated: DelegatedField<*, V>?
|
val <V> KProperty0<V>.getOwnerDelegated: DelegatedField<*, V>?
|
||||||
get() = getDelegate(receiver, name).castOrNull()
|
get() = getDelegate(receiver, name).castOrNull()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取委托过后的值
|
||||||
|
* 不会触发getter方法
|
||||||
|
*/
|
||||||
val <V> KProperty0<V>.getDelegatedValue: V?
|
val <V> KProperty0<V>.getDelegatedValue: V?
|
||||||
get() {
|
get() {
|
||||||
val delegate = getDelegate() ?: getOwnerDelegated
|
val delegate = getDelegate() ?: getOwnerDelegated
|
||||||
return delegate?.castOrNull<DelegatedField<*, V>>()?.getValue()
|
return delegate?.castOrNull<DelegatedField<*, V>>()?.getValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <V> KProperty0<*>.getDelegatedAttachmentValue(key: DelegatedFieldAttachmentKey<V>): V? {
|
||||||
|
val delegated = getOwnerDelegated ?: return null
|
||||||
|
return delegated[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun <V> KProperty0<*>.get(key: DelegatedFieldAttachmentKey<V>): V? = getDelegatedAttachmentValue(key)
|
||||||
|
|
||||||
fun <V> KProperty0<V>.setDelegatedValue(value: V): Boolean {
|
fun <V> KProperty0<V>.setDelegatedValue(value: V): Boolean {
|
||||||
val delegate = getDelegate() ?: getOwnerDelegated
|
val delegate = getDelegate() ?: getOwnerDelegated
|
||||||
delegate.castOrNull<MutableDelegatedField<*, V>>()?.setValue(value) ?: return false
|
delegate.castOrNull<MutableDelegatedField<*, V>>()?.setValue(value) ?: return false
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,50 +57,74 @@ fun <V> KProperty0<V>.setDelegatedValue(value: V): Boolean {
|
|||||||
*/
|
*/
|
||||||
fun <T, V> T.delegated(value: V): MutableDelegatedField<T, V> = MutableDelegatedFieldValue(value)
|
fun <T, V> T.delegated(value: V): MutableDelegatedField<T, V> = MutableDelegatedFieldValue(value)
|
||||||
fun <T, V> T.delegated(@Suppress("UNUSED_PARAMETER") target: T, value: V): MutableDelegatedField<T, V> =
|
fun <T, V> T.delegated(@Suppress("UNUSED_PARAMETER") target: T, value: V): MutableDelegatedField<T, V> =
|
||||||
MutableDelegatedFieldValue(value)
|
MutableDelegatedFieldValue(value)
|
||||||
|
|
||||||
val <V> KProperty0<V>.delegated: DelegatedField<Any, V> get() = KPropertyDelegatedField(this)
|
val <V> KProperty0<V>.delegated: DelegatedField<Any, V> get() = KPropertyDelegatedField(this)
|
||||||
val <V> KMutableProperty0<V>.delegated: MutableDelegatedField<Any, V> get() = KPropertyMutableDelegatedField(this)
|
val <V> KMutableProperty0<V>.delegated: MutableDelegatedField<Any, V> get() = KPropertyMutableDelegatedField(this)
|
||||||
val <V : Any> KProperty0<V?>.delegatedNotNull get() = delegated.notNull
|
val <V : Any> KProperty0<V?>.delegatedNotNull get() = delegated.notNull
|
||||||
val <V : Any> KMutableProperty0<out V?>.delegatedNotNull: MutableDelegatedField<Any, V> get() = delegated.notNull
|
val <V : Any> KMutableProperty0<out V?>.delegatedNotNull: MutableDelegatedField<Any, V> get() = delegated.notNull
|
||||||
|
fun <V : Any> KProperty0<V?>.delegatedNotNull(ifNull: () -> Nothing) = delegated.notNull(ifNull)
|
||||||
|
fun <V : Any> KMutableProperty0<out V?>.delegatedNotNull(ifNull: () -> Nothing): MutableDelegatedField<Any, V> =
|
||||||
|
delegated.notNull(ifNull)
|
||||||
|
|
||||||
val <T, V : Any> DelegatedField<T, V?>.notNull: DelegatedField<T, V> get() = NotNullDelegatedField(this)
|
val <T, V : Any> DelegatedField<T, V?>.notNull: DelegatedField<T, V> get() = NotNullDelegatedField(this)
|
||||||
val <T, V : Any> MutableDelegatedField<T, out V?>.notNull: MutableDelegatedField<T, V>
|
val <T, V : Any> MutableDelegatedField<T, out V?>.notNull: MutableDelegatedField<T, V>
|
||||||
get() = NotNullMutableDelegatedField(cast())
|
get() = NotNullMutableDelegatedField(uncheckedCast())
|
||||||
|
|
||||||
|
fun <T, V : Any> DelegatedField<T, V?>.notNull(ifNull: () -> Nothing): DelegatedField<T, V> =
|
||||||
|
NotNullDelegatedField(this, ifNull)
|
||||||
|
|
||||||
|
fun <T, V : Any> MutableDelegatedField<T, out V?>.notNull(ifNull: () -> Nothing): MutableDelegatedField<T, V> =
|
||||||
|
NotNullMutableDelegatedField(uncheckedCast(), ifNull)
|
||||||
|
|
||||||
val <T, V> MutableDelegatedField<T, V>.locked: MutableDelegatedField<T, V> get() = LockMutableDelegatedField(this)
|
val <T, V> MutableDelegatedField<T, V>.locked: MutableDelegatedField<T, V> get() = LockMutableDelegatedField(this)
|
||||||
fun <T, V> MutableDelegatedField<T, V>.locked(lock: Lock = ReentrantLock()): MutableDelegatedField<T, V> =
|
fun <T, V> MutableDelegatedField<T, V>.locked(lock: Lock = ReentrantLock()): MutableDelegatedField<T, V> =
|
||||||
LockMutableDelegatedField(this, lock)
|
LockMutableDelegatedField(this, lock)
|
||||||
|
|
||||||
val <T, V> MutableDelegatedField<T, V>.readWriteLocked: MutableDelegatedField<T, V>
|
val <T, V> MutableDelegatedField<T, V>.readWriteLocked: MutableDelegatedField<T, V>
|
||||||
get() = ReadWriteLockMutableDelegatedField(this)
|
get() = ReadWriteLockMutableDelegatedField(this)
|
||||||
|
|
||||||
fun <T, V> MutableDelegatedField<T, V>.readWriteLocked(readWriteLock: ReadWriteLock = ReentrantReadWriteLock()): MutableDelegatedField<T, V> =
|
fun <T, V> MutableDelegatedField<T, V>.readWriteLocked(readWriteLock: ReadWriteLock = ReentrantReadWriteLock()): MutableDelegatedField<T, V> =
|
||||||
ReadWriteLockMutableDelegatedField(this, readWriteLock)
|
ReadWriteLockMutableDelegatedField(this, readWriteLock)
|
||||||
|
|
||||||
|
|
||||||
|
fun <T, V> ThreadLocal<V?>.delegated(): MutableDelegatedField<T, V?> = ThreadLocalMutableDelegatedField(this)
|
||||||
|
fun <T, V> T.delegated(
|
||||||
|
threadLocal: ThreadLocal<V?>,
|
||||||
|
): MutableDelegatedField<T, V?> = ThreadLocalMutableDelegatedField(threadLocal)
|
||||||
|
|
||||||
fun <T, V> T.threadLocalDelegated(): MutableDelegatedField<T, V?> = ThreadLocalMutableDelegatedField()
|
fun <T, V> T.threadLocalDelegated(): MutableDelegatedField<T, V?> = ThreadLocalMutableDelegatedField()
|
||||||
fun <T, V> T.threadLocalDelegated(type: Class<V>): MutableDelegatedField<T, V?> = ThreadLocalMutableDelegatedField()
|
fun <T, V> T.threadLocalDelegated(type: V?): MutableDelegatedField<T, V?> = ThreadLocalMutableDelegatedField()
|
||||||
fun <T, V : Any> T.threadLocalDelegated(type: KClass<V>): MutableDelegatedField<T, V?> =
|
fun <T, V> T.threadLocalDelegated(type: Class<out V?>): MutableDelegatedField<T, V?> =
|
||||||
ThreadLocalMutableDelegatedField()
|
ThreadLocalMutableDelegatedField()
|
||||||
|
|
||||||
fun <T, V> T.threadLocalDelegated(new: () -> V): MutableDelegatedField<T, V> = SimpThreadLocalMutableDelegatedField(new)
|
fun <T, V : Any> T.threadLocalDelegated(type: KClass<V>): MutableDelegatedField<T, V?> =
|
||||||
fun <T, V> T.threadLocalDelegated(simpThreadLocal: SimpThreadLocal<V>, new: () -> V): MutableDelegatedField<T, V> =
|
ThreadLocalMutableDelegatedField()
|
||||||
SimpThreadLocalMutableDelegatedField(simpThreadLocal, new)
|
|
||||||
|
fun <T, V : Any> SimpThreadLocal<V>.delegated(): MutableDelegatedField<T, V> =
|
||||||
|
SimpThreadLocalMutableDelegatedField(this)
|
||||||
|
|
||||||
|
fun <T, V : Any> T.threadLocalDelegated(
|
||||||
|
threadLocal: ThreadLocal<V?> = ThreadLocal(),
|
||||||
|
new: () -> V,
|
||||||
|
): MutableDelegatedField<T, V> = SimpThreadLocalMutableDelegatedField(SimpThreadLocal(threadLocal, new))
|
||||||
|
//fun <T, V> T.threadLocalDelegated(simpThreadLocal: SimpThreadLocal<V>): MutableDelegatedField<T, V> =
|
||||||
|
// SimpThreadLocalMutableDelegatedField(simpThreadLocal)
|
||||||
|
|
||||||
fun <T, V> MutableDelegatedField<T, V>.filter(filter: T.(old: V, new: V) -> Boolean): MutableDelegatedField<T, V> =
|
fun <T, V> MutableDelegatedField<T, V>.filter(filter: T.(old: V, new: V) -> Boolean): MutableDelegatedField<T, V> =
|
||||||
FilterDelegatedField(this, filter)
|
FilterDelegatedField(this, filter)
|
||||||
|
|
||||||
fun <T, V> DelegatedField<T, V>.setter(setter: DelegatedField<T, V>.(value: V) -> Unit): DelegatedField<T, V> =
|
fun <T, V> DelegatedField<T, V>.setter(setter: DelegatedField<T, V>.(value: V) -> Unit): DelegatedField<T, V> =
|
||||||
SetterDelegatedField(this, setter)
|
SetterDelegatedField(this, setter)
|
||||||
|
|
||||||
fun <T, V> MutableDelegatedField<T, V>.setter(setter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>, value: V) -> Unit): MutableDelegatedField<T, V> =
|
fun <T, V> MutableDelegatedField<T, V>.setter(setter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>, value: V) -> Unit): MutableDelegatedField<T, V> =
|
||||||
SetterMutableDelegatedField(this, setter)
|
SetterMutableDelegatedField(this, setter)
|
||||||
|
|
||||||
fun <T, V> DelegatedField<T, V>.getter(getter: DelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V): DelegatedField<T, V> =
|
fun <T, V> DelegatedField<T, V>.getter(getter: DelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V): DelegatedField<T, V> =
|
||||||
GetterDelegatedField(this, getter)
|
GetterDelegatedField(this, getter)
|
||||||
|
|
||||||
fun <T, V> MutableDelegatedField<T, V>.getter(getter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V): MutableDelegatedField<T, V> =
|
fun <T, V> MutableDelegatedField<T, V>.getter(getter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V): MutableDelegatedField<T, V> =
|
||||||
GetterMutableDelegatedField(this, getter)
|
GetterMutableDelegatedField(this, getter)
|
||||||
|
|
||||||
fun <T, V> MutableDelegatedField<T, V>.withExecutor(executor: Executor): MutableDelegatedField<T, V> =
|
fun <T, V> MutableDelegatedField<T, V>.withExecutor(executor: Executor): MutableDelegatedField<T, V> =
|
||||||
ExecutorMutableDelegatedField(this, executor)
|
ExecutorMutableDelegatedField(this, executor)
|
@ -1,6 +0,0 @@
|
|||||||
package cn.tursom.delegation
|
|
||||||
|
|
||||||
interface DecoratorMutableDelegatedField<in T, V> : DecoratorDelegatedField<T, V> {
|
|
||||||
val mutableDelegatedField: MutableDelegatedField<T, V>
|
|
||||||
override val delegatedField: DelegatedField<T, V> get() = mutableDelegatedField
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
package cn.tursom.delegation
|
|
||||||
|
|
||||||
interface DelegatedFieldAttachmentKey<V>
|
|
@ -1,10 +0,0 @@
|
|||||||
package cn.tursom.delegation
|
|
||||||
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
class GetterMutableDelegatedField<in T, V>(
|
|
||||||
override val mutableDelegatedField: MutableDelegatedField<T, V>,
|
|
||||||
private val getter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V,
|
|
||||||
) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> {
|
|
||||||
override fun getValue(thisRef: T, property: KProperty<*>): V = mutableDelegatedField.getter(thisRef, property)
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package cn.tursom.delegation
|
|
||||||
|
|
||||||
import cn.tursom.core.cast
|
|
||||||
|
|
||||||
class NotNullDelegatedField<in T, out V : Any>(
|
|
||||||
override val delegatedField: DelegatedField<T, V?>,
|
|
||||||
) : DelegatedField<T, V> by delegatedField.cast(), DecoratorDelegatedField<T, V?>
|
|
@ -1,8 +0,0 @@
|
|||||||
package cn.tursom.delegation
|
|
||||||
|
|
||||||
import cn.tursom.core.cast
|
|
||||||
|
|
||||||
class NotNullMutableDelegatedField<in T, V : Any>(
|
|
||||||
override val mutableDelegatedField: MutableDelegatedField<T, V?>,
|
|
||||||
) : MutableDelegatedField<T, V> by mutableDelegatedField.cast(), DecoratorMutableDelegatedField<T, V?>
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
|||||||
package cn.tursom.delegation
|
|
||||||
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
class SetterMutableDelegatedField<T, V>(
|
|
||||||
override val mutableDelegatedField: MutableDelegatedField<T, V>,
|
|
||||||
val setter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>, value: V) -> Unit,
|
|
||||||
) : MutableDelegatedField<T, V> by mutableDelegatedField, DecoratorMutableDelegatedField<T, V> {
|
|
||||||
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
|
|
||||||
mutableDelegatedField.setter(thisRef, property, value)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package cn.tursom.delegation
|
|
||||||
|
|
||||||
import cn.tursom.core.SimpThreadLocal
|
|
||||||
|
|
||||||
|
|
||||||
class SimpThreadLocalMutableDelegatedField<in T, V>(
|
|
||||||
private val threadLocal: SimpThreadLocal<V>,
|
|
||||||
val new: () -> V
|
|
||||||
) : MutableDelegatedField<T, V> {
|
|
||||||
constructor(new: () -> V) : this(SimpThreadLocal(new = new), new)
|
|
||||||
|
|
||||||
override fun setValue(value: V) = threadLocal.set(value)
|
|
||||||
override fun getValue(): V = threadLocal.get()
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package cn.tursom.delegation
|
|
||||||
|
|
||||||
class ThreadLocalMutableDelegatedField<in T, V>(
|
|
||||||
private val threadLocal: ThreadLocal<V?> = ThreadLocal()
|
|
||||||
) : MutableDelegatedField<T, V?> {
|
|
||||||
override fun setValue(value: V?) = threadLocal.set(value)
|
|
||||||
override fun getValue(): V? = threadLocal.get()
|
|
||||||
}
|
|
32
ts-core/ts-delegation/ts-observer/build.gradle.kts
Normal file
32
ts-core/ts-delegation/ts-observer/build.gradle.kts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
`maven-publish`
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":ts-core"))
|
||||||
|
implementation(project(":ts-core:ts-delegation"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Suppress("UNCHECKED_CAST")
|
||||||
|
(rootProject.ext["excludeTest"] as (Project, TaskContainer) -> Unit)(project, tasks)
|
||||||
|
|
||||||
|
tasks.register("install") {
|
||||||
|
finalizedBy(tasks["publishToMavenLocal"])
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
create<MavenPublication>("maven") {
|
||||||
|
groupId = project.group.toString()
|
||||||
|
artifactId = project.name
|
||||||
|
version = project.version.toString()
|
||||||
|
|
||||||
|
from(components["java"])
|
||||||
|
try {
|
||||||
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package cn.tursom.core.delegation.observer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标识一个属性可以被指定的 FieldChangeListener 监听
|
||||||
|
* 属性的实现者应该实现相应的逻辑
|
||||||
|
*/
|
||||||
|
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
|
||||||
|
annotation class Listenable
|
@ -0,0 +1,6 @@
|
|||||||
|
package cn.tursom.core.delegation.observer
|
||||||
|
|
||||||
|
interface ListenableListener<out T, V> : Listener<T, V> {
|
||||||
|
infix fun addListener(listener: T.(old: V, new: V) -> Unit): Listener<T, V>
|
||||||
|
override fun catch(handler: T.(old: V, new: V, e: Throwable) -> Unit): ListenableListener<T, V>
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package cn.tursom.core.delegation.observer
|
||||||
|
|
||||||
|
import cn.tursom.core.delegation.DecoratorMutableDelegatedField
|
||||||
|
import cn.tursom.core.delegation.DelegatedFieldAttachmentKey
|
||||||
|
import cn.tursom.core.delegation.MutableDelegatedField
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import java.util.concurrent.ConcurrentLinkedDeque
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
@Listenable
|
||||||
|
class ListenableMutableDelegatedField<T, V>(
|
||||||
|
override val delegatedField: MutableDelegatedField<T, V>,
|
||||||
|
) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> {
|
||||||
|
companion object : DelegatedFieldAttachmentKey<Boolean>
|
||||||
|
|
||||||
|
override fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? {
|
||||||
|
return if (key == Companion) true.uncheckedCast() else super.get(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val listenerList = ConcurrentLinkedDeque<T.(old: V, new: V) -> Unit>()
|
||||||
|
|
||||||
|
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
|
||||||
|
val oldValue = getValue()
|
||||||
|
listenerList.forEach {
|
||||||
|
thisRef.it(oldValue, value)
|
||||||
|
}
|
||||||
|
delegatedField.setValue(thisRef, property, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {
|
||||||
|
listenerList.forEach {
|
||||||
|
thisRef.it(oldValue, value)
|
||||||
|
}
|
||||||
|
delegatedField.valueOnSet(thisRef, property, value, oldValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addListener(listener: T.(old: V, new: V) -> Unit): Listener<T, V> {
|
||||||
|
var catch: (T.(old: V, new: V, e: Throwable) -> Unit)? = null
|
||||||
|
var finally: (T.(old: V, new: V) -> Unit)? = null
|
||||||
|
listenerList.add { old, new ->
|
||||||
|
try {
|
||||||
|
listener(old, new)
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
catch?.invoke(this, old, new, e)
|
||||||
|
} finally {
|
||||||
|
finally?.invoke(this, old, new)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return object : Listener<T, V> {
|
||||||
|
override fun cancel() = listenerList.remove(listener)
|
||||||
|
|
||||||
|
override fun catch(handler: T.(old: V, new: V, e: Throwable) -> Unit): Listener<T, V> {
|
||||||
|
catch = handler
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun finally(handler: T.(old: V, new: V) -> Unit): Listener<T, V> {
|
||||||
|
finally = handler
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package cn.tursom.core.delegation.observer
|
||||||
|
|
||||||
|
interface Listener<out T, V> {
|
||||||
|
fun cancel(): Boolean
|
||||||
|
infix fun catch(handler: T.(old: V, new: V, e: Throwable) -> Unit): Listener<T, V>
|
||||||
|
infix fun finally(handler: T.(old: V, new: V) -> Unit): Listener<T, V>
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package cn.tursom.core.delegation.observer
|
||||||
|
|
||||||
|
class UnmonitoredFieldException : Exception {
|
||||||
|
constructor() : super()
|
||||||
|
constructor(message: String?) : super(message)
|
||||||
|
constructor(message: String?, cause: Throwable?) : super(message, cause)
|
||||||
|
constructor(cause: Throwable?) : super(cause)
|
||||||
|
constructor(message: String?, cause: Throwable?, enableSuppression: Boolean, writableStackTrace: Boolean) : super(message, cause, enableSuppression, writableStackTrace)
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
@file:Suppress("unused")
|
||||||
|
|
||||||
|
package cn.tursom.core.delegation.observer
|
||||||
|
|
||||||
|
import cn.tursom.core.UncheckedCast
|
||||||
|
import cn.tursom.core.cast
|
||||||
|
import cn.tursom.core.delegation.*
|
||||||
|
import cn.tursom.core.receiver
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
|
import kotlin.reflect.KMutableProperty0
|
||||||
|
import kotlin.reflect.KProperty0
|
||||||
|
import kotlin.reflect.jvm.isAccessible
|
||||||
|
|
||||||
|
|
||||||
|
@Listenable
|
||||||
|
fun <V> KMutableProperty0<V>.listenable(): MutableDelegatedField<Any, V> {
|
||||||
|
isAccessible = true
|
||||||
|
val delegate = getDelegate()
|
||||||
|
return if (delegate is MutableDelegatedField<*, *> && delegate[ListenableMutableDelegatedField] == true) {
|
||||||
|
@OptIn(UncheckedCast::class)
|
||||||
|
delegate.cast()
|
||||||
|
} else {
|
||||||
|
@OptIn(UncheckedCast::class)
|
||||||
|
(ListenableMutableDelegatedField(KPropertyMutableDelegatedField(cast())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Listenable
|
||||||
|
fun <V> listenable(initValue: V): MutableDelegatedField<Any, V> = ListenableMutableDelegatedField(
|
||||||
|
MutableDelegatedFieldValue(initValue)
|
||||||
|
)
|
||||||
|
|
||||||
|
@Listenable
|
||||||
|
fun <T, V> MutableDelegatedField<T, V>.listenable(): MutableDelegatedField<T, V> =
|
||||||
|
ListenableMutableDelegatedField(this)
|
||||||
|
|
||||||
|
@JvmName("listenable1")
|
||||||
|
@Listenable
|
||||||
|
fun <T, V> listenable(delegatedField: MutableDelegatedField<T, V>): MutableDelegatedField<T, V> =
|
||||||
|
ListenableMutableDelegatedField(delegatedField)
|
||||||
|
|
||||||
|
|
||||||
|
infix operator fun <T, V> ListenableListener<T, V>.plus(listener: T.(old: V, new: V) -> Unit): Listener<T, V> =
|
||||||
|
addListener(listener)
|
||||||
|
|
||||||
|
@OptIn(Listenable::class)
|
||||||
|
fun <V> KProperty0<V>.getListenableMutableDelegatedField(): ListenableMutableDelegatedField<Any, V>? {
|
||||||
|
isAccessible = true
|
||||||
|
var delegate = getDelegate() ?: getDelegate(receiver, name)
|
||||||
|
if (delegate is DelegatedField<*, *>) {
|
||||||
|
while (true) {
|
||||||
|
if (delegate is ListenableMutableDelegatedField<*, *>) {
|
||||||
|
@OptIn(UncheckedCast::class)
|
||||||
|
return delegate.cast()
|
||||||
|
}
|
||||||
|
if (delegate is DecoratorDelegatedField<*, *>) {
|
||||||
|
delegate = delegate.delegatedField
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (delegate is KProperty0<*> && delegate != this) {
|
||||||
|
@OptIn(UncheckedCast::class)
|
||||||
|
return delegate.cast<KProperty0<V>>().getListenableMutableDelegatedField()
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <T, V> T.addChangeListener(
|
||||||
|
property: T.() -> KProperty0<V>,
|
||||||
|
): ListenableListener<T, V> {
|
||||||
|
val kProperty0 = property()
|
||||||
|
|
||||||
|
@OptIn(Listenable::class, UncheckedCast::class)
|
||||||
|
val delegatedField = kProperty0
|
||||||
|
.getListenableMutableDelegatedField()
|
||||||
|
.cast<ListenableMutableDelegatedField<T, V>?>()
|
||||||
|
?: throw UnmonitoredFieldException(kProperty0.toString())
|
||||||
|
return object : ListenableListener<T, V> {
|
||||||
|
private val selfList = ConcurrentLinkedQueue<Listener<T, V>>()
|
||||||
|
override fun addListener(listener: T.(old: V, new: V) -> Unit): Listener<T, V> {
|
||||||
|
@OptIn(Listenable::class)
|
||||||
|
val listener1 = delegatedField.addListener(listener)
|
||||||
|
selfList.add(listener1)
|
||||||
|
return listener1
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun catch(handler: T.(old: V, new: V, e: Throwable) -> Unit): ListenableListener<T, V> {
|
||||||
|
selfList.forEach {
|
||||||
|
it.catch(handler)
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cancel(): Boolean {
|
||||||
|
selfList.forEach {
|
||||||
|
it.cancel()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun finally(handler: T.(old: V, new: V) -> Unit): Listener<T, V> {
|
||||||
|
selfList.forEach {
|
||||||
|
it.finally(handler)
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,7 +26,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package cn.tursom.core.encrypt
|
package cn.tursom.core.encrypt
|
||||||
|
|
||||||
import cn.tursom.core.Unsafe
|
import cn.tursom.core.Unsafe
|
||||||
import cn.tursom.core.cast
|
import cn.tursom.core.uncheckedCast
|
||||||
import sun.security.ec.CurveDB
|
|
||||||
import java.security.KeyFactory
|
import java.security.KeyFactory
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.KeyPairGenerator
|
import java.security.KeyPairGenerator
|
||||||
@ -17,7 +16,7 @@ import java.security.spec.X509EncodedKeySpec
|
|||||||
@Suppress("unused", "MemberVisibilityCanBePrivate")
|
@Suppress("unused", "MemberVisibilityCanBePrivate")
|
||||||
class ECC(
|
class ECC(
|
||||||
publicKey: ECPublicKey,
|
publicKey: ECPublicKey,
|
||||||
privateKey: ECPrivateKey? = null
|
privateKey: ECPrivateKey? = null,
|
||||||
) : AbstractPublicKeyEncrypt("EC", publicKey, privateKey) {
|
) : AbstractPublicKeyEncrypt("EC", publicKey, privateKey) {
|
||||||
|
|
||||||
override val decryptMaxLen = Int.MAX_VALUE
|
override val decryptMaxLen = Int.MAX_VALUE
|
||||||
@ -41,7 +40,7 @@ class ECC(
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
keySize: Int = 256,
|
keySize: Int = 256,
|
||||||
standardCurveLine: String = StandardCurveLine.secp256k1.name.replace('_', ' ')
|
standardCurveLine: String = StandardCurveLine.secp256k1.name.replace('_', ' '),
|
||||||
) : this(
|
) : this(
|
||||||
keySize,
|
keySize,
|
||||||
ECGenParameterSpec(standardCurveLine)
|
ECGenParameterSpec(standardCurveLine)
|
||||||
@ -71,8 +70,12 @@ class ECC(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val standardCurveLineSet by lazy {
|
val standardCurveLineSet by lazy {
|
||||||
Unsafe {
|
try {
|
||||||
CurveDB::class.java["nameMap"].cast<Map<String, Any>>().keys
|
Unsafe {
|
||||||
|
Class.forName("sun.security.ec.CurveDB")["nameMap"].uncheckedCast<Map<String, Any>>().keys
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
emptySet()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,10 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":"))
|
implementation(project(":ts-core"))
|
||||||
implementation(group = "org.slf4j", name = "slf4j-api", version = "1.7.29")
|
api(group = "org.slf4j", name = "slf4j-api", version = "1.7.29")
|
||||||
implementation(group = "ch.qos.logback", name = "logback-core", version = "1.2.3")
|
api(group = "ch.qos.logback", name = "logback-core", version = "1.2.3")
|
||||||
implementation(group = "ch.qos.logback", name = "logback-classic", version = "1.2.3")
|
api(group = "ch.qos.logback", name = "logback-classic", version = "1.2.3")
|
||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.Suppress("UNCHECKED_CAST")
|
@kotlin.Suppress("UNCHECKED_CAST")
|
||||||
@ -26,7 +26,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package cn.tursom.log
|
|||||||
|
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
|
|
||||||
interface Slf4j : TrySlf4j {
|
interface Slf4j : TrySlf4j, Logger {
|
||||||
override val log: Logger
|
override val log: Logger
|
||||||
override val logger get() = log
|
override val logger get() = log
|
||||||
override val sfl4j get() = log
|
override val sfl4j get() = log
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
package cn.tursom.log.impl
|
package cn.tursom.log.impl
|
||||||
|
|
||||||
|
import cn.tursom.core.getCallerClassName
|
||||||
import cn.tursom.log.Slf4j
|
import cn.tursom.log.Slf4j
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import sun.reflect.Reflection
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.jvm.jvmName
|
import kotlin.reflect.jvm.jvmName
|
||||||
|
|
||||||
open class Slf4jImpl(
|
open class Slf4jImpl constructor(
|
||||||
|
@field:Transient
|
||||||
override val log: Logger,
|
override val log: Logger,
|
||||||
) : Slf4j, Logger by log {
|
) : Slf4j, Logger by log {
|
||||||
constructor(name: String? = null) : this(LoggerFactory.getLogger(name ?: loggerName))
|
constructor(name: String? = null) : this(LoggerFactory.getLogger(name ?: loggerName))
|
||||||
@ -27,20 +28,8 @@ open class Slf4jImpl(
|
|||||||
companion object {
|
companion object {
|
||||||
private val thisClassName = listOf(this::class.java.name.dropLast(10), this::class.java.name)
|
private val thisClassName = listOf(this::class.java.name.dropLast(10), this::class.java.name)
|
||||||
private val loggerName: String
|
private val loggerName: String
|
||||||
get() = getCallerClassName() ?: throw UnsupportedOperationException()
|
get() = getCallerClassName(thisClassName)?.substringBefore('$')
|
||||||
|
?: throw UnsupportedOperationException()
|
||||||
private fun getCallerClassName(): String? {
|
|
||||||
var clazz: Class<*>?
|
|
||||||
var callStackDepth = 1
|
|
||||||
do {
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
clazz = Reflection.getCallerClass(callStackDepth++)
|
|
||||||
if (clazz?.name !in thisClassName) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} while (clazz != null)
|
|
||||||
return clazz?.name
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun getLogger(name: String): Logger = LoggerFactory.getLogger(name)
|
inline fun getLogger(name: String): Logger = LoggerFactory.getLogger(name)
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,10 @@ tasks.register("install") {
|
|||||||
finalizedBy(tasks["publishToMavenLocal"])
|
finalizedBy(tasks["publishToMavenLocal"])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
artifacts {
|
||||||
|
archives(tasks["kotlinSourcesJar"])
|
||||||
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
create<MavenPublication>("maven") {
|
create<MavenPublication>("maven") {
|
||||||
@ -26,7 +30,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package cn.tursom.core.ws
|
||||||
|
|
||||||
|
import cn.tursom.core.buffer.ByteBuffer
|
||||||
|
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame
|
||||||
|
|
||||||
|
interface AutoCloseWebSocketHandler : WebSocketHandler {
|
||||||
|
override fun readMessage(client: WebSocketClient, msg: TextWebSocketFrame) {
|
||||||
|
super.readMessage(client, msg)
|
||||||
|
msg.release()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readMessage(client: WebSocketClient, msg: ByteBuffer) {
|
||||||
|
super.readMessage(client, msg)
|
||||||
|
msg.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readPing(client: WebSocketClient, msg: ByteBuffer) {
|
||||||
|
super.readPing(client, msg)
|
||||||
|
msg.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readPong(client: WebSocketClient, msg: ByteBuffer) {
|
||||||
|
super.readPong(client, msg)
|
||||||
|
msg.close()
|
||||||
|
}
|
||||||
|
}
|
@ -5,10 +5,7 @@ import cn.tursom.core.buffer.impl.NettyByteBuffer
|
|||||||
import io.netty.bootstrap.Bootstrap
|
import io.netty.bootstrap.Bootstrap
|
||||||
import io.netty.buffer.ByteBuf
|
import io.netty.buffer.ByteBuf
|
||||||
import io.netty.buffer.Unpooled
|
import io.netty.buffer.Unpooled
|
||||||
import io.netty.channel.Channel
|
import io.netty.channel.*
|
||||||
import io.netty.channel.ChannelFuture
|
|
||||||
import io.netty.channel.ChannelInitializer
|
|
||||||
import io.netty.channel.EventLoopGroup
|
|
||||||
import io.netty.channel.nio.NioEventLoopGroup
|
import io.netty.channel.nio.NioEventLoopGroup
|
||||||
import io.netty.channel.socket.SocketChannel
|
import io.netty.channel.socket.SocketChannel
|
||||||
import io.netty.channel.socket.nio.NioSocketChannel
|
import io.netty.channel.socket.nio.NioSocketChannel
|
||||||
@ -33,9 +30,12 @@ class WebSocketClient(
|
|||||||
val maxContextLength: Int = 4096,
|
val maxContextLength: Int = 4096,
|
||||||
private val headers: Map<String, String>? = null,
|
private val headers: Map<String, String>? = null,
|
||||||
private val handshakerUri: URI? = null,
|
private val handshakerUri: URI? = null,
|
||||||
|
val autoRelease: Boolean = true,
|
||||||
|
var initChannel: ((ch: SocketChannel) -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
private val uri: URI = URI.create(url)
|
private val uri: URI = URI.create(url)
|
||||||
internal var ch: Channel? = null
|
var ch: Channel? = null
|
||||||
|
internal set
|
||||||
|
|
||||||
fun open() {
|
fun open() {
|
||||||
close()
|
close()
|
||||||
@ -68,10 +68,12 @@ class WebSocketClient(
|
|||||||
headers?.forEach { (k, v) ->
|
headers?.forEach { (k, v) ->
|
||||||
httpHeaders[k] = v
|
httpHeaders[k] = v
|
||||||
}
|
}
|
||||||
val handshakerAdapter = WebSocketClientHandshakerAdapter(WebSocketClientHandshakerFactory.newHandshaker(
|
val handshakerAdapter = WebSocketClientHandshakerAdapter(
|
||||||
handshakerUri ?: uri, WebSocketVersion.V13, null, true, httpHeaders
|
WebSocketClientHandshakerFactory.newHandshaker(
|
||||||
), this, handler)
|
handshakerUri ?: uri, WebSocketVersion.V13, null, true, httpHeaders
|
||||||
val handler = WebSocketClientChannelHandler(this, handler)
|
), this, handler
|
||||||
|
)
|
||||||
|
val handler = WebSocketClientChannelHandler(this, handler, autoRelease)
|
||||||
val bootstrap = Bootstrap()
|
val bootstrap = Bootstrap()
|
||||||
bootstrap.group(group)
|
bootstrap.group(group)
|
||||||
.channel(NioSocketChannel::class.java)
|
.channel(NioSocketChannel::class.java)
|
||||||
@ -90,27 +92,25 @@ class WebSocketClient(
|
|||||||
addLast(WebSocketClientCompressionHandler.INSTANCE)
|
addLast(WebSocketClientCompressionHandler.INSTANCE)
|
||||||
}
|
}
|
||||||
addLast(handshakerAdapter)
|
addLast(handshakerAdapter)
|
||||||
//if (log) {
|
|
||||||
// addLast(LoggingHandler())
|
|
||||||
//}
|
|
||||||
addLast(handler)
|
addLast(handler)
|
||||||
if (autoWrap) {
|
if (autoWrap) {
|
||||||
addLast(WebSocketFrameWrapper)
|
addLast(WebSocketFrameWrapper)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
initChannel?.invoke(ch)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
bootstrap.connect(uri.host, port)
|
bootstrap.connect(uri.host, port)
|
||||||
//handler.handshakeFuture().sync()
|
//handler.handshakeFuture().sync()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun close(reasonText: String? = null) {
|
fun close(reasonText: String? = null): ChannelFuture? {
|
||||||
if (reasonText == null) {
|
if (reasonText == null) {
|
||||||
ch?.writeAndFlush(CloseWebSocketFrame())
|
ch?.writeAndFlush(CloseWebSocketFrame())
|
||||||
} else {
|
} else {
|
||||||
ch?.writeAndFlush(CloseWebSocketFrame(WebSocketCloseStatus.NORMAL_CLOSURE, reasonText))
|
ch?.writeAndFlush(CloseWebSocketFrame(WebSocketCloseStatus.NORMAL_CLOSURE, reasonText))
|
||||||
}
|
}?.addListener(ChannelFutureListener.CLOSE)
|
||||||
ch?.closeFuture()?.sync()
|
return ch?.closeFuture()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun write(text: String): ChannelFuture {
|
fun write(text: String): ChannelFuture {
|
||||||
@ -190,6 +190,6 @@ class WebSocketClient(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val group: EventLoopGroup = NioEventLoopGroup()
|
val group: EventLoopGroup = NioEventLoopGroup()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,7 +8,8 @@ import io.netty.handler.codec.http.websocketx.*
|
|||||||
class WebSocketClientChannelHandler(
|
class WebSocketClientChannelHandler(
|
||||||
val client: WebSocketClient,
|
val client: WebSocketClient,
|
||||||
val handler: WebSocketHandler,
|
val handler: WebSocketHandler,
|
||||||
) : SimpleChannelInboundHandler<WebSocketFrame>() {
|
private val autoRelease: Boolean = true,
|
||||||
|
) : SimpleChannelInboundHandler<WebSocketFrame>(autoRelease) {
|
||||||
|
|
||||||
override fun channelInactive(ctx: ChannelHandlerContext) {
|
override fun channelInactive(ctx: ChannelHandlerContext) {
|
||||||
handler.onClose(client)
|
handler.onClose(client)
|
||||||
@ -24,7 +25,11 @@ class WebSocketClientChannelHandler(
|
|||||||
is BinaryWebSocketFrame -> handler.readMessage(client, msg)
|
is BinaryWebSocketFrame -> handler.readMessage(client, msg)
|
||||||
is PingWebSocketFrame -> handler.readPing(client, msg)
|
is PingWebSocketFrame -> handler.readPing(client, msg)
|
||||||
is PongWebSocketFrame -> handler.readPong(client, msg)
|
is PongWebSocketFrame -> handler.readPong(client, msg)
|
||||||
is CloseWebSocketFrame -> ch.close()
|
is CloseWebSocketFrame -> {
|
||||||
|
if (!autoRelease) while (msg.refCnt() != 0) msg.release()
|
||||||
|
ch.close()
|
||||||
|
}
|
||||||
|
else -> if (!autoRelease) while (msg.refCnt() != 0) msg.release()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,8 +27,8 @@ class WebSocketClientHandshakerAdapter(
|
|||||||
if (!handshaker.isHandshakeComplete) {
|
if (!handshaker.isHandshakeComplete) {
|
||||||
handshaker.finishHandshake(ctx.channel(), msg)
|
handshaker.finishHandshake(ctx.channel(), msg)
|
||||||
handshakeFuture!!.setSuccess()
|
handshakeFuture!!.setSuccess()
|
||||||
msg.retain()
|
//msg.retain()
|
||||||
ctx.fireChannelRead(msg)
|
//ctx.fireChannelRead(msg)
|
||||||
handler.onOpen(client)
|
handler.onOpen(client)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
33
ts-core/ts-xml/build.gradle.kts
Normal file
33
ts-core/ts-xml/build.gradle.kts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
`maven-publish`
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(project(":"))
|
||||||
|
// 解析XML https://mvnrepository.com/artifact/org.dom4j/dom4j
|
||||||
|
api(group = "org.dom4j", name = "dom4j", version = "2.1.3")
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Suppress("UNCHECKED_CAST")
|
||||||
|
(rootProject.ext["excludeTest"] as (Project, TaskContainer) -> Unit)(project, tasks)
|
||||||
|
|
||||||
|
tasks.register("install") {
|
||||||
|
finalizedBy(tasks["publishToMavenLocal"])
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
create<MavenPublication>("maven") {
|
||||||
|
groupId = project.group.toString()
|
||||||
|
artifactId = project.name
|
||||||
|
version = project.version.toString()
|
||||||
|
|
||||||
|
from(components["java"])
|
||||||
|
try {
|
||||||
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.utils.xml
|
package cn.tursom.core.xml
|
||||||
|
|
||||||
import org.dom4j.Document
|
import org.dom4j.Document
|
||||||
import org.dom4j.Element
|
import org.dom4j.Element
|
@ -1,6 +1,6 @@
|
|||||||
package cn.tursom.utils.xml
|
package cn.tursom.core.xml
|
||||||
|
|
||||||
import cn.tursom.utils.xml.interfaces.*
|
import cn.tursom.core.xml.interfaces.*
|
||||||
|
|
||||||
object XmlDocument {
|
object XmlDocument {
|
||||||
fun tag(name: String? = null, action: (TextPotableXmlElement.() -> Unit)? = null): TextXmlElement {
|
fun tag(name: String? = null, action: (TextPotableXmlElement.() -> Unit)? = null): TextXmlElement {
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.utils.xml
|
package cn.tursom.core.xml
|
||||||
|
|
||||||
enum class ElementTarget {
|
enum class ElementTarget {
|
||||||
Attribute, ElementText, SubElement
|
Attribute, ElementText, SubElement
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.utils.xml.interfaces
|
package cn.tursom.core.xml.interfaces
|
||||||
|
|
||||||
interface ElementContainerPotableXmlElement : ElementContainerXmlElement, PotableXmlElement {
|
interface ElementContainerPotableXmlElement : ElementContainerXmlElement, PotableXmlElement {
|
||||||
val size: Int
|
val size: Int
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.utils.xml.interfaces
|
package cn.tursom.core.xml.interfaces
|
||||||
|
|
||||||
interface ElementContainerXmlElement : XmlElement {
|
interface ElementContainerXmlElement : XmlElement {
|
||||||
val subElement: List<XmlElement>
|
val subElement: List<XmlElement>
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.utils.xml.interfaces
|
package cn.tursom.core.xml.interfaces
|
||||||
|
|
||||||
interface PotableXmlElement : XmlElement {
|
interface PotableXmlElement : XmlElement {
|
||||||
override var name: String
|
override var name: String
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.utils.xml.interfaces
|
package cn.tursom.core.xml.interfaces
|
||||||
|
|
||||||
interface TextPotableXmlElement : TextXmlElement, PotableXmlElement {
|
interface TextPotableXmlElement : TextXmlElement, PotableXmlElement {
|
||||||
override var text: String
|
override var text: String
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.utils.xml.interfaces
|
package cn.tursom.core.xml.interfaces
|
||||||
|
|
||||||
interface TextXmlElement : XmlElement {
|
interface TextXmlElement : XmlElement {
|
||||||
val text: String
|
val text: String
|
@ -1,4 +1,4 @@
|
|||||||
package cn.tursom.utils.xml.interfaces
|
package cn.tursom.core.xml.interfaces
|
||||||
|
|
||||||
interface XmlElement {
|
interface XmlElement {
|
||||||
val name: String
|
val name: String
|
@ -25,7 +25,7 @@ publishing {
|
|||||||
|
|
||||||
from(components["java"])
|
from(components["java"])
|
||||||
try {
|
try {
|
||||||
artifact(tasks["sourcesJar"])
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
37
ts-database/build.gradle.kts
Normal file
37
ts-database/build.gradle.kts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
`maven-publish`
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(project(":"))
|
||||||
|
implementation(project(":ts-core"))
|
||||||
|
implementation(project(":ts-core:ts-clone"))
|
||||||
|
implementation(project(":ts-core:ts-log"))
|
||||||
|
api(group = "me.liuwj.ktorm", name = "ktorm-core", version = "3.1.0")
|
||||||
|
compileOnly(group = "com.baomidou", name = "mybatis-plus", version = "3.4.2")
|
||||||
|
compileOnly(group = "com.google.code.gson", name = "gson", version = "2.8.6")
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Suppress("UNCHECKED_CAST")
|
||||||
|
(rootProject.ext["excludeTest"] as (Project, TaskContainer) -> Unit)(project, tasks)
|
||||||
|
|
||||||
|
tasks.register("install") {
|
||||||
|
finalizedBy(tasks["publishToMavenLocal"])
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
create<MavenPublication>("maven") {
|
||||||
|
groupId = project.group.toString()
|
||||||
|
artifactId = project.name
|
||||||
|
version = project.version.toString()
|
||||||
|
|
||||||
|
from(components["java"])
|
||||||
|
try {
|
||||||
|
artifact(tasks["kotlinSourcesJar"])
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
82
ts-database/src/main/kotlin/cn/tursom/database/AutoTable.kt
Normal file
82
ts-database/src/main/kotlin/cn/tursom/database/AutoTable.kt
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package cn.tursom.database
|
||||||
|
|
||||||
|
import cn.tursom.core.clone.Property
|
||||||
|
import cn.tursom.core.clone.inject
|
||||||
|
import cn.tursom.core.clone.instance
|
||||||
|
import cn.tursom.core.uncheckedCast
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField
|
||||||
|
import me.liuwj.ktorm.dsl.QueryRowSet
|
||||||
|
import me.liuwj.ktorm.schema.BaseTable
|
||||||
|
import me.liuwj.ktorm.schema.Column
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
import kotlin.reflect.KProperty0
|
||||||
|
import kotlin.reflect.KProperty1
|
||||||
|
import kotlin.reflect.full.memberProperties
|
||||||
|
import kotlin.reflect.jvm.javaField
|
||||||
|
|
||||||
|
open class AutoTable<T : Any>(
|
||||||
|
entityClass: KClass<T>,
|
||||||
|
tableName: String = entityClass.tableName,
|
||||||
|
alias: String? = null,
|
||||||
|
catalog: String? = null,
|
||||||
|
schema: String? = null,
|
||||||
|
val unsafe: Boolean = true,
|
||||||
|
) : BaseTable<T>(tableName, alias, catalog, schema, entityClass) {
|
||||||
|
private val fieldMap: Map<String, KProperty<*>>
|
||||||
|
private val fieldColumns: MutableMap<KProperty<*>, Column<*>> = HashMap()
|
||||||
|
private val fieldNameColumnMap: MutableMap<String, Column<*>> = HashMap()
|
||||||
|
|
||||||
|
init {
|
||||||
|
fieldMap = entityClass.memberProperties.associateBy { it.simpTableField }
|
||||||
|
entityClass.memberProperties.forEach {
|
||||||
|
val field = it.javaField ?: return@forEach
|
||||||
|
val tableField: TableField? = field.getAnnotation(TableField::class.java)
|
||||||
|
if (tableField?.exist == false) return@forEach
|
||||||
|
//TypeAdapterFactory.register(this, it)
|
||||||
|
val column = TypeAdapterFactory.register(this, it) ?: return@forEach
|
||||||
|
fieldColumns[it] = column
|
||||||
|
fieldNameColumnMap[it.name] = column
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doCreateEntity(row: QueryRowSet, withReferences: Boolean): T {
|
||||||
|
val instance = instance(unsafe, entityClass!!.java)
|
||||||
|
columns.forEach {
|
||||||
|
val field = fieldMap[it.name] ?: return@forEach
|
||||||
|
row[it]?.inject(instance, field.uncheckedCast<Property<Any>>())
|
||||||
|
}
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun <R : Any> get(property: KProperty1<T, R?>): Column<R> = fieldColumns[property].uncheckedCast()
|
||||||
|
//operator fun <R : Any> get(property: KProperty1<T, R?>): Column<R> = this[property.simpTableField].cast()
|
||||||
|
|
||||||
|
fun <V : Any> field(): FieldProxy<T, V> = fieldProxyInstance.uncheckedCast()
|
||||||
|
fun <V : Any> field(property: KProperty0<*>): Column<V> = fieldNameColumnMap[property.name].uncheckedCast()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val fieldProxyInstance = FieldProxy<Any, Any>()
|
||||||
|
private val autoTableMap = ConcurrentHashMap<Class<*>, AutoTable<*>>()
|
||||||
|
operator fun <T : Any> get(clazz: KClass<T>): AutoTable<T> = get(clazz.java)
|
||||||
|
|
||||||
|
operator fun <T : Any> get(clazz: Class<T>): AutoTable<T> {
|
||||||
|
var autoTable = autoTableMap[clazz]
|
||||||
|
if (autoTable == null) {
|
||||||
|
synchronized(autoTableMap) {
|
||||||
|
autoTable = AutoTable(clazz.kotlin)
|
||||||
|
autoTableMap[clazz] = autoTable.uncheckedCast()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return autoTable.uncheckedCast()
|
||||||
|
}
|
||||||
|
|
||||||
|
class FieldProxy<T : Any, V : Any> {
|
||||||
|
operator fun getValue(
|
||||||
|
autoTable: AutoTable<T>,
|
||||||
|
property: KProperty<*>,
|
||||||
|
): Column<V> = autoTable.fieldNameColumnMap[property.name].uncheckedCast()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user