Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.autonomousapps.internal.utils.moshi.kt Maven / Gradle / Ivy
// Copyright (c) 2024. Tony Robalik.
// SPDX-License-Identifier: Apache-2.0
@file:JvmName("MoshiUtils")
package com.autonomousapps.internal.utils
import com.autonomousapps.model.Coordinates
import com.autonomousapps.model.internal.DependencyGraphView
import com.autonomousapps.model.declaration.Variant
import com.google.common.graph.Graph
import com.squareup.moshi.*
import com.squareup.moshi.Types.newParameterizedType
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import dev.zacsweers.moshix.sealed.reflect.MoshiSealedJsonAdapterFactory
import okio.BufferedSource
import okio.buffer
import okio.sink
import java.io.File
const val noJsonIndent = ""
const val prettyJsonIndent = " "
val MOSHI: Moshi by lazy {
Moshi.Builder()
.add(GraphViewAdapter())
.add(MoshiSealedJsonAdapterFactory())
.add(TypeAdapters())
.addLast(KotlinJsonAdapterFactory())
.build()
}
inline fun JsonAdapter.withNulls(withNulls: Boolean): JsonAdapter {
return if (withNulls) {
this.serializeNulls()
} else {
this
}
}
inline fun getJsonAdapter(withNulls: Boolean = false): JsonAdapter {
return MOSHI.adapter(T::class.java).withNulls(withNulls)
}
inline fun getJsonListAdapter(withNulls: Boolean = false): JsonAdapter> {
val type = newParameterizedType(List::class.java, T::class.java)
return MOSHI.adapter>(type).withNulls(withNulls)
}
inline fun getJsonSetAdapter(withNulls: Boolean = false): JsonAdapter> {
val type = newParameterizedType(Set::class.java, T::class.java)
return MOSHI.adapter>(type).withNulls(withNulls)
}
inline fun getJsonMapAdapter(withNulls: Boolean = false): JsonAdapter> {
val type = newParameterizedType(Map::class.java, K::class.java, V::class.java)
return MOSHI.adapter>(type).withNulls(withNulls)
}
inline fun getJsonMapSetAdapter(withNulls: Boolean = false): JsonAdapter>> {
val setType = newParameterizedType(Set::class.java, V::class.java)
val mapType = newParameterizedType(Map::class.java, K::class.java, setType)
return MOSHI.adapter>>(mapType).withNulls(withNulls)
}
inline fun String.fromJson(): T {
return getJsonAdapter().fromJson(this)!!
}
inline fun T.toJson(withNulls: Boolean = false): String {
return getJsonAdapter(withNulls).toJson(this)
}
inline fun String.fromJsonList(withNulls: Boolean = false): List {
return getJsonListAdapter(withNulls).fromJson(this)!!
}
inline fun String.fromJsonSet(withNulls: Boolean = false): Set {
return getJsonSetAdapter(withNulls).fromJson(this)!!
}
inline fun String.fromJsonMap(): Map {
val mapType = newParameterizedType(Map::class.java, K::class.java, V::class.java)
val adapter = MOSHI.adapter>(mapType)
return adapter.fromJson(this)!!
}
inline fun BufferedSource.fromJsonMapList(): Map> {
val listType = newParameterizedType(List::class.java, V::class.java)
val mapType = newParameterizedType(Map::class.java, K::class.java, listType)
val adapter = MOSHI.adapter>>(mapType)
return adapter.fromJson(this)!!
}
inline fun BufferedSource.fromJsonMapSet(): Map> {
return getJsonMapSetAdapter().fromJson(this)!!
}
inline fun T.toPrettyString(withNulls: Boolean = false): String {
return getJsonAdapter(withNulls).indent(prettyJsonIndent).toJson(this)
}
inline fun Map.toPrettyString(withNulls: Boolean = false): String {
return getJsonMapAdapter(withNulls).indent(prettyJsonIndent).toJson(this)
}
/**
* Buffers writes of the set to disk, using the indent to make the output human-readable.
* By default, the output is compacted.
*
* @param set The set to write to file
* @param indent The indent to control how the result is formatted
*/
inline fun File.bufferWriteJsonMap(
set: Map,
withNulls: Boolean = false,
indent: String = noJsonIndent
) {
JsonWriter.of(sink().buffer()).use { writer ->
getJsonMapAdapter(withNulls).indent(indent).toJson(writer, set)
}
}
/**
* Buffers writes of the set to disk, using the indent to make the output human-readable.
* By default, the output is compacted.
*
* @param set The set to write to file
* @param indent The indent to control how the result is formatted
*/
inline fun File.bufferWriteJsonMapSet(set: Map>, indent: String = noJsonIndent) {
JsonWriter.of(sink().buffer()).use { writer ->
getJsonMapSetAdapter().indent(indent).toJson(writer, set)
}
}
/**
* Buffers pretty writes of the set to disk, using the indent to make the output human-readable.
* By default, the output is compacted.
*
* @param set The set to write to file
*/
inline fun File.bufferPrettyWriteJsonList(set: List) {
bufferWriteJsonList(set, prettyJsonIndent)
}
/**
* Buffers writes of the set to disk, using the indent to make the output human-readable.
* By default, the output is compacted.
*
* @param set The set to write to file
* @param indent The indent to control how the result is formatted
*/
inline fun File.bufferWriteJsonList(set: List, indent: String = noJsonIndent) {
JsonWriter.of(sink().buffer()).use { writer ->
getJsonListAdapter().indent(indent).toJson(writer, set)
}
}
/**
* Buffers pretty writes of the set to disk, using the indent to make the output human-readable.
* By default, the output is compacted.
*
* @param set The set to write to file
*/
inline fun File.bufferPrettyWriteJsonSet(set: Set) {
bufferWriteJsonSet(set, prettyJsonIndent)
}
/**
* Buffers writes of the set to disk, using the indent to make the output human-readable.
* By default, the output is compacted.
*
* @param set The set to write to file
* @param indent The indent to control how the result is formatted
*/
inline fun File.bufferWriteJsonSet(set: Set, indent: String = noJsonIndent) {
JsonWriter.of(sink().buffer()).use { writer ->
getJsonSetAdapter().indent(indent).toJson(writer, set)
}
}
/**
* Buffers writes of the set to disk, using the indent to make the output human-readable.
* By default, the output is compacted.
*
* @param set The set to write to file
* @param indent The indent to control how the result is formatted
*/
inline fun File.bufferWriteJson(set: T, indent: String = noJsonIndent) {
JsonWriter.of(sink().buffer()).use { writer ->
getJsonAdapter().indent(indent).toJson(writer, set)
}
}
inline fun File.bufferWriteParameterizedJson(
parameterizedData: A,
indent: String = noJsonIndent
) {
JsonWriter.of(sink().buffer()).use { writer ->
MOSHI.adapter(newParameterizedType(A::class.java, B::class.java))
.indent(indent)
.toJson(writer, parameterizedData)
}
}
@Suppress("unused")
internal class TypeAdapters {
@ToJson fun fileToJson(file: File): String = file.absolutePath
@FromJson fun fileFromJson(absolutePath: String): File = File(absolutePath)
}
@Suppress("unused", "UnstableApiUsage")
internal class GraphViewAdapter {
@ToJson fun graphViewToJson(graphView: DependencyGraphView): GraphViewJson {
return GraphViewJson(
variant = graphView.variant,
configurationName = graphView.configurationName,
nodes = graphView.graph.nodes(),
edges = graphView.graph.edges().asSequence().map { pair ->
pair.nodeU() to pair.nodeV()
}.toSet()
)
}
@FromJson fun jsonToGraphView(json: GraphViewJson): DependencyGraphView {
return DependencyGraphView(
variant = json.variant,
configurationName = json.configurationName,
graph = jsonToGraph(json)
)
}
private fun jsonToGraph(json: GraphViewJson): Graph {
val graphBuilder = DependencyGraphView.newGraphBuilder()
json.nodes.forEach { graphBuilder.addNode(it) }
json.edges.forEach { (source, target) -> graphBuilder.putEdge(source, target) }
return graphBuilder.build()
}
@JsonClass(generateAdapter = false)
internal data class GraphViewJson(
val variant: Variant,
val configurationName: String,
val nodes: Set,
val edges: Set
)
@JsonClass(generateAdapter = false)
internal data class EdgeJson(val source: Coordinates, val target: Coordinates)
private infix fun Coordinates.to(target: Coordinates) = EdgeJson(this, target)
}