Merge remote-tracking branch 'origin/master' into master

This commit is contained in:
tursom 2021-06-15 00:01:53 +08:00
commit eeacd926b2
193 changed files with 8359 additions and 812 deletions

View File

@ -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) {
} }
} }

View File

@ -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")

View File

@ -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) {
} }
} }

View 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>()")
}
}
}

View File

@ -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

View File

@ -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
}
}

View File

@ -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()
} }
} }

View 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
}

View File

@ -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)

View File

@ -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
} }

View File

@ -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) {
}
}
}
} }

View File

@ -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

View File

@ -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

View File

@ -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) {
} }
} }

View File

@ -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) {
} }
} }

View File

@ -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 = "",
) )

View File

@ -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<*>,
) )

View File

@ -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,
) )

View File

@ -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,
) )

View File

@ -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)
}
}
}
} }

View File

@ -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
}

View File

@ -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) {
} }
} }

View File

@ -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) {
} }
} }

View File

@ -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) {
} }
} }

View File

@ -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
} }

View File

@ -1,4 +1,4 @@
package cn.tursom.utils package cn.tursom.core.datastruct
interface AsyncIterator<T> { interface AsyncIterator<T> {
/** /**

View File

@ -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()
} }
} }
} }

View File

@ -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()
} }
} }
} }

View File

@ -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

View File

@ -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()
} }
} }
} }

View File

@ -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) {
} }
} }

View File

@ -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)
}

View File

@ -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
} }

View File

@ -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>

View File

@ -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
} }

View File

@ -0,0 +1,5 @@
package cn.tursom.core.delegation
interface DecoratorMutableDelegatedField<in T, V> : DecoratorDelegatedField<T, V> {
override val delegatedField: MutableDelegatedField<T, V>
}

View File

@ -1,4 +1,4 @@
package cn.tursom.delegation package cn.tursom.core.delegation
import kotlin.reflect.KProperty import kotlin.reflect.KProperty

View File

@ -1,4 +1,4 @@
package cn.tursom.delegation package cn.tursom.core.delegation
import kotlin.reflect.KProperty import kotlin.reflect.KProperty

View File

@ -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)
}

View File

@ -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)
} }
} }

View File

@ -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))
}

View File

@ -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)
} }
} }

View File

@ -1,4 +1,4 @@
package cn.tursom.delegation package cn.tursom.core.delegation
import kotlin.reflect.KProperty import kotlin.reflect.KProperty

View File

@ -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)
}

View File

@ -1,4 +1,4 @@
package cn.tursom.delegation package cn.tursom.core.delegation
import kotlin.reflect.KProperty0 import kotlin.reflect.KProperty0

View File

@ -1,4 +1,4 @@
package cn.tursom.delegation package cn.tursom.core.delegation
import kotlin.reflect.KMutableProperty0 import kotlin.reflect.KMutableProperty0

View File

@ -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)
} }
} }

View File

@ -1,4 +1,4 @@
package cn.tursom.delegation package cn.tursom.core.delegation
import kotlin.reflect.KProperty import kotlin.reflect.KProperty

View File

@ -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

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -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)
} }
} }
} }

View File

@ -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)
}
}
}

View File

@ -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>,

View File

@ -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)
}
}

View File

@ -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>>>()
}
}

View File

@ -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>>>()
}
}

View File

@ -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)

View File

@ -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
}

View File

@ -1,3 +0,0 @@
package cn.tursom.delegation
interface DelegatedFieldAttachmentKey<V>

View File

@ -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)
}

View File

@ -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?>

View File

@ -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?>

View File

@ -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)
}
}

View File

@ -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()
}

View File

@ -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()
}

View 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) {
}
}
}
}

View File

@ -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

View File

@ -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>
}

View File

@ -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
}
}
}
}

View File

@ -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>
}

View File

@ -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)
}

View File

@ -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
}
}
}

View File

@ -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) {
} }
} }

View File

@ -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()
} }
} }
} }

View File

@ -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) {
} }
} }

View File

@ -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) {
} }
} }

View File

@ -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) {
} }
} }

View File

@ -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

View File

@ -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)

View File

@ -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) {
} }
} }

View File

@ -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) {
} }
} }

View File

@ -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) {
} }
} }

View File

@ -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()
}
}

View File

@ -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()
} }
} }

View File

@ -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()
} }
} }
} }

View File

@ -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 {

View 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) {
}
}
}
}

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) {
} }
} }

View 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) {
}
}
}
}

View 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