All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.autonomousapps.internal.utils.moshi.kt Maven / Gradle / Ivy

There is a newer version: 2.0.2
Show newest version
@file:JvmName("MoshiUtils")

package com.autonomousapps.internal.utils

import com.autonomousapps.model.Coordinates
import com.autonomousapps.model.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)
  }
}

@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)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy