From d925f33e44b48484ddd2fc36dd77e2b0aab583e2 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 30 Dec 2022 18:49:03 +0700 Subject: [PATCH] JsonPath --- .../kstarbound/util/FullJsonPath.kt | 19 ++++ .../dbotthepony/kstarbound/util/JsonPath.kt | 96 +++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 src/main/kotlin/ru/dbotthepony/kstarbound/util/FullJsonPath.kt create mode 100644 src/main/kotlin/ru/dbotthepony/kstarbound/util/JsonPath.kt diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/util/FullJsonPath.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/util/FullJsonPath.kt new file mode 100644 index 00000000..bd93a1af --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/util/FullJsonPath.kt @@ -0,0 +1,19 @@ +package ru.dbotthepony.kstarbound.util + +class FullJsonPath(val fullPath: String) { + init { + val delimers = fullPath.count { it == ':' } + require(delimers < 2) { "Invalid path: $fullPath" } + } + + val path = fullPath.substringBefore(':') + val subpath: JsonPath + + init { + if (path.any { it == ':' }) { + subpath = JsonPath(fullPath.substringAfter(':')) + } else { + subpath = JsonPath.EMPTY + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/util/JsonPath.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/util/JsonPath.kt new file mode 100644 index 00000000..c1be930a --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/util/JsonPath.kt @@ -0,0 +1,96 @@ +package ru.dbotthepony.kstarbound.util + +import com.google.common.collect.ImmutableList +import com.google.gson.JsonArray +import com.google.gson.JsonElement +import com.google.gson.JsonObject + +class JsonPath(val path: String) { + private class Piece(private val value: String) { + private val asNumber = value.toIntOrNull() + + fun navigate(element: JsonElement): JsonElement? { + if (element is JsonObject) { + return element[value] + } + + if (element is JsonArray) { + if (asNumber == null) { + return null + } + + return element[asNumber] + } + + return null + } + + fun navigate(element: Any): Any? { + if (element is List<*>) { + if (asNumber == null) { + return null + } + + return element.getOrNull(asNumber) + } + + if (element is Map<*, *>) { + return element[value] + } + + return null + } + } + + val parts: List = ImmutableList.copyOf(path.split('.')) + private val pieces: List = ImmutableList.copyOf(parts.map { Piece(it) }) + + fun navigate(element: JsonElement): JsonElement? { + var current: JsonElement? = element + + for (piece in pieces) { + if (current == null) + return null + + current = piece.navigate(current) + } + + return current + } + + fun navigate(element: List): Any? { + var current: Any? = element + + for (piece in pieces) { + if (current == null) + return null + + current = piece.navigate(current) + } + + return current + } + + fun navigate(element: Map): Any? { + var current: Any? = element + + for (piece in pieces) { + if (current == null) + return null + + current = piece.navigate(current) + } + + return current + } + + val isEmpty: Boolean + get() = path.isEmpty() + + val isBlank: Boolean + get() = path.isBlank() + + companion object { + val EMPTY = JsonPath("") + } +}