aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/gui/config/storage/FirstLevelSplitJsonFolder.kt
blob: 3c672bf7f601ac40c93acacf380435262472e955 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
@file:OptIn(ExperimentalSerializationApi::class)

package moe.nea.firmament.gui.config.storage

import java.nio.file.Path
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.json.encodeToStream
import kotlin.io.path.createDirectories
import kotlin.io.path.deleteExisting
import kotlin.io.path.exists
import kotlin.io.path.inputStream
import kotlin.io.path.listDirectoryEntries
import kotlin.io.path.nameWithoutExtension
import kotlin.io.path.outputStream
import moe.nea.firmament.Firmament

class FirstLevelSplitJsonFolder(
	val context: ConfigLoadContext,
	val folder: Path
) {

	var hasCreatedBackup = false

	fun backup(cause: String) {
		if (hasCreatedBackup) return
		hasCreatedBackup = true
		context.createBackup(folder, cause)
	}

	fun load(): JsonObject {
		context.logInfo("Loading FLSJF from $folder")
		if (!folder.exists())
			return JsonObject(mapOf())
		return try {
			folder.listDirectoryEntries("*.json")
				.mapNotNull(::loadIndividualFile)
				.toMap()
				.let(::JsonObject)
				.also { context.logInfo("FLSJF from $folder - Voller Erfolg!") }
		} catch (ex: Exception) {
			context.logError("Could not load files from $folder", ex)
			backup("failed-load")
			JsonObject(mapOf())
		}
	}

	fun loadIndividualFile(path: Path): Pair<String, JsonElement>? {
		context.logDebug("Loading partial file from $path")
		return try {
			path.inputStream().use {
				path.nameWithoutExtension to Firmament.json.decodeFromStream(JsonElement.serializer(), it)
			}
		} catch (ex: Exception) {
			context.logError("Could not load file from $path", ex)
			backup("failed-load")
			null
		}
	}

	fun save(value: JsonObject) {
		context.logInfo("Saving FLSJF to $folder")
		context.logDebug("Current value:\n$value")
		if (!folder.exists()) {
			context.logInfo("Creating folder $folder")
			folder.createDirectories()
		}
		val entries = folder.listDirectoryEntries("*.json")
			.toMutableList()
		for ((name, element) in value) {
			val path = saveIndividualFile(name, element)
			if (path != null) {
				entries.remove(path)
			}
		}
		if (entries.isNotEmpty()) {
			context.logInfo("Deleting additional files.")
			for (path in entries) {
				context.logInfo("Deleting $path")
				backup("save-deletion")
				try {
					path.deleteExisting()
				} catch (ex: Exception) {
					context.logError("Could not delete $path", ex)
				}
			}
		}
		context.logInfo("FLSJF to $folder - Voller Erfolg!")
	}

	fun saveIndividualFile(name: String, element: JsonElement): Path? {
		try {
			context.logDebug("Saving partial file with name $name")
			val path = folder.resolve("$name.json")
			context.ensureWritable(path)
			path.outputStream().use {
				Firmament.json.encodeToStream(JsonElement.serializer(), element, it)
			}
			return path
		} catch (ex: Exception) {
			context.logError("Could not save $name with value $element", ex)
			backup("failed-save")
			return null
		}
	}
}