1
+ package taboolib.expansion
2
+
3
+ import taboolib.common.platform.function.info
4
+ import taboolib.common.platform.function.warning
5
+ import taboolib.common5.*
6
+ import java.sql.ResultSet
7
+ import java.util.UUID
8
+ import java.util.concurrent.ConcurrentHashMap
9
+ import kotlin.reflect.KParameter
10
+ import kotlin.reflect.full.*
11
+ import kotlin.reflect.jvm.javaType
12
+
13
+ /* *
14
+ * TabooLib
15
+ * taboolib.expansion.AnalyzedClass
16
+ *
17
+ * @author 坏黑
18
+ * @since 2023/3/29 11:28
19
+ */
20
+ @Suppress(" UNCHECKED_CAST" )
21
+ class AnalyzedClass private constructor(val clazz : Class <* >) {
22
+
23
+ /* * 主构造器 */
24
+ private val primaryConstructor = clazz.kotlin.primaryConstructor ? : error(" No primary constructor found for $clazz " )
25
+
26
+ /* * 成员列表 */
27
+ private val memberProperties = clazz.kotlin.memberProperties.associateBy { it.name }
28
+
29
+ /* * 成员列表 */
30
+ val members = primaryConstructor.valueParameters.map {
31
+ // 不知道为什么,isFinal 方法在这里会失效,全部都是 true
32
+ // 测试日志:
33
+ // name=username, p=val com.github.username.GameHistory.username: java.util.UUID, f=true
34
+ // name=game, p=val com.github.username.GameHistory.game: kotlin.String, f=true
35
+ // name=playTimes, p=var com.github.username.GameHistory.playTimes: kotlin.Int, f=true
36
+ // name=deepLevel, p=var com.github.username.GameHistory.deepLevel: kotlin.Int, f=true
37
+ // name=useTime, p=var com.github.username.GameHistory.useTime: kotlin.Long, f=true
38
+ AnalyzedClassMember (validation(it), memberProperties[it.name]?.toString()?.startsWith(" var" ) != true )
39
+ }
40
+
41
+ /* * 主成员 */
42
+ val primaryMember = members.firstOrNull { it.isPrimary }
43
+
44
+ /* * 主成员名称 */
45
+ val primaryMemberName = primaryMember?.name
46
+
47
+ /* * 反序列化所在伴生类实例 */
48
+ val wrapperObjectInstance = clazz.kotlin.companionObjectInstance
49
+
50
+ /* * 反序列化方法 */
51
+ val wrapperFunction = clazz.kotlin.companionObject?.functions?.firstOrNull {
52
+ it.valueParameters.size == 1 && BundleMap ::class .java.isAssignableFrom(it.valueParameters[0 ].type.javaType as Class <* >)
53
+ }
54
+
55
+ init {
56
+ val customs = members.filter { it.isCustomObject }
57
+ if (customs.isNotEmpty()) {
58
+ error(" The following members are not supported: $customs " )
59
+ }
60
+ if (members.count { it.isPrimary } > 1 ) {
61
+ error(" The primary member only supports one, but found ${members.count { it.isPrimary }} " )
62
+ }
63
+ }
64
+
65
+ /* * 获取主成员值 */
66
+ fun getPrimaryMemberValue (data : Any ): Any {
67
+ val property = memberProperties[primaryMember?.propertyName] ? : error(" Primary member \" $primaryMemberName \" not found in $clazz " )
68
+ return property.call(data)!!
69
+ }
70
+
71
+ /* * 获取成员值 */
72
+ fun getValue (data : Any , member : AnalyzedClassMember ): Any {
73
+ val property = memberProperties[member.propertyName] ? : error(" Member \" ${member.name} \" not found in $clazz " )
74
+ return property.call(data)!!
75
+ }
76
+
77
+ /* * 读取数据 */
78
+ fun read (result : ResultSet ): Map <String , Any ?> {
79
+ val map = hashMapOf<String , Any ?>()
80
+ members.forEach { member ->
81
+ val obj = result.getObject(member.name)
82
+ val wrap = when {
83
+ member.isBoolean -> obj.cbool
84
+ member.isByte -> obj.cbyte
85
+ member.isShort -> obj.cshort
86
+ member.isInt -> obj.cint
87
+ member.isLong -> obj.clong
88
+ member.isFloat -> obj.cfloat
89
+ member.isDouble -> obj.cdouble
90
+ member.isChar -> obj.cint.toChar()
91
+ member.isString -> obj.toString()
92
+ member.isUUID -> UUID .fromString(obj.toString())
93
+ member.isEnum -> member.returnType.enumConstants.first { it.toString() == obj.toString() }
94
+ else -> error(" Unsupported type ${member.returnType} for ${member.name} in $clazz " )
95
+ }
96
+ map[member.name] = wrap
97
+ }
98
+ return map
99
+ }
100
+
101
+ /* * 创建实例 */
102
+ fun <T > createInstance (map : Map <String , Any ?>): T {
103
+ return if (wrapperFunction != null ) {
104
+ wrapperFunction.call(wrapperObjectInstance, BundleMapImpl (map)) ? : error(" Failed to create instance for $clazz " )
105
+ } else {
106
+ val args = members.map { map[it.name] }
107
+ try {
108
+ primaryConstructor.call(* args.toTypedArray())
109
+ } catch (ex: Throwable ) {
110
+ error(" Failed to create instance for $clazz ($args ), map=$map " )
111
+ }
112
+ } as T
113
+ }
114
+
115
+ /* * 验证参数 */
116
+ fun validation (parameter : KParameter ): KParameter {
117
+ if (parameter.name == null ) {
118
+ error(" Parameter name is null for $parameter " )
119
+ }
120
+ if (parameter.isVararg) {
121
+ error(" Vararg parameters are not supported for $parameter " )
122
+ }
123
+ return parameter
124
+ }
125
+
126
+ companion object {
127
+
128
+ val cached = ConcurrentHashMap <Class <* >, AnalyzedClass > ()
129
+
130
+ fun of (clazz : Class <* >): AnalyzedClass {
131
+ return cached.computeIfAbsent(clazz) { AnalyzedClass (it) }
132
+ }
133
+ }
134
+ }
0 commit comments