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

ai.mantik.elements.meta.MetaVariableApplication.scala Maven / Gradle / Ivy

The newest version!
/*
 * This file is part of the Mantik Project.
 * Copyright (c) 2020-2021 Mantik UG (Haftungsbeschränkt)
 * Authors: See AUTHORS file
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.
 *
 * Additionally, the following linking exception is granted:
 *
 * If you modify this Program, or any covered work, by linking or
 * combining it with other code, such other code is not for that reason
 * alone subject to any of the requirements of the GNU Affero GPL
 * version 3.
 *
 * You can be released from the requirements of the license by purchasing
 * a commercial license.
 */
package ai.mantik.elements.meta

import io.circe.{Json, JsonObject}
import cats.implicits._

/**
  * A Transformation which applies meta variables to JSON.
  *
  * @param metaVariables the list of meta variables. may itself not contain meta variables.
  *
  * Variables have the form ${foo.bar}
  */
case class MetaVariableApplication(
    metaVariables: List[MetaVariable]
) {

  private lazy val metaVariablesByKey: Map[String, MetaVariable] = metaVariables.map { v =>
    v.name -> v
  }.toMap

  def apply(json: Json): Either[String, Json] = {
    json.fold(
      Right(Json.Null),
      b => Right(Json.fromBoolean(b)), // bool
      n => Right(Json.fromJsonNumber(n)), // number
      applyString,
      applyArray,
      x => applyObject(x).map(Json.fromJsonObject)
    )
  }

  private def applyString(s: String): Either[String, Json] = {
    if (s.startsWith("$$")) {
      // escaped
      return Right(Json.fromString(s.stripPrefix("$")))
    }
    if (
      s.startsWith(MetaVariableApplication.MetaVariablePrefix) &&
      s.endsWith(MetaVariableApplication.MetaVariableSuffix)
    ) {
      val variableName = s
        .stripPrefix(MetaVariableApplication.MetaVariablePrefix)
        .stripSuffix(MetaVariableApplication.MetaVariableSuffix)

      metaVariablesByKey.get(variableName) match {
        case None        => Left(s"Variable ${variableName} not found")
        case Some(value) => Right(value.jsonValue)
      }

    } else {
      // no variable access
      Right(Json.fromString(s))
    }
  }

  private def applyArray(v: Vector[Json]): Either[String, Json] = {
    val values: Either[String, Vector[Json]] = v.map(apply).sequence
    values.map { v =>
      Json.arr(v: _*)
    }
  }

  def applyObject(j: JsonObject): Either[String, JsonObject] = {
    val valuesBefore = j.toVector
    val maybeMapped: Either[String, Vector[Json]] = valuesBefore.map { case (key, value) =>
      apply(value)
    }.sequence
    maybeMapped.map { mapped =>
      JsonObject.fromIterable(valuesBefore.map(_._1).zip(mapped))
    }
  }
}

object MetaVariableApplication {

  /** Prefix of a Meta Variable access. */
  val MetaVariablePrefix = "${"

  /** Suffix of a Meta Variable access. */
  val MetaVariableSuffix = "}"
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy