Skip to content

Commit

Permalink
update COnfigManager2
Browse files Browse the repository at this point in the history
  • Loading branch information
Gk0Wk committed Aug 5, 2023
1 parent 03e4679 commit 2a57f72
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 55 deletions.
14 changes: 14 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ config.root {
val inventory = it["inventory"].asBase64Inventory()
val location = it["location"].asConfigurationSerializable<Location>()
}

// Class mapping mode
data class Config(
val a: Int,
val b: String,
)
val c1 = ConfigManager2.parse<Config>("""{"a":1,"b":"a"}""", ConfigManager2.ConfigFileType.Json) // to object
val c2 = ConfigManager2.parse<Config>(File("/root/example/config.yml")) // parse object from file
val c3 = configManager.parse<Config>("config.yml") // parse object from config
```

Write:
Expand All @@ -43,6 +52,11 @@ configManager["store.json"].save {
it.setBase64("example-inventory", Bukkit.getOfflinePlayers()[0].player!!.inventory)
it.remove("foo")
}

// Class mapping mode
ConfigManager2.stringify(Config(1, "a"), ConfigManager2.ConfigFileType.Json) // to string: {"a":1,"b":"a"}
ConfigManager2.save(Config(1, "a"), File("/root/example/config.yml")) // save object to file
configManager.save(Config(1, "a"), "config.yml") // save object to config
```

Multi-type support:
Expand Down
113 changes: 97 additions & 16 deletions src/main/kotlin/city/newnan/violet/config/ConfigManager2.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

package city.newnan.violet.config

import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
Expand Down Expand Up @@ -49,9 +50,9 @@ class Configure2(
/**
* 配置文件启用或关闭持久化保存,即不会因为长久未访问就从内存中卸载,适合经常访问的配置文件。
*/
fun setCache(enable: Boolean) {
if (path == null) return
if (enable == _enableCache) return
fun setCache(enable: Boolean): Configure2 {
if (path == null) return this
if (enable == _enableCache) return this
_enableCache = enable
val p = path!!.canonicalPath
if (enable) {
Expand All @@ -64,6 +65,7 @@ class Configure2(
manager.persistentConfigSet.remove(p)
save()
}
return this
}
/**
* 配置文件启用或关闭持久化保存,即不会因为长久未访问就从内存中卸载,适合经常访问的配置文件。
Expand All @@ -83,18 +85,20 @@ class Configure2(
*
* @param enable 是否启动持久化
*/
fun setPersistence(enable: Boolean) {
if (path == null) return
if (enable == _enablePersistence) return
fun setPersistence(enable: Boolean): Configure2 {
if (path == null) return this
if (enable == _enablePersistence) return this
_enablePersistence = enable
if (enable) manager.persistentConfigSet.add(path!!.canonicalPath)
return this
}
/**
* 将某个文件设置为持久化保存的,即不会因为长久未访问就从内存中卸载;或者取消。以缓存为前提。
*
* @param enable 是否启动持久化
*/
infix fun persistence(enable: Boolean) = setPersistence(enable)
fun persistence() = persistence(true)

/**
* 配置文件路径
Expand Down Expand Up @@ -284,16 +288,15 @@ class ConfigManager2
ConfigFileType.Hocon to { decorateMapper(ObjectMapper(HoconFactory())) }
)
private val Mappers = HashMap<ConfigFileType, ObjectMapper>()
private fun decorateMapper(mapper: ObjectMapper): ObjectMapper {
// 序列化时使用缩进
mapper.configure(SerializationFeature.INDENT_OUTPUT, true)
// 解析时忽略未知的属性
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
// 支持 Kotlin 类
// https://github.com/FasterXML/jackson-module-kotlin
mapper.registerKotlinModule()
return mapper
}
private fun decorateMapper(mapper: ObjectMapper): ObjectMapper = mapper
// 序列化时使用缩进
.enable(SerializationFeature.INDENT_OUTPUT)
// 解析时忽略未知的属性
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
// 支持 Kotlin 类
// https://github.com/FasterXML/jackson-module-kotlin
.registerKotlinModule()


/**
* 获取一个 mapper
Expand Down Expand Up @@ -322,6 +325,52 @@ class ConfigManager2
"conf", "hocon" -> ConfigFileType.Hocon
else -> throw UnknownConfigFileFormatException(path.path)
}

/**
* 使用指定类型解析配置文件
*
* @param T 指定类型
* @param path 配置文件路径
* @param type 配置文件类型,如果为null则自动检测
* @return [T] 实例
*/
@Throws(IOException::class, UnknownConfigFileFormatException::class)
inline fun <reified T> parse(path: File, type: ConfigFileType? = null): T {
// 读取配置文件
val typeReal = type ?: guessConfigType(path)
return mapper[typeReal].readValue(path, T::class.java)
}

/**
* 使用指定类型解析文本
*
* @param T 指定类型
* @param config 配置文本
* @param type 配置文件类型
* @return [T] 实例
*/
@Throws(JsonProcessingException::class, UnknownConfigFileFormatException::class)
inline fun <reified T> parse(config: String, type: ConfigFileType): T {
return mapper[type].readValue(config, T::class.java)
}

/**
* 序列化为文本
*
* @param T 指定类型
* @param type 配置文件类型
* @return [String] 文本
*/
@Throws(JsonProcessingException::class, UnknownConfigFileFormatException::class)
inline fun <reified T> stringify(obj: T, type: ConfigFileType): String {
return mapper[type].writeValueAsString(obj)
}

@Throws(IOException::class, UnknownConfigFileFormatException::class)
inline fun <reified T> save(obj: T, path: File, type: ConfigFileType? = null) {
val typeReal = type ?: guessConfigType(path)
mapper[typeReal].writeValue(path, obj)
}
}

/**
Expand Down Expand Up @@ -483,6 +532,7 @@ class ConfigManager2
/**
* 直接从文件获取某个配置文件(支持YAML,JSON,TOML,HOCON,XML,Properties和CSV),不使用缓存机制
* @param configFile 配置文件路径
* @param type 配置文件类型,如果为null则自动检测
* @return 配置实例
* @throws IOException 文件读写出错
* @throws UnknownConfigFileFormatException 未知的配置文件格式
Expand All @@ -497,6 +547,37 @@ class ConfigManager2
return Configure2(path, typeReal, mapper[typeReal].readTree(path) as ObjectNode, this)
}

/**
* 使用指定类型解析配置文件
*
* @param T 指定类型
* @param configFile 配置文件路径
* @param type 配置文件类型,如果为null则自动检测
* @return [T] 实例
*/
@Throws(IOException::class, UnknownConfigFileFormatException::class)
inline fun <reified T> parse(configFile: String, type: ConfigFileType? = null): T {
// 未缓存则加载
touch(configFile)
// 读取配置文件
return parse(File(plugin.dataFolder, configFile), type)
}

/**
* 序列化对象到指定的配置文件
*
* @param T 指定类型
* @param obj 对象实例
* @param configFile 配置文件路径
* @param type 配置文件类型,如果为null则自动检测
* @return [T] 实例
*/
@Throws(IOException::class, UnknownConfigFileFormatException::class)
inline fun <reified T> save(obj: T, configFile: String, type: ConfigFileType? = null) {
// 读取配置文件
save(obj, File(plugin.dataFolder, configFile), type)
}

/**
* 获取某个配置文件(支持YAML,JSON和HOCON),如果不存在就从指定的模板复制一份
* @param targetFile 要获取的配置文件路径
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ infix fun ObjectNode.get(key: String) = get(key) as ObjectNode

fun <T> JsonNode.asType(): T = ConfigManager2.mapper[ConfigManager2.ConfigFileType.Json]
.convertValue(this, object : com.fasterxml.jackson.core.type.TypeReference<T>() {})
fun JsonNode.asMap() = asType<LinkedHashMap<String, Any>>()
fun <K> JsonNode.asMap() = asType<LinkedHashMap<String, K>>()
fun Map<*, *>.toObjectNode(): ObjectNode = ConfigManager2.mapper[ConfigManager2.ConfigFileType.Json]
.valueToTree(this)
fun ObjectNode.put(key: String, value: Map<*, *>) {
replace(key, value.toObjectNode())
}
fun JsonNode.asList() = asType<ArrayList<Any>>()
fun <T> JsonNode.asList() = asType<ArrayList<T>>()
fun List<*>.toObjectNode(): ObjectNode = ConfigManager2.mapper[ConfigManager2.ConfigFileType.Json]
.valueToTree(this)
fun ObjectNode.put(key: String, value: List<*>) {
Expand All @@ -66,9 +66,9 @@ fun ObjectNode.put(key: String, value: ConfigurationSerializable): ObjectNode
= replace(key,
ConfigManager2.mapper[ConfigManager2.ConfigFileType.Json].valueToTree<ObjectNode>(value.serialize())) as ObjectNode
fun <T : ConfigurationSerializable> JsonNode.asConfigurationSerializable(): T?
= ConfigurationSerialization.deserializeObject(asMap()) as T?
= ConfigurationSerialization.deserializeObject(asMap<Any>()) as T?
fun JsonNode.asBase64Inventory(): Inventory {
val map = asMap()
val map = asMap<Any>()
return InventorySerialization.decodeInventory(map["data"] as String, map["title"] as String)
}
fun JsonNode.asBase64ItemStacks(): Array<ItemStack>
Expand Down
66 changes: 31 additions & 35 deletions src/test/kotlin/Main.kt
Original file line number Diff line number Diff line change
@@ -1,40 +1,36 @@
import city.newnan.violet.config.asConfigurationSerializable
import city.newnan.violet.config.asMap
import city.newnan.violet.config.put
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.node.ObjectNode
import com.fasterxml.jackson.dataformat.csv.CsvMapper
import com.fasterxml.jackson.dataformat.xml.XmlMapper
import me.lucko.helper.serialize.Position
import org.bukkit.Bukkit
import org.bukkit.Material
import org.bukkit.inventory.Inventory
import org.bukkit.inventory.ItemStack
import city.newnan.violet.config.ConfigManager2

data class Area(val a: String, val b: Int)

fun main() {
val mapper = ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT)
val mapper2 = CsvMapper().enable(SerializationFeature.INDENT_OUTPUT)
val m = mapper.readValue("""{
|"title": "title",
|"created": 0,
|"modified": 1,
|"xxx": [1,2,3,4,5]
|}""".trimMargin(), ObjectNode::class.java)
// val mapper2 = CsvMapper().enable(SerializationFeature.INDENT_OUTPUT)
// val m = mapper.readValue("""{
// |"title": "title",
// |"created": 0,
// |"modified": 1,
// |"xxx": [1,2,3,4,5]
// |}""".trimMargin(), ObjectNode::class.java)
//
// val x = hashMapOf(
// "title" to "title",
// "created" to 0,
// "modified" to 1,
// "xxx" to listOf(1,2,3,4,5),
// "c" to hashMapOf(
// "a" to 1,
// "b" to 2
// )
// )
// // println(mapper.writeValueAsString(x))
// println(mapper.valueToTree<ObjectNode>(x).toPrettyString())
//
// val k = m.asMap()
// println(k)

val x = hashMapOf(
"title" to "title",
"created" to 0,
"modified" to 1,
"xxx" to listOf(1,2,3,4,5),
"c" to hashMapOf(
"a" to 1,
"b" to 2
)
val a = hashMapOf(
"a" to Area("a", 1),
"b" to Area("b", 2)
)
// println(mapper.writeValueAsString(x))
println(mapper.valueToTree<ObjectNode>(x).toPrettyString())

val k = m.asMap()
println(k)
ConfigManager2.stringify(a, ConfigManager2.ConfigFileType.Json).also(::println)
ConfigManager2.parse<LinkedHashMap<String, Area>>(ConfigManager2.stringify(a, ConfigManager2.ConfigFileType.Json), ConfigManager2.ConfigFileType.Json).also(::println)
}

0 comments on commit 2a57f72

Please sign in to comment.