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

commonMain.io.github.optimumcode.json.schema.internal.ReferenceResolver.kt Maven / Gradle / Ivy

There is a newer version: 0.3.0
Show newest version
package io.github.optimumcode.json.schema.internal

import com.eygraber.uri.Uri
import io.github.optimumcode.json.pointer.JsonPointer
import io.github.optimumcode.json.pointer.internal.length

internal interface ReferenceResolver {
  fun ref(refId: RefId): Pair

  fun dynamicRef(refId: RefId): Pair
}

internal class DefaultReferenceResolver(
  private val references: Map,
  private val schemaPathsStack: ArrayDeque> = ArrayDeque(),
) : ReferenceResolver {
  override fun ref(refId: RefId): Pair {
    val resolvedRef = requireNotNull(references[refId]) { "$refId is not found" }
    return resolvedRef.schemaPath to resolvedRef.assertion
  }

  override fun dynamicRef(refId: RefId): Pair {
    val originalRef = requireNotNull(references[refId]) { "$refId is not found" }
    if (!originalRef.dynamic) {
      return originalRef.schemaPath to originalRef.assertion
    }

    val fragment = refId.fragment
    val possibleDynamicRefs: MutableList =
      references.asSequence()
        .filter { (id, link) ->
          link.dynamic && id.fragment == fragment && id != refId
        }.map { it.value }.toMutableList()
    possibleDynamicRefs.sortBy { it.schemaPath.length }

    val resolvedDynamicRef =
      schemaPathsStack.firstNotNullOfOrNull { (_, scopeId) ->
        possibleDynamicRefs.firstOrNull { it.scopeId == scopeId }
      }
        // If no outer anchor found use the original ref
        ?: originalRef
    return resolvedDynamicRef.schemaPath to resolvedDynamicRef.assertion
  }

  fun pushSchemaPath(
    path: JsonPointer,
    scopeId: Uri,
  ) {
    schemaPathsStack.addLast(path to scopeId)
  }

  fun popSchemaPath() {
    schemaPathsStack.removeLast()
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy