io.circe.Encoder Scala Examples

The following examples show how to use io.circe.Encoder. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: Analyzer.scala    From scarango   with MIT License 8 votes vote down vote up
package com.outr.arango

import io.circe.Decoder.Result
import io.circe.{Decoder, DecodingFailure, Encoder, HCursor, Json}

sealed abstract class Analyzer(val name: String)

object Analyzer {
  case object Identity extends Analyzer("identity")
  case object TextGerman extends Analyzer("text_de")
  case object TextEnglish extends Analyzer("text_en")
  case object TextSpanish extends Analyzer("text_es")
  case object TextFinnish extends Analyzer("text_fi")
  case object TextFrench extends Analyzer("text_fr")
  case object TextItalian extends Analyzer("text_it")
  case object TextDutch extends Analyzer("text_nl")
  case object TextNorwegian extends Analyzer("text_no")
  case object TextPortuguese extends Analyzer("text_pt")
  case object TextRussian extends Analyzer("text_ru")
  case object TextSwedish extends Analyzer("text_sv")
  case object TextChinese extends Analyzer("text_zh")

  private val map = List(Identity, TextGerman, TextEnglish, TextSpanish, TextFinnish, TextFrench, TextItalian, TextDutch, TextNorwegian, TextPortuguese, TextRussian, TextSwedish, TextChinese).map(a => a.name -> a).toMap

  def apply(name: String): Analyzer = map.getOrElse(name, throw new RuntimeException(s"Unable to find analyzer by name: $name"))

  implicit val decoder: Decoder[Analyzer] = new Decoder[Analyzer] {
    override def apply(c: HCursor): Result[Analyzer] = c.value.asString match {
      case Some(s) => Right(Analyzer(s))
      case None => Left(DecodingFailure(s"Expected String to decode Analyzer, but got: ${c.value}", Nil))
    }
  }

  implicit val encoder: Encoder[Analyzer] = new Encoder[Analyzer] {
    override def apply(a: Analyzer): Json = Json.fromString(a.name)
  }
} 
Example 2
Source File: ScalajHttpClient.scala    From telegram   with Apache License 2.0 6 votes vote down vote up
package com.bot4s.telegram.clients

import java.net.Proxy
import java.nio.file.Files

import cats.instances.future._
import com.bot4s.telegram.api.RequestHandler
import com.bot4s.telegram.methods.{Request, JsonRequest, MultipartRequest, Response}
import com.bot4s.telegram.models.InputFile
import com.bot4s.telegram.marshalling
import io.circe.parser.parse
import io.circe.{Decoder, Encoder}
import scalaj.http.{Http, MultiPart}
import slogging.StrictLogging

import scala.concurrent.{ExecutionContext, Future, blocking}


class ScalajHttpClient(token: String, proxy: Proxy = Proxy.NO_PROXY, telegramHost: String = "api.telegram.org")
                      (implicit ec: ExecutionContext) extends RequestHandler[Future] with StrictLogging {

  val connectionTimeoutMs = 10000
  val readTimeoutMs = 50000

  private val apiBaseUrl = s"https://$telegramHost/bot$token/"

  def sendRequest[R, T <: Request[_]](request: T)(implicit encT: Encoder[T], decR: Decoder[R]): Future[R] = {
    val url = apiBaseUrl + request.methodName

    val scalajRequest = request match {
      case r: JsonRequest[_] =>
        Http(url)
          .postData(marshalling.toJson(request))
          .header("Content-Type", "application/json")

      case r: MultipartRequest[_] =>

        // InputFile.FileIds are encoded as query params.
        val (fileIds, files) = r.getFiles.partition {
          case (key, _: InputFile.FileId) => true
          case _ => false
        }

        val parts = files.map {
          case (camelKey, inputFile) =>
            val key = marshalling.snakenize(camelKey)
            inputFile match {
              case InputFile.FileId(id) =>
                throw new RuntimeException("InputFile.FileId cannot must be encoded as a query param")

              case InputFile.Contents(filename, contents) =>
                MultiPart(key, filename, "application/octet-stream", contents)

              case InputFile.Path(path) =>
                MultiPart(key, path.getFileName.toString(),
                  "application/octet-stream",
                  Files.newInputStream(path),
                  Files.size(path),
                  _ => ())

              case other =>
                throw new RuntimeException(s"InputFile $other not supported")
            }
        }

        val fields = parse(marshalling.toJson(request)).fold(throw _, _.asObject.map {
          _.toMap.mapValues {
            json =>
              json.asString.getOrElse(marshalling.printer.pretty(json))
          }
        })

        val fileIdsParams = fileIds.map {
          case (key, inputFile: InputFile.FileId) =>
            marshalling.snakenize(key) -> inputFile.fileId
        }

        val params = fields.getOrElse(Map())

        Http(url).params(params ++ fileIdsParams).postMulti(parts: _*)
    }

    import marshalling.responseDecoder

    Future {
      blocking {
        scalajRequest
          .timeout(connectionTimeoutMs, readTimeoutMs)
          .proxy(proxy)
          .asString
      }
    } map {
      x =>
        if (x.isSuccess)
          marshalling.fromJson[Response[R]](x.body)
        else
          throw new RuntimeException(s"Error ${x.code} on request")
    } map (processApiResponse[R])
  }

} 
Example 3
Source File: BlockTag.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.core.api

import io.circe.{Decoder, Encoder}
import jbok.common.math.N

sealed trait BlockTag
object BlockTag {
  case object latest                extends BlockTag
  final case class Number(value: N) extends BlockTag

  def apply(number: N): Number = Number(number)
  def apply(s: String): Number = Number(N(s))
  def apply(i: Int): Number    = Number(N(i))
  def apply(l: Long): Number   = Number(N(l))

  implicit val encoder: Encoder[BlockTag] = Encoder.encodeString.contramap[BlockTag] {
    case BlockTag.latest        => "latest"
    case BlockTag.Number(value) => value.toString()
  }
  implicit val decoder: Decoder[BlockTag] = Decoder.decodeString.map[BlockTag] {
    case "latest" => BlockTag.latest
    case number   => BlockTag(number)
  }
} 
Example 4
Source File: Serialization.scala    From scarango   with MIT License 5 votes vote down vote up
package com.outr.arango

import io.circe.Decoder.Result
import io.circe.{Decoder, Encoder, HCursor, Json}

import scala.language.experimental.macros

case class Serialization[D](private val doc2Json: D => Json, private val json2Doc: Json => D) {
  final def toJson(document: D): Json = Id.update(doc2Json(document))

  final def fromJson(json: Json): D = json2Doc(Id.update(json))

  lazy val decoder: Decoder[D] = new Decoder[D] {
    override def apply(c: HCursor): Result[D] = Right(fromJson(c.value))
  }
}

object Serialization {
  def auto[D]: Serialization[D] = macro Macros.serializationAuto[D]
  def create[D](encoder: Encoder[D], decoder: Decoder[D]): Serialization[D] = {
    val doc2Json = (d: D) => encoder(d)
    val json2Doc = (json: Json) => decoder.decodeJson(json) match {
      case Left(df) => throw df
      case Right(d) => d
    }
    Serialization[D](doc2Json, json2Doc)
  }
} 
Example 5
Source File: Id.scala    From scarango   with MIT License 5 votes vote down vote up
package com.outr.arango

import io.circe.Decoder.Result
import io.circe.{Decoder, Encoder, HCursor, Json}
import com.outr.arango.JsonImplicits._


  lazy val _id: String = s"$collection/$value"

  override def compare(that: Id[D]): Int = this._id.compare(that._id)

  override def toString: String = _id
}

object Id {
  private val ExtractorRegex = """(.+)/(.+)""".r

  implicit def encoder[D]: Encoder[Id[D]] = new Encoder[Id[D]] {
    override def apply(id: Id[D]): Json = Json.fromString(id._id)
  }

  implicit def decoder[D]: Decoder[Id[D]] = new Decoder[Id[D]] {
    override def apply(c: HCursor): Result[Id[D]] = c.value.asString.get match {
      case ExtractorRegex(collection, value) => Right(Id[D](value, collection))
    }
  }

  def parse[D](id: String): Id[D] = id match {
    case ExtractorRegex(collection, value) => Id[D](value, collection)
  }

  def extract[D](json: Json): Id[D] = {
    val updated = update(json)
    decoder[D].decodeJson((updated \ "_id").get) match {
      case Left(df) => throw df
      case Right(id) => id
    }
  }

  def update(json: Json): Json = {
    val _key = (json \ "_key").flatMap(_.asString)
    val _id = (json \ "_id").flatMap(_.asString)
    val _identity = _id.map(parse[Any])

    if (_id.nonEmpty && _key.isEmpty) {
      json.deepMerge(Json.obj("_key" -> Json.fromString(_identity.get.value)))
    } else {
      json
    }
  }
} 
Example 6
Source File: ResourceFileGoldenCodecLaws.scala    From circe-golden   with Apache License 2.0 5 votes vote down vote up
package io.circe.testing.golden

import cats.instances.list._, cats.instances.try_._
import cats.syntax.apply._, cats.syntax.traverse._
import io.circe.{ Decoder, Encoder, Printer }
import java.io.{ File, PrintWriter }
import org.scalacheck.{ Arbitrary, Gen }
import scala.reflect.runtime.universe.TypeTag
import scala.util.{ Failure, Try }
import scala.util.matching.Regex

abstract class ResourceFileGoldenCodecLaws[A](
  name: String,
  resourceRootDir: File,
  resourcePackage: List[String],
  val size: Int,
  count: Int,
  override protected val printer: Printer
) extends GoldenCodecLaws[A]
    with ExampleGeneration[A] {

  private[this] val resourceRootPath: String = "/" + resourcePackage.mkString("/") + "/"
  private[this] val resourceDir: File = resourcePackage.foldLeft(resourceRootDir) {
    case (acc, p) => new File(acc, p)
  }
  private[this] val GoldenFilePattern: Regex = "^-(.{44})\\.json$".r

  private[this] lazy val loadGoldenFiles: Try[List[(A, String)]] =
    Resources.open(resourceRootPath).flatMap { dirSource =>
      val files = dirSource.getLines.flatMap {
        case fileName if fileName.startsWith(name) =>
          fileName.drop(name.length) match {
            case GoldenFilePattern(seed) => Some((seed, fileName))
            case _                       => None
          }
        case _ => None
      }.toList.traverse[Try, (A, String)] {
        case (seed, name) =>
          val contents = Resources.open(resourceRootPath + name).map { source =>
            val lines = source.getLines.mkString("\n")
            source.close()
            lines
          }
          (getValueFromBase64Seed(seed), contents).tupled
      }

      dirSource.close()

      // Fail if we don't have either zero golden files or the required number.
      files.flatMap { values =>
        if (values.size == 0 || values.size == count) files
        else Failure(new IllegalStateException(s"Expected 0 or $count golden files, got ${values.size}"))
      }
    }

  private[this] def generateGoldenFiles: Try[List[(A, String)]] =
    generateRandomGoldenExamples(count).traverse {
      case (seed, value, encoded) =>
        Try {
          resourceDir.mkdirs()
          val file = new File(resourceDir, s"$name-${seed.toBase64}.json")

          val writer = new PrintWriter(file)
          writer.print(encoded)
          writer.close()

          (value, encoded)
        }
    }

  protected lazy val goldenExamples: Try[List[(A, String)]] =
    loadGoldenFiles.flatMap(fs => if (fs.isEmpty) generateGoldenFiles else loadGoldenFiles)
}

object ResourceFileGoldenCodecLaws {
  def apply[A](
    name: String,
    resourceRootDir: File,
    resourcePackage: List[String],
    size: Int,
    count: Int,
   printer: Printer
  )(implicit decodeA: Decoder[A], encodeA: Encoder[A], arbitraryA: Arbitrary[A]): GoldenCodecLaws[A] =
    new ResourceFileGoldenCodecLaws[A](name, resourceRootDir, resourcePackage, size, count, printer) {
      val decode: Decoder[A] = decodeA
      val encode: Encoder[A] = encodeA
      val gen: Gen[A] = arbitraryA.arbitrary
    }

  def apply[A](
    size: Int = 100,
    count: Int = 1,
    printer: Printer = Printer.spaces2
  )(
    implicit decodeA: Decoder[A],
    encodeA: Encoder[A],
    arbitraryA: Arbitrary[A],
    typeTagA: TypeTag[A]
  ): GoldenCodecLaws[A] =
    apply[A](Resources.inferName[A], Resources.inferRootDir, Resources.inferPackage[A], size, count, printer)
} 
Example 7
Source File: GoldenCodecTests.scala    From circe-golden   with Apache License 2.0 5 votes vote down vote up
package io.circe.testing.golden

import cats.instances.string._
import cats.kernel.Eq
import cats.laws.IsEq
import cats.laws.discipline.catsLawsIsEqToProp
import io.circe.{ Decoder, Encoder, Json, Printer }
import io.circe.testing.CodecTests
import org.scalacheck.{ Arbitrary, Prop, Shrink }
import scala.reflect.runtime.universe.TypeTag
import scala.util.{ Failure, Success, Try }

trait GoldenCodecTests[A] extends CodecTests[A] {
  def laws: GoldenCodecLaws[A]

  private[this] def tryListToProp[A: Eq](result: Try[List[IsEq[A]]]): Prop = result match {
    case Failure(error)      => Prop.exception(error)
    case Success(equalities) => Prop.all(equalities.map(catsLawsIsEqToProp(_)): _*)
  }

  def goldenCodec(
    implicit
    arbitraryA: Arbitrary[A],
    shrinkA: Shrink[A],
    eqA: Eq[A],
    arbitraryJson: Arbitrary[Json],
    shrinkJson: Shrink[Json]
  ): RuleSet = new DefaultRuleSet(
    name = "goldenCodec",
    parent = Some(codec),
    "decoding golden files" -> tryListToProp(laws.goldenDecoding),
    "encoding golden files" -> tryListToProp(laws.goldenEncoding)
  )

  def unserializableGoldenCodec(
    implicit
    arbitraryA: Arbitrary[A],
    shrinkA: Shrink[A],
    eqA: Eq[A],
    arbitraryJson: Arbitrary[Json],
    shrinkJson: Shrink[Json]
  ): RuleSet = new DefaultRuleSet(
    name = "goldenCodec",
    parent = Some(unserializableCodec),
    "decoding golden files" -> tryListToProp(laws.goldenDecoding),
    "encoding golden files" -> tryListToProp(laws.goldenEncoding)
  )
}

object GoldenCodecTests {
  def apply[A: Decoder: Encoder: Arbitrary: TypeTag]: GoldenCodecTests[A] =
    apply[A](ResourceFileGoldenCodecLaws[A]())

  def apply[A: Decoder: Encoder: Arbitrary: TypeTag](printer: Printer): GoldenCodecTests[A] =
    apply[A](ResourceFileGoldenCodecLaws[A](printer = printer))

  def apply[A: Decoder: Encoder: Arbitrary: TypeTag](count: Int): GoldenCodecTests[A] =
    apply[A](ResourceFileGoldenCodecLaws[A](count = count))

  def apply[A: Decoder: Encoder: Arbitrary: TypeTag](count: Int, printer: Printer): GoldenCodecTests[A] =
    apply[A](ResourceFileGoldenCodecLaws[A](count = count, printer = printer))

  def apply[A: Decoder: Encoder: Arbitrary](laws0: GoldenCodecLaws[A]): GoldenCodecTests[A] =
    new GoldenCodecTests[A] {
      val laws: GoldenCodecLaws[A] = laws0
    }
} 
Example 8
Source File: PaginationLinks.scala    From kanadi   with MIT License 5 votes vote down vote up
package org.zalando.kanadi
package models

import io.circe.{Decoder, Encoder}

final case class PaginationLinks(prev: Option[PaginationLink], next: Option[PaginationLink])

object PaginationLinks {
  implicit val paginationLinksEncoder: Encoder[PaginationLinks] =
    Encoder.forProduct2(
      "prev",
      "next"
    )(x => PaginationLinks.unapply(x).get)

  implicit val paginationLinksDecoder: Decoder[PaginationLinks] =
    Decoder.forProduct2(
      "prev",
      "next"
    )(PaginationLinks.apply)
} 
Example 9
Source File: BasicServerError.scala    From kanadi   with MIT License 5 votes vote down vote up
package org.zalando.kanadi.models

import io.circe.{Decoder, Encoder}

final case class BasicServerError(error: String, errorDescription: String)

object BasicServerError {
  implicit val basicServerErrorEncoder: Encoder[BasicServerError] =
    Encoder.forProduct2(
      "error",
      "error_description"
    )(x => BasicServerError.unapply(x).get)

  implicit val basicServerErrorDecoder: Decoder[BasicServerError] =
    Decoder.forProduct2(
      "error",
      "error_description"
    )(BasicServerError.apply)
} 
Example 10
Source File: package.scala    From kanadi   with MIT License 5 votes vote down vote up
package org.zalando

import java.net.URI
import cats.syntax.either._
import io.circe.Decoder.Result
import io.circe.syntax._
import io.circe.{Decoder, DecodingFailure, Encoder, HCursor}
import scala.util.control.NonFatal

package object kanadi {
  private[kanadi] implicit val uriEncoder: Encoder[URI] =
    Encoder.instance[URI](_.toString.asJson)

  private[kanadi] implicit val uriDecoder: Decoder[URI] = new Decoder[URI] {
    override def apply(c: HCursor): Result[URI] =
      c.as[String].flatMap { value =>
        try {
          Right(new URI(value))
        } catch {
          case NonFatal(_) => Left(DecodingFailure("Invalid Uri", c.history))
        }
      }
  }
} 
Example 11
Source File: SomeEvent.scala    From kanadi   with MIT License 5 votes vote down vote up
package org.zalando.kanadi

import java.util.UUID

import io.circe.{Decoder, Encoder}

case class SomeEvent(firstName: String, lastName: String, uuid: UUID)

object SomeEvent {
  implicit val someEventEncoder: Encoder[SomeEvent] = Encoder.forProduct3(
    "first_name",
    "last_name",
    "uuid"
  )(x => SomeEvent.unapply(x).get)
  implicit val someEventDecoder: Decoder[SomeEvent] = Decoder.forProduct3(
    "first_name",
    "last_name",
    "uuid"
  )(SomeEvent.apply)
} 
Example 12
Source File: EscapingTests.scala    From circe-yaml   with Apache License 2.0 5 votes vote down vote up
package io.circe.yaml

import io.circe.Encoder
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks
import scala.util.{ Success, Try }
import org.scalatest.matchers.should.Matchers

class EscapingTests extends AnyFlatSpec with Matchers with ScalaCheckDrivenPropertyChecks {

  import io.circe.syntax._
  import io.circe.yaml.Printer.spaces2.pretty
  import io.circe.yaml.parser.parse

  // according to the YAML spec (section 5.1: character set)
  def isPrintable(c: Char): Boolean =
    ('\t' == c) ||
      ('\n' == c) ||
      ('\r' == c) ||
      (' ' <= c && c <= '~') ||
      ('\u0085' == c) ||
      ('\u00a0' <= c && c <= '\ud7ff') ||
      ('\ue000' <= c && c <= '\ufffd')

  def test1(c: Char): Unit = {
    val r = "'\\u%04X'".format(c.toInt)
    def repr[A](a: A): (String, A) = (r, a)

    val json = c.toString.asJson
    val s = pretty(json)

    if (s.contains(c)) repr(isPrintable(c)) shouldBe repr(true)
    else () // we do not enforce that printable chars are never escaped

    repr(s.forall(isPrintable)) shouldBe repr(true)
    repr(Try(parse(s))) shouldBe repr(Success(Right(json)))
  }

  "Escaping" should "properly escape JSON string values (all chars)" in {
    // exhaustive test: 65k test cases
    (Char.MinValue to Char.MaxValue).map(_.toChar).foreach(test1)
  }

  def test2(s0: String): Unit = {
    val json = s0.asJson
    val s1 = pretty(json)
    s1.forall(isPrintable)
    parse(s1) shouldBe Right(json)
  }

  it should "properly escape JSON string values" in {
    forAll { (s0: String) =>
      test2(s0)
    }
  }

  def test3(c: Char): Unit = {
    val m = Map(c.toString -> c.toInt)
    val o = Encoder[Map[String, Int]].apply(m)

    parser.parse(printer.print(o)).right.flatMap(_.as[Map[String, Int]]) shouldBe Right(m)
  }

  it should "properly escape JSON object keys" in {
    // exhaustive test: 65k test cases
    (Char.MinValue to Char.MaxValue).map(_.toChar).foreach(test3)
  }
} 
Example 13
Source File: SymmetricSerializationLaws.scala    From circe-yaml   with Apache License 2.0 5 votes vote down vote up
package io.circe.yaml

import cats.Eq
import cats.instances.either._
import cats.laws._
import cats.laws.discipline._
import io.circe.{ Decoder, Encoder, Json, ParsingFailure }
import org.scalacheck.{ Arbitrary, Prop, Shrink }
import org.typelevel.discipline.Laws

trait SymmetricSerializationLaws {

  def printerRoundTrip[A: Eq: Encoder: Decoder](
    parse: String => Either[ParsingFailure, Json],
    print: Json => String,
    a: A
  ): IsEq[Either[io.circe.Error, A]] =
    parse(print(Encoder[A].apply(a))).right.flatMap(_.as[A]) <-> Right(a)

}

object SymmetricSerializationLaws {

  def apply(): SymmetricSerializationLaws = new SymmetricSerializationLaws {}
}

trait SymmetricSerializationTests extends Laws {
  def laws: SymmetricSerializationLaws

  def symmetricPrinter[A: Eq: Arbitrary: Shrink: Encoder: Decoder](
    print: Json => String,
    parse: String => Either[ParsingFailure, Json]
  ): RuleSet =
    new DefaultRuleSet(
      name = "printer",
      parent = None,
      "roundTrip" -> Prop.forAll { (a: A) =>
        laws.printerRoundTrip(parse, print, a)
      }
    )
}

object SymmetricSerializationTests {
  def apply[A: Eq: Arbitrary: Decoder: Encoder](
    print: Json => String,
    parse: String => Either[ParsingFailure, Json]
  ): SymmetricSerializationTests =
    new SymmetricSerializationTests {
      val laws: SymmetricSerializationLaws = SymmetricSerializationLaws()
      symmetricPrinter[A](print, parse)
    }
} 
Example 14
Source File: CirceJSONSerializer.scala    From scala-json-rpc   with MIT License 5 votes vote down vote up
package io.github.shogowada.scala.jsonrpc.serializers

import io.circe.{Decoder, Encoder, Error, Json}

import scala.language.experimental.macros
import scala.reflect.macros.blackbox

object CirceJSONCoder {
  def encode[T](value: T)(implicit encoder: Encoder[T]): Json = {
    encoder(value)
  }

  def decode[T](json: String)(implicit decoder: Decoder[T]): Either[Error, T] = {
    io.circe.parser.decode[T](json)
  }
}

class CirceJSONSerializer extends JSONSerializer {
  override def serialize[T](value: T): Option[String] = macro CirceJSONSerializerMacro.serialize[T]

  override def deserialize[T](json: String): Option[T] = macro CirceJSONSerializerMacro.deserialize[T]
}

object CirceJSONSerializer {
  def apply(): CirceJSONSerializer = {
    new CirceJSONSerializer
  }
}

object CirceJSONSerializerMacro {
  def serialize[T](c: blackbox.Context)(value: c.Expr[T]): c.Expr[Option[String]] = {
    import c.universe._

    c.Expr[Option[String]](
      q"""
          {
            import io.circe.generic.auto._
            scala.util.Try(io.circe.Printer.noSpaces.pretty(io.github.shogowada.scala.jsonrpc.serializers.CirceJSONCoder.encode($value))).toOption
          }
          """
    )
  }

  def deserialize[T: c.WeakTypeTag](c: blackbox.Context)(json: c.Expr[String]): c.Expr[Option[T]] = {
    import c.universe._

    val deserializeType = weakTypeOf[T]

    c.Expr[Option[T]](
      q"""
          {
            import io.circe.generic.auto._
            io.github.shogowada.scala.jsonrpc.serializers.CirceJSONCoder.decode[$deserializeType]($json).toOption
          }
          """
    )
  }
} 
Example 15
Source File: circe.scala    From sup   with Apache License 2.0 5 votes vote down vote up
package sup.modules

import io.circe.Decoder
import io.circe.Encoder
import sup.data.Report
import sup.data.Tagged
import sup.Health
import sup.HealthResult

object circe {
  implicit val healthCirceEncoder: Encoder[Health] = Encoder[String].contramap(_.toString)

  implicit val healthCirceDecoder: Decoder[Health] =
    Decoder[String].emap(s => Health.fromString(s).toRight(s"$s is not a valid ${Health.getClass.getName}"))

  implicit def taggedCirceEncoder[Tag: Encoder, H: Encoder]: Encoder[Tagged[Tag, H]] =
    Encoder.forProduct2("tag", "health")(tagged => (tagged.tag, tagged.health))

  implicit def taggedCirceDecoder[Tag: Decoder, H: Decoder]: Decoder[Tagged[Tag, H]] =
    Decoder.forProduct2("tag", "health")(Tagged.apply)

  implicit def reportCirceEncoder[G[_], H[_], A: Encoder](implicit H: Encoder[G[H[A]]]): Encoder[Report[G, H, A]] =
    Encoder.forProduct2("health", "checks")(report => (report.health, report.checks))

  implicit def reportCirceDecoder[G[_], H[_], A: Decoder](implicit H: Decoder[G[H[A]]]): Decoder[Report[G, H, A]] =
    Decoder.forProduct2("health", "checks")(Report.apply)

  implicit def healthResultCirceEncoder[H[_]](implicit E: Encoder[H[Health]]): Encoder[HealthResult[H]] =
    E.contramap(_.value)

  implicit def healthResultCirceDecoder[H[_]](implicit D: Decoder[H[Health]]): Decoder[HealthResult[H]] =
    D.map(HealthResult(_))
} 
Example 16
Source File: ModelSet.scala    From seals   with Apache License 2.0 5 votes vote down vote up
package dev.tauri.seals
package checker

import io.circe.{ Encoder, Decoder }

import circe.Codecs


final case class ModelSet(models: Map[String, Map[String, Model]])

final object ModelSet {

  implicit val encoderInstance: Encoder[ModelSet] = {
    // Note: we're explicitly only using `Reified` for decoding `Model`,
    // otherwise we want the default behavior of circe.
    implicit val mEnc: Encoder[Model] = Codecs.encoderFromReified[Model]
    Encoder[Map[String, Map[String, Model]]].contramap(_.models)
  }

  implicit val decoderInstance: Decoder[ModelSet] = {
    // Note: we're explicitly only using `Reified` for encoding `Model`,
    // otherwise we want the default behavior of circe.
    implicit val mDec: Decoder[Model] = Codecs.decoderFromReified[Model]
    Decoder[Map[String, Map[String, Model]]].map(ModelSet(_))
  }
} 
Example 17
Source File: PeersApiRoute.scala    From EncryCore   with GNU General Public License v3.0 5 votes vote down vote up
package encry.api.http.routes

import java.net.{InetAddress, InetSocketAddress}
import akka.actor.{ActorRef, ActorRefFactory}
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import encry.api.http.DataHolderForApi._
import encry.api.http.routes.PeersApiRoute.PeerInfoResponse
import encry.network.BlackList.{BanReason, BanTime, BanType}
import encry.network.ConnectedPeersCollection.PeerInfo
import encry.settings.RESTApiSettings
import io.circe.Encoder
import io.circe.generic.semiauto._
import io.circe.syntax._
import scala.util.{Failure, Success, Try}

case class PeersApiRoute(override val settings: RESTApiSettings, dataHolder: ActorRef)(
  implicit val context: ActorRefFactory
) extends EncryBaseApiRoute {

  override lazy val route: Route = pathPrefix("peers") {
    connectedPeers ~ allPeers ~ bannedList ~ WebRoute.authRoute(connectPeer ~ removeFromBan, settings)
  }

  def allPeers: Route = (path("all") & get) {
    (dataHolder ? GetAllPeers)
      .mapTo[Seq[InetSocketAddress]]
      .map(_.map(_.toString).asJson).okJson()
  }

  def connectedPeers: Route = (path("connected") & get) {
    (dataHolder ? GetConnectedPeersHelper)
      .mapTo[Seq[PeerInfoResponse]].map(_.asJson).okJson()
  }

  def bannedList: Route = (path("banned") & get) {
    (dataHolder ? GetBannedPeersHelper).mapTo[Seq[(InetAddress, (BanReason, BanTime, BanType))]]
    .map(_.map(_.toString).asJson).okJson()
  }

  def connectPeer: Route = path("add") {
    post(entity(as[String]) { str =>
      complete {
        Try {
          val split = str.split(':')
          (split(0), split(1).toInt)
        } match {
          case Success((host, port)) =>
            dataHolder ! UserAddPeer(new InetSocketAddress(host, port))
            StatusCodes.OK
          case Failure(_) =>
            StatusCodes.BadRequest
        }
      }
    })
  }

  def removeFromBan: Route = path("remove") {
    post(entity(as[String]) { str =>
      complete {
        Try {
          val split = str.split(':')
          (split(0), split(1).toInt)
        } match {
          case Success((host, port)) =>
            dataHolder ! RemovePeerFromBanList(new InetSocketAddress(host, port))
            StatusCodes.OK
          case Failure(_) =>
            StatusCodes.BadRequest
        }
      }
    })
  }
}

object PeersApiRoute {

  case class PeerInfoResponse(address: String, name: Option[String], connectionType: Option[String])

  object PeerInfoResponse {

    def fromAddressAndInfo(address: InetSocketAddress, peerInfo: PeerInfo): PeerInfoResponse = PeerInfoResponse(
      address.toString,
      Some(peerInfo.connectedPeer.toString),
      Some(peerInfo.connectionType.toString)
    )
  }

  implicit val encodePeerInfoResponse: Encoder[PeerInfoResponse] = deriveEncoder
} 
Example 18
Source File: CandidateBlock.scala    From EncryCore   with GNU General Public License v3.0 5 votes vote down vote up
package encry.consensus

import io.circe.Encoder
import io.circe.syntax._
import org.encryfoundation.common.modifiers.history.Header
import org.encryfoundation.common.modifiers.mempool.transaction.Transaction
import org.encryfoundation.common.utils.Algos
import org.encryfoundation.common.utils.TaggedTypes.Difficulty

case class CandidateBlock(parentOpt: Option[Header],
                          version: Byte,
                          transactions: Seq[Transaction],
                          timestamp: Long,
                          difficulty: Difficulty,
                          stateRoot: Array[Byte]) {

  override def toString: String = s"<CandidateBlock timestamp=$timestamp txQty=${transactions.size} " +
    s"parentId=${parentOpt.map(_.encodedId).getOrElse("None")}>"
}

object CandidateBlock {

  implicit val jsonEncoder: Encoder[CandidateBlock] = (b: CandidateBlock) => Map(
    "parentId" -> b.parentOpt.map(p => Algos.encode(p.id)).getOrElse("None").asJson,
    "timestamp" -> b.timestamp.asJson,
    "transactions" -> b.transactions.map(_.asJson).asJson,
    "transactionsQty" -> b.transactions.length.asJson,
  ).asJson
} 
Example 19
Source File: CirceSerdes.scala    From kafka-streams-circe   with Apache License 2.0 5 votes vote down vote up
package com.goyeau.kafka.streams.circe

import java.nio.charset.StandardCharsets
import java.util

import io.circe.parser._
import io.circe.{Decoder, Encoder}
import org.apache.kafka.common.errors.SerializationException
import org.apache.kafka.common.serialization.{Deserializer, Serde, Serdes, Serializer}

object CirceSerdes {

  implicit def serializer[T: Encoder]: Serializer[T] =
    new Serializer[T] {
      override def configure(configs: util.Map[String, _], isKey: Boolean): Unit = ()
      override def serialize(topic: String, caseClass: T): Array[Byte] =
        Encoder[T].apply(caseClass).noSpaces.getBytes(StandardCharsets.UTF_8)
      override def close(): Unit = ()
    }

  implicit def deserializer[T: Decoder]: Deserializer[T] =
    new Deserializer[T] {
      override def configure(configs: util.Map[String, _], isKey: Boolean): Unit = ()
      override def deserialize(topic: String, data: Array[Byte]): T =
        Option(data).fold(null.asInstanceOf[T]) { data =>
          decode[T](new String(data, StandardCharsets.UTF_8))
            .fold(error => throw new SerializationException(error), identity)
        }
      override def close(): Unit = ()
    }

  implicit def serde[CC: Encoder: Decoder]: Serde[CC] = Serdes.serdeFrom(serializer, deserializer)
} 
Example 20
Source File: PrimitiveWrappersSpec.scala    From scalapb-circe   with MIT License 5 votes vote down vote up
package scalapb_circe

import com.google.protobuf.ByteString
import jsontest.test3._
import io.circe.{Encoder, Json}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.must.Matchers

class PrimitiveWrappersSpec extends AnyFlatSpec with Matchers {

  private[this] def render[A](a: A)(implicit A: Encoder[A]): Json =
    A.apply(a)

  "Empty object" should "give empty json for Wrapper" in {
    JsonFormat.toJson(Wrapper()) must be(render(Map.empty[String, Json]))
  }

  "primitive values" should "serialize properly" in {
    JsonFormat.toJson(Wrapper(wBool = Some(false))) must be(render(Map("wBool" -> Json.fromBoolean(false))))
    JsonFormat.toJson(Wrapper(wBool = Some(true))) must be(render(Map("wBool" -> Json.fromBoolean(true))))
    JsonFormat.toJson(Wrapper(wDouble = Some(3.1))) must be(render(Map("wDouble" -> Json.fromDouble(3.1))))
    JsonFormat.toJson(Wrapper(wFloat = Some(3.0f))) must be(render(Map("wFloat" -> Json.fromDouble(3.0))))
    JsonFormat.toJson(Wrapper(wInt32 = Some(35544))) must be(render(Map("wInt32" -> Json.fromLong(35544))))
    JsonFormat.toJson(Wrapper(wInt32 = Some(0))) must be(render(Map("wInt32" -> Json.fromLong(0))))
    JsonFormat.toJson(Wrapper(wInt64 = Some(125))) must be(render(Map("wInt64" -> Json.fromString("125"))))
    JsonFormat.toJson(Wrapper(wUint32 = Some(125))) must be(render(Map("wUint32" -> Json.fromLong(125))))
    JsonFormat.toJson(Wrapper(wUint64 = Some(125))) must be(render(Map("wUint64" -> Json.fromString("125"))))
    JsonFormat.toJson(Wrapper(wString = Some("bar"))) must be(render(Map("wString" -> Json.fromString("bar"))))
    JsonFormat.toJson(Wrapper(wString = Some(""))) must be(render(Map("wString" -> Json.fromString(""))))
    JsonFormat.toJson(Wrapper(wBytes = Some(ByteString.copyFrom(Array[Byte](3, 5, 4))))) must be(
      render(Map("wBytes" -> Json.fromString("AwUE")))
    )
    JsonFormat.toJson(Wrapper(wBytes = Some(ByteString.EMPTY))) must be(render(Map("wBytes" -> Json.fromString(""))))
    new Printer(formattingLongAsNumber = true).toJson(Wrapper(wUint64 = Some(125))) must be(
      render(Map("wUint64" -> Json.fromLong(125)))
    )
    new Printer(formattingLongAsNumber = true).toJson(Wrapper(wInt64 = Some(125))) must be(
      render(Map("wInt64" -> Json.fromLong(125)))
    )
  }

  "primitive values" should "parse properly" in {
    JsonFormat.fromJson[Wrapper](render(Map("wBool" -> Json.fromBoolean(false)))) must be(Wrapper(wBool = Some(false)))
    JsonFormat.fromJson[Wrapper](render(Map("wBool" -> Json.fromBoolean(true)))) must be(Wrapper(wBool = Some(true)))
    JsonFormat.fromJson[Wrapper](render(Map("wDouble" -> Json.fromDouble(3.1)))) must be(Wrapper(wDouble = Some(3.1)))
    JsonFormat.fromJson[Wrapper](render(Map("wFloat" -> Json.fromDouble(3.0)))) must be(Wrapper(wFloat = Some(3.0f)))
    JsonFormat.fromJson[Wrapper](render(Map("wInt32" -> Json.fromLong(35544)))) must be(Wrapper(wInt32 = Some(35544)))
    JsonFormat.fromJson[Wrapper](render(Map("wInt32" -> Json.fromLong(0)))) must be(Wrapper(wInt32 = Some(0)))
    JsonFormat.fromJson[Wrapper](render(Map("wInt64" -> Json.fromString("125")))) must be(Wrapper(wInt64 = Some(125)))
    JsonFormat.fromJson[Wrapper](render(Map("wUint32" -> Json.fromLong(125)))) must be(Wrapper(wUint32 = Some(125)))
    JsonFormat.fromJson[Wrapper](render(Map("wUint64" -> Json.fromString("125")))) must be(Wrapper(wUint64 = Some(125)))
    JsonFormat.fromJson[Wrapper](render(Map("wString" -> Json.fromString("bar")))) must be(
      Wrapper(wString = Some("bar"))
    )
    JsonFormat.fromJson[Wrapper](render(Map("wString" -> Json.fromString("")))) must be(Wrapper(wString = Some("")))
    JsonFormat.fromJson[Wrapper](render(Map("wBytes" -> Json.fromString("AwUE")))) must be(
      Wrapper(wBytes = Some(ByteString.copyFrom(Array[Byte](3, 5, 4))))
    )
    JsonFormat.fromJson[Wrapper](render(Map("wBytes" -> Json.fromString("")))) must be(
      Wrapper(wBytes = Some(ByteString.EMPTY))
    )
  }

} 
Example 21
Source File: StatelessJWTAuth.scala    From tsec   with MIT License 5 votes vote down vote up
package tsec.authentication.internal

import java.time.Instant

import cats.data.OptionT
import cats.effect.Sync
import cats.syntax.all._
import io.circe.syntax._
import io.circe.{Decoder, Encoder}
import org.http4s._
import tsec.authentication._
import tsec.common._
import tsec.jws.mac._
import tsec.jwt.algorithms.JWTMacAlgo
import tsec.jwt.JWTClaims
import tsec.mac.MAC
import tsec.mac.jca._

import scala.concurrent.duration._

private[tsec] abstract class StatelessJWTAuth[F[_], V: Decoder: Encoder.AsObject, A: JWTMacAlgo](
    val expiry: FiniteDuration,
    val maxIdle: Option[FiniteDuration],
    signingKey: MacSigningKey[A]
)(implicit F: Sync[F], cv: JWSMacCV[F, A])
    extends JWTAuthenticator[F, V, V, A] {

  private[tsec] def verifyLastTouched(body: JWTMac[A], now: Instant): F[Option[Instant]]

  def parseRaw(raw: String, request: Request[F]): OptionT[F, SecuredRequest[F, V, AugmentedJWT[A, V]]] =
    OptionT(
      (for {
        now         <- F.delay(Instant.now())
        extracted   <- cv.verifyAndParse(raw, signingKey, now)
        jwtid       <- cataOption(extracted.id)
        body        <- extracted.body.asF[F, V]
        expiry      <- cataOption(extracted.body.expiration)
        lastTouched <- verifyLastTouched(extracted, now)
        augmented = AugmentedJWT(
          SecureRandomId.coerce(jwtid),
          extracted,
          body,
          expiry,
          lastTouched
        )
        refreshed <- refresh(augmented)
      } yield SecuredRequest(request, body, refreshed).some)
        .handleError(_ => None)
    )

  def create(body: V): F[AugmentedJWT[A, V]] =
    for {
      now   <- F.delay(Instant.now())
      jwtId <- SecureRandomId.Interactive.generateF[F]
      expiryTime  = now.plusSeconds(expiry.toSeconds)
      lastTouched = touch(now)
      claims = JWTClaims(
        issuedAt = touch(now),
        jwtId = Some(jwtId),
        expiration = Some(expiryTime),
        customFields = body.asJsonObject.toList
      )
      out <- JWTMac.build[F, A](claims, signingKey)
    } yield AugmentedJWT(jwtId, out, body, expiryTime, lastTouched)

  def update(authenticator: AugmentedJWT[A, V]): F[AugmentedJWT[A, V]] =
    F.pure(authenticator)

  def renew(authenticator: AugmentedJWT[A, V]): F[AugmentedJWT[A, V]] =
    for {
      now <- F.delay(Instant.now())
      updatedExpiry = now.plusSeconds(expiry.toSeconds)
      authBody      = authenticator.jwt.body
      lastTouched   = touch(now)
      jwt <- JWTMac.build(
        authBody.withIATOption(lastTouched).withExpiry(updatedExpiry),
        signingKey
      )
    } yield AugmentedJWT(authenticator.id, jwt, authenticator.identity, updatedExpiry, lastTouched)

  def discard(authenticator: AugmentedJWT[A, V]): F[AugmentedJWT[A, V]] =
    F.pure(authenticator.copy(jwt = JWTMac.buildToken[A](JWSMacHeader[A], JWTClaims(), MAC[A](Array.empty[Byte]))))

  def afterBlock(response: Response[F], authenticator: AugmentedJWT[A, V]): OptionT[F, Response[F]] =
    OptionT.pure[F](embed(response, authenticator))
} 
Example 22
Source File: PartialStatelessJWTAuth.scala    From tsec   with MIT License 5 votes vote down vote up
package tsec.authentication.internal

import java.time.Instant

import cats.data.OptionT
import cats.effect.Sync
import cats.syntax.all._
import io.circe.parser.decode
import io.circe.syntax._
import io.circe.{Decoder, Encoder}
import org.http4s._
import tsec.authentication._
import tsec.common._
import tsec.jws.mac._
import tsec.jwt.algorithms.JWTMacAlgo
import tsec.jwt.{JWTClaims, JWTPrinter}
import tsec.mac.jca._

import scala.concurrent.duration._


  def discard(authenticator: AugmentedJWT[A, I]): F[AugmentedJWT[A, I]] =
    for {
      now <- F.delay(Instant.now)
      jwt <- JWTMac
        .build[F, A](
          authenticator.jwt.body
            .withExpiry(now)
            .withJwtID(SecureRandomId.Interactive.generate),
          signingKey
        )
    } yield AugmentedJWT(authenticator.id, jwt, authenticator.identity, now, authenticator.lastTouched)
} 
Example 23
Source File: package.scala    From tsec   with MIT License 5 votes vote down vote up
package tsec

import cats.{Eq, MonadError}
import cats.instances.string._
import cats.syntax.either._
import io.circe.{Decoder, Encoder, HCursor, Json}
import tsec.cipher.common.padding.NoPadding
import tsec.cipher.symmetric._
import tsec.cipher.symmetric.jca._
import tsec.common._
import tsec.mac.MAC
import tsec.mac.jca.MacVerificationError

package object cookies {

  type AEADCookie[A] = AEADCookie.Cookie[A]

  implicit object AEADCookie {
    type Cookie[A] <: String

    @inline def fromEncrypted[A](a: CipherText[A], aad: AAD): AEADCookie[A] =
      apply[A](a.toConcatenated.toB64String + "-" + aad.toB64String)

    @inline def subst[G[_], A](fa: G[String]): G[AEADCookie[A]] = fa.asInstanceOf[G[AEADCookie[A]]]

    @inline def unsubst[G[_], A](fa: G[AEADCookie[A]]): G[String] = fa.asInstanceOf[G[String]]

    @inline def apply[A](raw: String): AEADCookie[A] = raw.asInstanceOf[AEADCookie[A]]

    def getEncryptedContent[F[_], A: AES](
        signed: AEADCookie[A]
    )(implicit encryptor: AADEncryptor[F, A, SecretKey]): Either[CipherTextError, CipherText[A]] = {
      val split = signed.split("-")
      if (split.length != 2)
        Left(CipherTextError("String encoded improperly"))
      else {
        split(0).b64Bytes match {
          case Some(e) => CTOPS.ciphertextFromArray[A, GCM, NoPadding](e)
          case None    => Left(CipherTextError("String encoded improperly"))
        }
      }
    }

    implicit def circeDecoder[A]: Decoder[AEADCookie[A]] = new Decoder[AEADCookie[A]] {
      def apply(c: HCursor) = c.as[String].map(AEADCookie.apply[A])
    }

    implicit def circeEncoder[A]: Encoder[AEADCookie[A]] = new Encoder[AEADCookie[A]] {
      def apply(a: AEADCookie[A]): Json = Json.fromString(a)
    }

  }

  type SignedCookie[A] = SignedCookie.Cookie[A]

  implicit object SignedCookie {
    type Cookie[A] <: String

    @inline def from[A](signed: MAC[A], joined: String): SignedCookie[A] =
      apply[A](joined + "-" + signed.toB64String)

    @inline def apply[A](raw: String): SignedCookie[A] = raw.asInstanceOf[SignedCookie[A]]

    @inline def subst[G[_], A](fa: G[String]): G[SignedCookie[A]] = fa.asInstanceOf[G[SignedCookie[A]]]

    @inline def unsubst[G[_], A](fa: G[SignedCookie[A]]): G[String] = fa.asInstanceOf[G[String]]

    def fromDecodedString[F[_]](original: String)(implicit F: MonadError[F, Throwable]): F[String] =
      original.split("-") match {
        case Array(orig, nonce) =>
          orig.b64Bytes match {
            case Some(o) => F.pure(o.toUtf8String)
            case None    => F.raiseError(MacVerificationError("String encoded improperly"))
          }
        case _ =>
          F.raiseError(MacVerificationError("String encoded improperly"))
      }
  }
  implicit final def cookieEQ[A]: Eq[SignedCookie[A]] = SignedCookie.subst(Eq[String])
  implicit final def ecookieEQ[A]: Eq[AEADCookie[A]]  = Eq.by[AEADCookie[A], String](identity[String])
} 
Example 24
Source File: IssuesReportSerializer.scala    From codacy-analysis-cli   with GNU Affero General Public License v3.0 5 votes vote down vote up
package com.codacy.analysis.core.serializer

import java.nio.file.Path

import com.codacy.analysis.core.model.IssuesAnalysis.FileResults
import com.codacy.analysis.core.model.{Issue, IssuesAnalysis, Location, ToolResult, ToolResults}
import com.codacy.plugins.api.results
import io.circe.{Encoder, Printer}
import io.circe.generic.semiauto.deriveEncoder
import io.circe.syntax._

object IssuesReportSerializer {

  private[IssuesReportSerializer] implicit val levelEncoder: Encoder[results.Result.Level.Value] =
    Encoder.encodeEnumeration(results.Result.Level)

  private[IssuesReportSerializer] implicit val categoryEncoder: Encoder[results.Pattern.Category.Value] =
    Encoder.encodeEnumeration(results.Pattern.Category)

  private[IssuesReportSerializer] implicit val pathEncoder: Encoder[Path] = Encoder.encodeString.contramap(_.toString)

  private[IssuesReportSerializer] implicit val toolResultsEncoder: Encoder[ToolResults] = deriveEncoder
  private[IssuesReportSerializer] implicit val issuesAnalysisEncoder: Encoder[IssuesAnalysis] = deriveEncoder
  private[IssuesReportSerializer] implicit val issueResultEncoder: Encoder[Issue] = deriveEncoder
  private[IssuesReportSerializer] implicit val patternIdEncoder: Encoder[results.Pattern.Id] = deriveEncoder
  private[IssuesReportSerializer] implicit val issueMessageEncoder: Encoder[Issue.Message] = deriveEncoder
  private[IssuesReportSerializer] implicit val issueLocationEncoder: Encoder[Location] = deriveEncoder
  private[IssuesReportSerializer] implicit val resultEncoder: Encoder[ToolResult] = deriveEncoder
  private[IssuesReportSerializer] implicit val fileResultsEncoder: Encoder[FileResults] = deriveEncoder

  def toJsonString(toolResults: Set[ToolResults]): String =
    toolResults.asJson.printWith(Printer.noSpaces.copy(dropNullValues = true))
} 
Example 25
Source File: Json.scala    From codacy-analysis-cli   with GNU Affero General Public License v3.0 5 votes vote down vote up
package com.codacy.analysis.cli.formatter

import java.io.PrintStream
import java.nio.file.Path

import com.codacy.analysis.core.model.Result
import com.codacy.plugins.api.results
import io.circe.Encoder
import io.circe.generic.auto._
import io.circe.syntax._

import scala.util.Properties

object Json extends FormatterCompanion {
  val name: String = "json"
  def apply(stream: PrintStream): Formatter = new Json(stream)
}

private[formatter] class Json(val stream: PrintStream) extends Formatter {

  private var alreadyPrinted: Boolean = false

  private implicit val categoryEncoder: Encoder[results.Pattern.Category.Value] =
    Encoder.encodeEnumeration(results.Pattern.Category)

  private implicit val levelEncoder: Encoder[results.Result.Level.Value] =
    Encoder.encodeEnumeration(results.Result.Level)
  private implicit val fileEncoder: Encoder[Path] = Encoder[String].contramap(_.toString)

  override def begin(): Unit = {
    stream.print("[")
  }

  override def end(): Unit = {
    stream.print("]")
    stream.print(Properties.lineSeparator)
    stream.flush()
  }

  def add(element: Result): Unit = {
    if (alreadyPrinted) stream.print(",") else alreadyPrinted = true
    stream.print(element.asJson.noSpaces)
  }

} 
Example 26
Source File: MagnoliaEncoder.scala    From circe-magnolia   with Apache License 2.0 5 votes vote down vote up
package io.circe.magnolia

import io.circe.magnolia.configured.Configuration
import io.circe.{Encoder, Json}
import magnolia._

private[magnolia] object MagnoliaEncoder {

  private[magnolia] def combine[T](caseClass: CaseClass[Encoder, T])(implicit config: Configuration): Encoder[T] = {
    val paramJsonKeyLookup = caseClass.parameters.map { p =>
      val jsonKeyAnnotation = p.annotations.collectFirst {
        case ann: JsonKey => ann
      }
      jsonKeyAnnotation match {
        case Some(ann) => p.label -> ann.value
        case None => p.label -> config.transformMemberNames(p.label)
      }
    }.toMap

    if (paramJsonKeyLookup.values.toList.distinct.size != caseClass.parameters.length) {
      throw new DerivationError(
        "Duplicate key detected after applying transformation function for case class parameters"
      )
    }

    new Encoder[T] {
      def apply(a: T): Json =
        Json.obj(caseClass.parameters.map { p =>
          val label = paramJsonKeyLookup.getOrElse(p.label, throw new IllegalStateException("Looking up a parameter label should always yield a value. This is a bug"))
          label -> p.typeclass(p.dereference(a))
        }: _*)
    }
  }

  private[magnolia] def dispatch[T](
    sealedTrait: SealedTrait[Encoder, T]
  )(implicit config: Configuration): Encoder[T] = {
    {
      val origTypeNames = sealedTrait.subtypes.map(_.typeName.short)
      val transformed = origTypeNames.map(config.transformConstructorNames).distinct
      if (transformed.length != origTypeNames.length) {
        throw new DerivationError(
          "Duplicate key detected after applying transformation function for " +
            "sealed trait child classes"
        )
      }
    }

    new Encoder[T] {
      def apply(a: T): Json = {
        sealedTrait.dispatch(a) { subtype =>
          val baseJson = subtype.typeclass(subtype.cast(a))
          val constructorName = config
            .transformConstructorNames(subtype.typeName.short)
          config.discriminator match {
            case Some(discriminator) => {
              // Note: Here we handle the edge case where a subtype of a sealed trait has a custom encoder which does not encode
              // encode into a JSON object and thus we cannot insert the discriminator key. In this case we fallback
              // to the non-discriminator case for this subtype. This is same as the behavior of circe-generic-extras
              baseJson.asObject match {
                case Some(jsObj) => Json.fromJsonObject(jsObj.add(discriminator, Json.fromString(constructorName)))
                case None => Json.obj(constructorName -> baseJson)
              }
            }
            case None =>
              Json.obj(constructorName -> baseJson)
          }
        }
      }
    }
  }

} 
Example 27
Source File: tags.scala    From circe-magnolia   with Apache License 2.0 5 votes vote down vote up
package io.circe.magnolia

import io.circe.{Decoder, Encoder}
import shapeless.tag.@@

object tags {
  trait Magnolia
  trait Circe

  final class TaggedDecoder[T, A](val inner: Decoder[A]) extends AnyVal {
    def toTagged: Decoder[A] @@ T = {
      shapeless.tag[T](inner)
    }
  }
  final class TaggedEncoder[T, A](val inner: Encoder[A]) extends AnyVal {
    def toTagged: Encoder[A] @@ T = {
      shapeless.tag[T](inner)
    }
  }

  final class PartialTagged[T] {
    def apply[A](decoder: Decoder[A]): TaggedDecoder[T, A] = new TaggedDecoder(decoder)
    def apply[A](encoder: Encoder[A]): TaggedEncoder[T, A] = new TaggedEncoder(encoder)
  }

  def mkTag[T]: PartialTagged[T] = new PartialTagged[T]

} 
Example 28
Source File: CodecEquivalenceTests.scala    From circe-magnolia   with Apache License 2.0 5 votes vote down vote up
package io.circe.magnolia

import cats.instances.either._
import cats.kernel.Eq
import cats.laws._
import cats.laws.discipline._
import io.circe.magnolia.tags.{TaggedDecoder, TaggedEncoder}
import io.circe.{Decoder, Encoder, Json}
import org.scalacheck.{Arbitrary, Prop, Shrink}
import org.typelevel.discipline.Laws
import shapeless.tag.@@

trait CodecEquivalenceLaws[A] {
  def circeDecoder: Decoder[A] @@ tags.Circe
  def magnoliaDecoder: Decoder[A] @@ tags.Magnolia

  def circeEncoder: Encoder[A] @@ tags.Circe
  def magnoliaEncoder: Encoder[A] @@ tags.Magnolia

  def encoderEq(a: A): IsEq[Json] =
    circeEncoder(a) <-> magnoliaEncoder(a)

  def decoderEq(a: A): IsEq[Decoder.Result[A]] = {
    val encoded = magnoliaEncoder(a)
    encoded.as(circeDecoder) <-> encoded.as(magnoliaDecoder)
  }
}

object CodecEquivalenceLaws {

  def apply[A](
    implicit
    circeDecode: Decoder[A] @@ tags.Circe,
    magnoliaDecode: Decoder[A] @@ tags.Magnolia,
    circeEncode: Encoder[A] @@ tags.Circe,
    magnoliaEncode: Encoder[A] @@ tags.Magnolia) = new CodecEquivalenceLaws[A] {

    override val circeDecoder = circeDecode
    override val magnoliaDecoder = magnoliaDecode
    override val circeEncoder = circeEncode
    override val magnoliaEncoder = magnoliaEncode
  }
}

trait CodecEquivalenceTests[A] extends Laws {
  def laws: CodecEquivalenceLaws[A]

  def codecEquivalence(
    implicit
    arbitraryA: Arbitrary[A],
    shrinkA: Shrink[A],
    eqA: Eq[A]): RuleSet = new DefaultRuleSet(
    name = "codec equality",
    parent = None,
    "encoder equivalence" -> Prop.forAll { (a: A) =>
      laws.encoderEq(a)
    },
    "decoder equivalence" -> Prop.forAll { (a: A) =>
      laws.decoderEq(a)
    }
  )

  // Use codecEquivalence if possible. Use only when only
  // derived Encoder can be equivalent and should be documented
  def encoderEquivalence(
    implicit
    arbitraryA: Arbitrary[A],
    shrinkA: Shrink[A]
    ): RuleSet = new DefaultRuleSet(
    name = "codec equality",
    parent = None,
    "encoder equivalence" -> Prop.forAll { (a: A) =>
      laws.encoderEq(a)
    },
  )
}

object CodecEquivalenceTests {
  def apply[A](
    implicit
    circeDecode: Decoder[A] @@ tags.Circe,
    magnoliaDecode: Decoder[A] @@ tags.Magnolia,
    circeEncode: Encoder[A] @@ tags.Circe,
    magnoliaEncode: Encoder[A] @@ tags.Magnolia): CodecEquivalenceTests[A] = new CodecEquivalenceTests[A] {
    val laws: CodecEquivalenceLaws[A] = CodecEquivalenceLaws[A](
      circeDecode, magnoliaDecode, circeEncode, magnoliaEncode)
  }

  def useTagged[A](
    implicit
    circeDecode: TaggedDecoder[tags.Circe, A],
    magnoliaDecode: TaggedDecoder[tags.Magnolia, A],
    circeEncode: TaggedEncoder[tags.Circe, A],
    magnoliaEncode: TaggedEncoder[tags.Magnolia, A]): CodecEquivalenceTests[A] = new CodecEquivalenceTests[A] {
    val laws: CodecEquivalenceLaws[A] = CodecEquivalenceLaws[A](
      circeDecode.toTagged, magnoliaDecode.toTagged, circeEncode.toTagged, magnoliaEncode.toTagged)
  }
} 
Example 29
Source File: WrappedOptionalString.scala    From circe-magnolia   with Apache License 2.0 5 votes vote down vote up
package io.circe.tests.examples

import cats.kernel.Eq
import io.circe.{ Decoder, Encoder }
import org.scalacheck.Arbitrary

case class OptionalString(value: String) {
  def toOption: Option[String] = value match {
    case "" => None
    case other => Some(other)
  }
}

object OptionalString {
  def fromOption(o: Option[String]): OptionalString =
    OptionalString(o.getOrElse(""))

  implicit val decodeOptionalString: Decoder[OptionalString] =
    Decoder[Option[String]].map(fromOption)

  implicit val encodeOptionalString: Encoder[OptionalString] =
    Encoder[Option[String]].contramap(_.toOption)

  implicit val eqOptionalString: Eq[OptionalString] = Eq.fromUniversalEquals

  implicit val arbitraryOptionalString: Arbitrary[OptionalString] =
    Arbitrary(Arbitrary.arbitrary[Option[String]].map(fromOption))
}

case class WrappedOptionalField(f: OptionalString)

object WrappedOptionalField {
  implicit val decodeWrappedOptionalField: Decoder[WrappedOptionalField] =
    Decoder.forProduct1("f")(WrappedOptionalField.apply)

  implicit val encodeWrappedOptionalField: Encoder[WrappedOptionalField] =
    Encoder.forProduct1("f")(_.f)

  implicit val eqWrappedOptionalField: Eq[WrappedOptionalField] =
    Eq.fromUniversalEquals

  implicit val arbitraryWrappedOptionalField: Arbitrary[WrappedOptionalField] =
    Arbitrary(Arbitrary.arbitrary[OptionalString].map(WrappedOptionalField(_)))
} 
Example 30
Source File: AutoDerivedSuite.scala    From circe-magnolia   with Apache License 2.0 5 votes vote down vote up
package io.circe.magnolia

import io.circe.magnolia.derivation.decoder.auto._
import io.circe.magnolia.derivation.encoder.auto._
import io.circe.testing.CodecTests
import io.circe.tests.CirceSuite
import io.circe.tests.examples._
import io.circe.{Decoder, Encoder, Json}
import shapeless.tag
import shapeless.tag.@@
import shapeless.test.illTyped

class AutoDerivedSuite extends CirceSuite {
  import AutoDerivedSuiteInputs._

  // TODO: All these imports are temporary workaround for https://github.com/propensive/magnolia/issues/89
  import Encoder._
  import Decoder._

  private implicit val encodeStringTag: Encoder[String @@ Tag] = Encoder[String].narrow
  private implicit val decodeStringTag: Decoder[String @@ Tag] = Decoder[String].map(tag[Tag](_))

  checkLaws("Codec[Tuple1[Int]]", CodecTests[Tuple1[Int]].unserializableCodec)
  checkLaws("Codec[(Int, Int, Foo)]", CodecTests[(Int, Int, Foo)].unserializableCodec)
  checkLaws("Codec[Qux[Int]]", CodecTests[Qux[Int]].unserializableCodec)
  checkLaws("Codec[Seq[Foo]]", CodecTests[Seq[Foo]].unserializableCodec)
  checkLaws("Codec[Baz]", CodecTests[Baz].unserializableCodec)
  checkLaws("Codec[Foo]", CodecTests[Foo].unserializableCodec)
  checkLaws("Codec[OuterCaseClassExample]", CodecTests[OuterCaseClassExample].unserializableCodec)
  checkLaws("Codec[RecursiveAdtExample]", CodecTests[RecursiveAdtExample].unserializableCodec)
  checkLaws("Codec[RecursiveWithOptionExample]", CodecTests[RecursiveWithOptionExample].unserializableCodec)
  checkLaws("Codec[RecursiveWithListExample]", CodecTests[RecursiveWithListExample].unserializableCodec)
  checkLaws("Codec[AnyValInside]", CodecTests[AnyValInside].unserializableCodec)

  "A generically derived codec" should "not interfere with base instances" in forAll { (is: List[Int]) =>
    val json = Encoder[List[Int]].apply(is)

    assert(json === Json.fromValues(is.map(Json.fromInt)) && json.as[List[Int]] === Right(is))
  }

  it should "not be derived for Object" in {
    illTyped("Decoder[Object]")
    illTyped("Encoder[Object]")
  }

  it should "not be derived for AnyRef" in {
    illTyped("Decoder[AnyRef]")
    illTyped("Encoder[AnyRef]")
  }

  "Generic decoders" should "not interfere with defined decoders" in forAll { (xs: List[String]) =>
    val json = Json.obj("SubtypeWithExplicitInstance" -> Json.fromValues(xs.map(Json.fromString)))
    val ch = Decoder[Sealed].apply(json.hcursor)
    val res = ch === Right(SubtypeWithExplicitInstance(xs): Sealed)
    assert(res)
  }

  "Generic encoders" should "not interfere with defined encoders" in forAll { (xs: List[String]) =>
    val json = Json.obj("SubtypeWithExplicitInstance" -> Json.fromValues(xs.map(Json.fromString)))

    assert(Encoder[Sealed].apply(SubtypeWithExplicitInstance(xs): Sealed) === json)
  }

  // TODO: tagged types don't work ATM, might be related to https://github.com/propensive/magnolia/issues/89
  //  checkLaws("Codec[WithTaggedMembers]", CodecTests[WithTaggedMembers].unserializableCodec)
  checkLaws("Codec[Seq[WithSeqOfTagged]]", CodecTests[Seq[WithSeqOfTagged]].unserializableCodec)
} 
Example 31
Source File: SemiautoDerivedSuite.scala    From circe-magnolia   with Apache License 2.0 5 votes vote down vote up
package io.circe.magnolia

import io.circe.magnolia.derivation.decoder.semiauto._
import io.circe.magnolia.derivation.encoder.semiauto._
import io.circe.testing.CodecTests
import io.circe.tests.CirceSuite
import io.circe.tests.examples._
import io.circe.{Decoder, Encoder, Json}
import shapeless.test.illTyped

class SemiautoDerivedSuite extends CirceSuite {
  import SemiautoDerivedSuiteInputs._

  implicit def decodeBox[A: Decoder]: Decoder[Box[A]] = deriveMagnoliaDecoder
  implicit def encodeBox[A: Encoder]: Encoder[Box[A]] = deriveMagnoliaEncoder

  implicit def decodeQux[A: Decoder]: Decoder[Qux[A]] = deriveMagnoliaDecoder
  implicit def encodeQux[A: Encoder]: Encoder[Qux[A]] = deriveMagnoliaEncoder

  implicit val decodeWub: Decoder[Wub] = deriveMagnoliaDecoder
  implicit val encodeWub: Encoder[Wub] = deriveMagnoliaEncoder
  implicit val decodeFoo: Decoder[Foo] = deriveMagnoliaDecoder
  implicit val encodeFoo: Encoder[Foo] = deriveMagnoliaEncoder

  implicit val decodeAnyValInside: Decoder[AnyValInside] = deriveMagnoliaDecoder
  implicit val encodeAnyValInside: Encoder[AnyValInside] = deriveMagnoliaEncoder

  implicit val decodeRecursiveAdtExample: Decoder[RecursiveAdtExample] = deriveMagnoliaDecoder
  implicit val encodeRecursiveAdtExample: Encoder[RecursiveAdtExample] = deriveMagnoliaEncoder

  implicit val decodeRecursiveWithOptionExample: Decoder[RecursiveWithOptionExample] =
    deriveMagnoliaDecoder
  implicit val encodeRecursiveWithOptionExample: Encoder[RecursiveWithOptionExample] =
    deriveMagnoliaEncoder

  checkLaws("Codec[Tuple1[Int]]", CodecTests[Tuple1[Int]].unserializableCodec)
  checkLaws("Codec[(Int, Int, Foo)]", CodecTests[(Int, Int, Foo)].unserializableCodec)
  checkLaws("Codec[Box[Int]]", CodecTests[Box[Int]].unserializableCodec)
  checkLaws("Codec[Qux[Int]]", CodecTests[Qux[Int]].unserializableCodec)
  checkLaws("Codec[Seq[Foo]]", CodecTests[Seq[Foo]].unserializableCodec)
  checkLaws("Codec[Baz]", CodecTests[Baz].unserializableCodec)
  checkLaws("Codec[Foo]", CodecTests[Foo].unserializableCodec)
  checkLaws("Codec[RecursiveAdtExample]", CodecTests[RecursiveAdtExample].unserializableCodec)
  checkLaws("Codec[RecursiveWithOptionExample]", CodecTests[RecursiveWithOptionExample].unserializableCodec)
  checkLaws("Codec[AnyValInside]", CodecTests[AnyValInside].unserializableCodec)

  "A generically derived codec" should "not interfere with base instances" in forAll { (is: List[Int]) =>
    val json = Encoder[List[Int]].apply(is)

    assert(json === Json.fromValues(is.map(Json.fromInt)) && json.as[List[Int]] === Right(is))
  }

  it should "not come from nowhere" in {
    illTyped("Decoder[OvergenerationExampleInner]")
    illTyped("Encoder[OvergenerationExampleInner]")

    illTyped("Decoder[OvergenerationExampleOuter0]")
    illTyped("Encoder[OvergenerationExampleOuter0]")
    illTyped("Decoder[OvergenerationExampleOuter1]")
    illTyped("Encoder[OvergenerationExampleOuter1]")
  }

  it should "require instances for all parts" in {
    illTyped("deriveMagnoliaDecoder[OvergenerationExampleInner0]")
    illTyped("deriveMagnoliaDecoder[OvergenerationExampleInner1]")
    illTyped("deriveMagnoliaEncoder[OvergenerationExampleInner0]")
    illTyped("deriveMagnoliaEncoder[OvergenerationExampleInner1]")
  }
} 
Example 32
Source File: SemiautoDerivedEquivalenceSuite.scala    From circe-magnolia   with Apache License 2.0 5 votes vote down vote up
package io.circe.magnolia

import io.circe.{Decoder, Encoder}
import io.circe.tests.CirceSuite
import io.circe.tests.examples._
import shapeless.tag
import shapeless.tag.@@
import tags._

class SemiautoDerivedEquivalenceSuite extends CirceSuite {
  import SemiautoDerivedSuiteInputs._

  object magnolia {
    import io.circe.magnolia.derivation.decoder.semiauto._
    import io.circe.magnolia.derivation.encoder.semiauto._

    implicit val magnoliaEncoder3 = tag[Magnolia](deriveMagnoliaEncoder[Box[Int]])
    implicit val magnoliaEncoder4 = tag[Magnolia](deriveMagnoliaEncoder[Qux[Int]])
    implicit val magnoliaEncoder6 = tag[Magnolia](deriveMagnoliaEncoder[Baz])
    implicit val magnoliaEncoder11 = tag[Magnolia](deriveMagnoliaEncoder[Wub])
    implicit val magnoliaEncoder10 = tag[Magnolia](deriveMagnoliaEncoder[Bam])
    implicit val magnoliaEncoder7 = tag[Magnolia](deriveMagnoliaEncoder[Foo])
    private implicit val encodeRecursiveAdtExample: Encoder[RecursiveAdtExample] = deriveMagnoliaEncoder[RecursiveAdtExample]
    implicit val magnoliaEncoder8 = tag[Magnolia](encodeRecursiveAdtExample)
    private implicit val encodeREcursiveWithOptionExample: Encoder[RecursiveWithOptionExample] = deriveMagnoliaEncoder[RecursiveWithOptionExample]
    implicit val magnoliaEncoder9 = tag[Magnolia](encodeREcursiveWithOptionExample)
    implicit val magnoliaEncoder1 = tag[Magnolia](deriveMagnoliaEncoder[AnyValInside])
    implicit val magnoliaEncoder5: Encoder[Seq[Foo]] @@ Magnolia = tag[Magnolia](Encoder.encodeSeq(magnoliaEncoder7))


    implicit val magnoliaDecoder3 = tag[Magnolia](deriveMagnoliaDecoder[Box[Int]])
    implicit val magnoliaDecoder4 = tag[Magnolia](deriveMagnoliaDecoder[Qux[Int]])
    implicit val magnoliaDecoder11 = tag[Magnolia](deriveMagnoliaDecoder[Wub])
    implicit val magnoliaDecoder10 = tag[Magnolia](deriveMagnoliaDecoder[Bam])
    implicit val magnoliaDecoder6 = tag[Magnolia](deriveMagnoliaDecoder[Baz])
    implicit val magnoliaDecoder7 = tag[Magnolia](deriveMagnoliaDecoder[Foo])
    private implicit val decoderREcursiveAdtExample: Decoder[RecursiveAdtExample] = deriveMagnoliaDecoder[RecursiveAdtExample]
    implicit val magnoliaDecoder8 = tag[Magnolia](decoderREcursiveAdtExample)
    private implicit val decoderRecursiveWithOptionExample: Decoder[RecursiveWithOptionExample] = deriveMagnoliaDecoder[RecursiveWithOptionExample]
    implicit val magnoliaDecoder9 = tag[Magnolia](decoderRecursiveWithOptionExample)
    implicit val magnoliaDecoder1 = tag[Magnolia](deriveMagnoliaDecoder[AnyValInside])
    implicit val magnoliaDecoder5 = tag[Magnolia](Decoder.decodeSeq(magnoliaDecoder7))
  }

  object circe {

    import io.circe.generic.semiauto._

    implicit val enc1 = deriveEncoder[Wub]
    implicit val dec1 = deriveDecoder[Wub]

    implicit val enc2 = deriveEncoder[BaseAdtExample]
    implicit val dec2 = deriveDecoder[BaseAdtExample]

    implicit val circeEncoder3 = tag[Circe](deriveEncoder[Box[Int]])
    implicit val circeEncoder4 = tag[Circe](deriveEncoder[Qux[Int]])
    implicit val circeEncoder6 = tag[Circe](deriveEncoder[Baz])
    implicit val circeEncoder7 = tag[Circe](deriveEncoder[Foo])
    private implicit val encoderREcursiveAdtExample: Encoder[RecursiveAdtExample] = deriveEncoder[RecursiveAdtExample]
    implicit val circeEncoder8 = tag[Circe](encoderREcursiveAdtExample)
    private implicit val encoderRecursiveWithOptionExample: Encoder[RecursiveWithOptionExample] = deriveEncoder[RecursiveWithOptionExample]
    implicit val circeEncoder9 = tag[Circe](encoderRecursiveWithOptionExample)
    implicit val circeEncoder1 = tag[Circe](deriveEncoder[AnyValInside])
    implicit val circeEncoder5: Encoder[Seq[Foo]] @@ Circe = tag[Circe](Encoder.encodeSeq(circeEncoder7))

    implicit val circeDecoder3 = tag[Circe](deriveDecoder[Box[Int]])
    implicit val circeDecoder4 = tag[Circe](deriveDecoder[Qux[Int]])
    implicit val circeDecoder6 = tag[Circe](deriveDecoder[Baz])
    implicit val circeDecoder7 = tag[Circe](deriveDecoder[Foo]: Decoder[Foo])
    private implicit val decodeRecursiveAdtExample: Decoder[RecursiveAdtExample] = deriveDecoder[RecursiveAdtExample]
    implicit val circeDecoder8 = tag[Circe](decodeRecursiveAdtExample)
    private implicit val decodeRecursiveWithOptionExample: Decoder[RecursiveWithOptionExample] = deriveDecoder[RecursiveWithOptionExample]
    implicit val circeDecoder9 = tag[Circe](decodeRecursiveWithOptionExample)
    implicit val circeDecoder1 = tag[Circe](deriveDecoder[AnyValInside])
    implicit val circeDecoder5 = tag[Circe](Decoder.decodeSeq(circeDecoder7))
  }

  import magnolia._
  import circe._

  checkLaws("Codec[Box[Int]]", CodecEquivalenceTests[Box[Int]].codecEquivalence)
  checkLaws("Codec[Qux[Int]]", CodecEquivalenceTests[Qux[Int]].codecEquivalence)
  checkLaws("Codec[Baz]", CodecEquivalenceTests[Baz].codecEquivalence)
  checkLaws("Codec[Foo]", CodecEquivalenceTests[Foo].codecEquivalence)
  checkLaws("Codec[RecursiveAdtExample]", CodecEquivalenceTests[RecursiveAdtExample].codecEquivalence)
  checkLaws("Codec[RecursiveWithOptionExample]", CodecEquivalenceTests[RecursiveWithOptionExample].codecEquivalence)
  checkLaws("Codec[AnyValInside]", CodecEquivalenceTests[AnyValInside].codecEquivalence)
  checkLaws("Codec[Seq[Foo]]", CodecEquivalenceTests[Seq[Foo]].codecEquivalence)
} 
Example 33
Source File: PriorityIssueTest.scala    From circe-magnolia   with Apache License 2.0 5 votes vote down vote up
package io.circe.magnolia.incompat


import io.circe.{Encoder, Json}
import io.circe.magnolia.CirceMagnoliaSuite
import io.circe.magnolia.derivation.encoder.auto._
import org.scalatest.OptionValues

case class MapContainer(theMap: Map[String, List[Int]])


class PriorityIssueTest extends CirceMagnoliaSuite with OptionValues {

  // todo: uncomment when https://github.com/propensive/magnolia/issues/89 is fixed
  "Circe Magnolia Encoder" should "use instances from companion even if they are not imported" ignore {
    val encoder = Encoder[MapContainer]
    val json = encoder(MapContainer(Map("f" -> List(1, 2, 3))))
    json.hcursor.downField("theMap").downField("f").focus.value shouldBe
      Json.arr(Json.fromInt(1), Json.fromInt(2), Json.fromInt(3))
  }

  "Circe Magnolia Encoder" should "use instances from companion if they are explicitly imported" in {
    import Encoder._

    val encoder = Encoder[MapContainer]
    val json = encoder(MapContainer(Map("f" -> List(1, 2, 3))))
    json.hcursor.downField("theMap").downField("f").focus.value shouldBe
      Json.arr(Json.fromInt(1), Json.fromInt(2), Json.fromInt(3))
  }
} 
Example 34
Source File: HardcodedDerivationSpec.scala    From circe-magnolia   with Apache License 2.0 5 votes vote down vote up
package io.circe.magnolia.configured

import io.circe.Encoder
import io.circe.magnolia.MagnoliaEncoder
import io.circe.magnolia.configured.HardcodedDerivationSpec.{User, UserType}
import io.circe.parser.parse
import io.circe.tests.CirceSuite
import magnolia.{CaseClass, Magnolia, SealedTrait}

// An example of hardcoding a configuration. This means at when deriving Encoder/Decoder you no longer need to provide
// a Configuration object
class HardcodedDerivationSpec extends CirceSuite {
  "Hardcoded Encoder deriver" should "match the hardcoded configured behavior" in {
    assert(UserType.encoder(User("John", "Doe")).asRight[Throwable] == parse(
      """
        {
          "type": "user",
          "first_name": "John",
          "last_name": "Doe"
        }
      """))
  }
}

object HardcodedDerivationSpec {

  sealed trait UserType
  final case class User(firstName: String, lastName: String) extends UserType

  final case class SuperUser(name: String) extends UserType

  object UserType {
    implicit val encoder: Encoder[UserType] = hardcodedConfiguration.deriveEncoder[UserType]
  }

  object hardcodedConfiguration {
    val config: Configuration =
      Configuration
        .default
        .withDiscriminator("type")
        .withSnakeCaseConstructorNames
        .withSnakeCaseMemberNames

    type Typeclass[T] = Encoder[T]

    def combine[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] =
      MagnoliaEncoder.combine(caseClass)(config)

    def dispatch[T](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] =
      MagnoliaEncoder.dispatch(sealedTrait)(config)

    def deriveEncoder[T]: Typeclass[T] = macro Magnolia.gen[T]
  }

} 
Example 35
Source File: SemiautoDerivedSuiteInputs.scala    From circe-magnolia   with Apache License 2.0 5 votes vote down vote up
package io.circe.magnolia

import cats.kernel.Eq
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}
import org.scalacheck.{Arbitrary, Gen}
import org.scalacheck.Arbitrary.arbitrary

object SemiautoDerivedSuiteInputs {

  sealed trait RecursiveAdtExample
  case class BaseAdtExample(a: String) extends RecursiveAdtExample
  case class NestedAdtExample(r: RecursiveAdtExample)
      extends RecursiveAdtExample

  object RecursiveAdtExample {
    implicit val eqRecursiveAdtExample: Eq[RecursiveAdtExample] =
      Eq.fromUniversalEquals

    private def atDepth(depth: Int): Gen[RecursiveAdtExample] =
      if (depth < 3)
        Gen.oneOf(
          Arbitrary.arbitrary[String].map(BaseAdtExample(_)),
          atDepth(depth + 1).map(NestedAdtExample(_))
        )
      else Arbitrary.arbitrary[String].map(BaseAdtExample(_))

    implicit val arbitraryRecursiveAdtExample: Arbitrary[RecursiveAdtExample] =
      Arbitrary(atDepth(0))
  }

  case class RecursiveWithOptionExample(o: Option[RecursiveWithOptionExample])

  object RecursiveWithOptionExample {
    implicit val eqRecursiveWithOptionExample: Eq[RecursiveWithOptionExample] =
      Eq.fromUniversalEquals

    private def atDepth(depth: Int): Gen[RecursiveWithOptionExample] =
      if (depth < 3)
        Gen.option(atDepth(depth + 1)).map(RecursiveWithOptionExample(_))
      else Gen.const(RecursiveWithOptionExample(None))

    implicit val arbitraryRecursiveWithOptionExample
      : Arbitrary[RecursiveWithOptionExample] =
      Arbitrary(atDepth(0))
  }

  case class AnyInt(value: Int) extends AnyVal

  object AnyInt {
    implicit val encodeAnyInt: Encoder[AnyInt] = deriveEncoder
    implicit val decodeAnyInt: Decoder[AnyInt] = deriveDecoder
  }

  case class AnyValInside(v: AnyInt)

  object AnyValInside {
    implicit val eqAnyValInside: Eq[AnyValInside] = Eq.fromUniversalEquals

    implicit val arbitraryAnyValInside: Arbitrary[AnyValInside] =
      Arbitrary(arbitrary[Int].map(i => AnyValInside(AnyInt(i))))
  }

  case class OvergenerationExampleInner(i: Int)
  case class OvergenerationExampleOuter0(i: OvergenerationExampleInner)
  case class OvergenerationExampleOuter1(oi: Option[OvergenerationExampleInner])
} 
Example 36
Source File: ExternalNotification.scala    From CloudGenesis   with Apache License 2.0 5 votes vote down vote up
package com.lifeway.cloudops.cloudformation

import io.circe.{Decoder, Encoder}

case class ExternalNotification(eventType: EventType,
                                accountId: String,
                                stackName: String,
                                stackFile: String,
                                templateFile: String,
                                fileVersion: String,
                                bucket: String,
                                tags: Option[Seq[Tag]])

object ExternalNotification {
  implicit val encoder: Encoder[ExternalNotification] =
    Encoder.forProduct8("eventType",
                        "accountId",
                        "stackName",
                        "stackFile",
                        "templateFile",
                        "stackFileVersion",
                        "bucket",
                        "tags")(x =>
      (x.eventType, x.accountId, x.stackName, x.stackFile, x.templateFile, x.fileVersion, x.bucket, x.tags))

  implicit val decoder: Decoder[ExternalNotification] =
    Decoder.forProduct8("eventType",
                        "accountId",
                        "stackName",
                        "stackFile",
                        "templateFile",
                        "stackFileVersion",
                        "bucket",
                        "tags")(ExternalNotification.apply)
} 
Example 37
Source File: Types.scala    From CloudGenesis   with Apache License 2.0 5 votes vote down vote up
package com.lifeway.cloudops.cloudformation

import io.circe.{Decoder, Encoder, Json}


sealed trait EventType
case object CreateUpdateEvent extends EventType
case object DeletedEvent      extends EventType

object EventType {
  implicit val encoder: Encoder[EventType] = Encoder[EventType] {
    case CreateUpdateEvent => Json.fromString("CreateUpdateEvent")
    case DeletedEvent      => Json.fromString("DeletedEvent")
  }
  implicit val decoder: Decoder[EventType] = Decoder[EventType] { c =>
    for {
      eType <- c.as[String]
    } yield {
      eType match {
        case "CreateUpdateEvent" => CreateUpdateEvent
        case "DeletedEvent"      => DeletedEvent
      }
    }
  }
}

case class S3File(bucket: String, key: String, versionId: String, eventType: EventType)

object S3File {
  implicit val decoder: Decoder[S3File] =
    Decoder.forProduct4("bucketName", "key", "versionId", "eventType")(S3File.apply)
  implicit val encoder: Encoder[S3File] =
    Encoder.forProduct4("bucketName", "key", "versionId", "eventType")(f => (f.bucket, f.key, f.versionId, f.eventType))
} 
Example 38
Source File: Http4sClientSpec.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.api.clients

import canoe.api._
import canoe.methods.Method
import canoe.models.InputFile
import cats.effect.IO
import io.circe.{Decoder, Encoder}
import org.http4s.HttpApp
import org.http4s.client.Client
import org.http4s.dsl.io._
import io.circe.Json
import io.chrisdavenport.log4cats.slf4j.Slf4jLogger
import org.scalatest.freespec.AnyFreeSpec

class Http4sClientSpec extends AnyFreeSpec {
  private case class TestMethod(name: String = "test",
                                encoder: Encoder[String] = Encoder.encodeString,
                                decoder: Decoder[String] = Decoder.decodeString,
                                files: List[InputFile] = Nil)
      extends Method[String, String] {
    def attachments(request: String): List[(String, InputFile)] = files.map("" -> _)
  }

  private implicit val testMethod = TestMethod()

  private def response(s: String) = s"""{"ok" : true, "result" : "$s"}"""

  private implicit val logger = Slf4jLogger.getLogger[IO]

  "Client" - {
    "sends" - {
      "to correct Telegram endpoint" in {
        val client: Client[IO] = Client.fromHttpApp(HttpApp(r => Ok(response(r.uri.toString))))
        val tgClient = new Http4sTelegramClient("token", client)

        assert(tgClient.execute("any").unsafeRunSync() == s"https://api.telegram.org/bottoken/${testMethod.name}")
      }

      val tgClient = new Http4sTelegramClient("", Client.fromHttpApp(HttpApp[IO] { r =>
        Ok(response(r.headers.get(org.http4s.headers.`Content-Type`).map(_.value.replace("\"", "''")).getOrElse("")))
      }))

      "json POST request if attachments contain file upload" in {
        assert(tgClient.execute("any").unsafeRunSync() == "application/json")
      }

      "multipart POST request if attachments contain file upload" in {
        val resp = tgClient.execute("any")(testMethod.copy(files = List(InputFile.Upload("", Array.emptyByteArray))))
        assert(resp.unsafeRunSync().startsWith("multipart/form-data"))
      }
    }

    "encodes/decodes" - {
      "request entity with method encoder" in {
        val tgClient = new Http4sTelegramClient(
          "",
          Client.fromHttpApp(HttpApp[IO](_.bodyAsText.compile.string.flatMap(s => Ok(response(s.replace("\"", "'"))))))
        )
        val res = tgClient.execute("")(testMethod.copy(encoder = Encoder.instance(_ => Json.fromString("encoded"))))

        assert(res.unsafeRunSync() == "'encoded'")
      }

      "result entity with method decoder" in {
        val tgClient = new Http4sTelegramClient("", Client.fromHttpApp(HttpApp[IO](_ => Ok(response("")))))
        val res = tgClient.execute("")(testMethod.copy(decoder = Decoder.const("decoded")))

        assert(res.unsafeRunSync() == "decoded")
      }
    }

    "handles" - {
      "decode failure as ResponseDecodingError" in {
        val tgClient = new Http4sTelegramClient("", Client.fromHttpApp(HttpApp[IO](_ => Ok("{}"))))

        assertThrows[ResponseDecodingError](tgClient.execute("any").unsafeRunSync())
      }

      "unsuccessful result as FailedMethod" in {
        val response = """{"ok" : false, "result" : "any"}"""
        val tgClient = new Http4sTelegramClient("", Client.fromHttpApp(HttpApp[IO](_ => Ok(response))))

        assertThrows[FailedMethod[String, String]](tgClient.execute("any").unsafeRunSync())
      }
    }
  }
} 
Example 39
Source File: AddStickerToSet.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.stickers

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.{InputFile, MaskPosition}
import io.circe.generic.semiauto.deriveEncoder
import io.circe.{Decoder, Encoder}
import cats.instances.option._
import cats.syntax.all._


  def animated(userId: Int,
               name: String,
               sticker: InputFile,
               emojis: String,
               maskPosition: Option[MaskPosition]
  ): AddStickerToSet =
    new AddStickerToSet(userId, name, None, Some(sticker), emojis, maskPosition)

  import io.circe.generic.auto._

  implicit val method: Method[AddStickerToSet, Boolean] =
    new Method[AddStickerToSet, Boolean] {

      def name: String = "addStickerToSet"

      def encoder: Encoder[AddStickerToSet] = deriveEncoder[AddStickerToSet].snakeCase

      def decoder: Decoder[Boolean] = Decoder.decodeBoolean

      def attachments(request: AddStickerToSet): List[(String, InputFile)] =
        List(request.pngSticker.tupleLeft("png_sticker"), request.tgsSticker.tupleLeft("tgs_sticker")).flatten
    }
} 
Example 40
Source File: AnswerInlineQuery.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.queries

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.{InlineQueryResult, InputFile}
import io.circe.generic.semiauto.deriveEncoder
import io.circe.{Decoder, Encoder}


final case class AnswerInlineQuery(inlineQueryId: String,
                                   results: Seq[InlineQueryResult],
                                   cacheTime: Option[Int] = None,
                                   isPersonal: Option[Boolean] = None,
                                   nextOffset: Option[String] = None,
                                   switchPmText: Option[String] = None,
                                   switchPmParameter: Option[String] = None)

object AnswerInlineQuery {
  import io.circe.generic.auto._

  implicit val method: Method[AnswerInlineQuery, Boolean] =
    new Method[AnswerInlineQuery, Boolean] {

      def name: String = "answerInlineQuery"

      def encoder: Encoder[AnswerInlineQuery] = deriveEncoder[AnswerInlineQuery].snakeCase

      def decoder: Decoder[Boolean] = Decoder.decodeBoolean

      def attachments(request: AnswerInlineQuery): List[(String, InputFile)] = Nil
    }
} 
Example 41
Source File: SendMediaGroup.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.messages.TelegramMessage
import canoe.models.{ChatId, InputFile, InputMedia}
import io.circe.generic.semiauto.deriveEncoder
import io.circe.{Decoder, Encoder}


final case class SendMediaGroup(chatId: ChatId,
                                media: List[InputMedia],
                                disableNotification: Option[Boolean] = None,
                                replyToMessageId: Option[Int] = None)

object SendMediaGroup {
  import io.circe.generic.auto._

  implicit val method: Method[SendMediaGroup, List[TelegramMessage]] =
    new Method[SendMediaGroup, List[TelegramMessage]] {

      def name: String = "sendMediaGroup"

      def encoder: Encoder[SendMediaGroup] =
        deriveEncoder[SendMediaGroup]
          .contramap[SendMediaGroup](
            s =>
              s.copy(media = s.media.filter(_.media match {
                case InputFile.Upload(_, _) => false
                case InputFile.Existing(_)  => true
              }))
          )
          .snakeCase

      def decoder: Decoder[List[TelegramMessage]] =
        Decoder.decodeList(TelegramMessage.telegramMessageDecoder)

      def attachments(request: SendMediaGroup): List[(String, InputFile)] =
        request.media.flatMap(_.files)
    }
} 
Example 42
Source File: SendDocument.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.ParseMode.ParseMode
import canoe.models.messages.DocumentMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}


final case class SendDocument(chatId: ChatId,
                              document: InputFile,
                              thumb: Option[InputFile] = None,
                              caption: Option[String] = None,
                              parseMode: Option[ParseMode] = None,
                              disableNotification: Option[Boolean] = None,
                              replyToMessageId: Option[Int] = None,
                              replyMarkup: Option[ReplyMarkup] = None)

object SendDocument {
  import io.circe.generic.auto._

  implicit val method: Method[SendDocument, DocumentMessage] =
    new Method[SendDocument, DocumentMessage] {

      def name: String = "sendDocument"

      def encoder: Encoder[SendDocument] = deriveEncoder[SendDocument].snakeCase

      def decoder: Decoder[DocumentMessage] = deriveDecoder[DocumentMessage]

      def attachments(request: SendDocument): List[(String, InputFile)] =
        List("document" -> request.document)
    }
} 
Example 43
Source File: SendVideo.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.ParseMode.ParseMode
import canoe.models.messages.VideoMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}


final case class SendVideo(chatId: ChatId,
                           video: InputFile,
                           duration: Option[Int] = None,
                           width: Option[Int] = None,
                           height: Option[Int] = None,
                           thumb: Option[InputFile] = None,
                           caption: Option[String] = None,
                           parseMode: Option[ParseMode] = None,
                           supportsStreaming: Option[Boolean] = None,
                           disableNotification: Option[Boolean] = None,
                           replyToMessageId: Option[Int] = None,
                           replyMarkup: Option[ReplyMarkup] = None)

object SendVideo {
  import io.circe.generic.auto._

  implicit val method: Method[SendVideo, VideoMessage] =
    new Method[SendVideo, VideoMessage] {

      def name: String = "sendVideo"

      def encoder: Encoder[SendVideo] = deriveEncoder[SendVideo].snakeCase

      def decoder: Decoder[VideoMessage] = deriveDecoder[VideoMessage]

      def attachments(request: SendVideo): List[(String, InputFile)] =
        List("video" -> request.video)
    }
} 
Example 44
Source File: EditMessageCaption.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.ParseMode.ParseMode
import canoe.models.messages.TelegramMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.auto._
import io.circe.generic.semiauto.deriveEncoder
import io.circe.{Decoder, Encoder}


  def inlined(inlineMessageId: String,
              caption: Option[String],
              parseMode: Option[ParseMode] = None,
              replyMarkup: Option[ReplyMarkup] = None): EditMessageCaption =
    new EditMessageCaption(None, None, Some(inlineMessageId), caption, parseMode, replyMarkup)

  implicit val method: Method[EditMessageCaption, Either[Boolean, TelegramMessage]] =
    new Method[EditMessageCaption, Either[Boolean, TelegramMessage]] {
      def name: String = "editMessageCaption"

      def encoder: Encoder[EditMessageCaption] = deriveEncoder[EditMessageCaption].snakeCase

      def decoder: Decoder[Either[Boolean, TelegramMessage]] =
        Decoder.decodeBoolean.either(TelegramMessage.telegramMessageDecoder)

      def attachments(request: EditMessageCaption): List[(String, InputFile)] = Nil
    }
} 
Example 45
Source File: SendAudio.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.ParseMode.ParseMode
import canoe.models.messages.AudioMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}


final case class SendAudio(chatId: ChatId,
                           audio: InputFile,
                           duration: Option[Int] = None,
                           caption: Option[String] = None,
                           parseMode: Option[ParseMode] = None,
                           performer: Option[String] = None,
                           title: Option[String] = None,
                           thumb: Option[InputFile] = None,
                           disableNotification: Option[Boolean] = None,
                           replyToMessageId: Option[Int] = None,
                           replyMarkup: Option[ReplyMarkup] = None)

object SendAudio {
  import io.circe.generic.auto._

  implicit val method: Method[SendAudio, AudioMessage] =
    new Method[SendAudio, AudioMessage] {

      def name: String = "sendAudio"

      def encoder: Encoder[SendAudio] = deriveEncoder[SendAudio].snakeCase

      def decoder: Decoder[AudioMessage] = deriveDecoder[AudioMessage]

      def attachments(request: SendAudio): List[(String, InputFile)] =
        List("audio" -> request.audio)
    }
} 
Example 46
Source File: EditMessageText.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.ParseMode.ParseMode
import canoe.models.messages.TelegramMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.semiauto.deriveEncoder
import io.circe.{Decoder, Encoder}


  def inlined(inlineMessageId: String,
              text: String,
              parseMode: Option[ParseMode] = None,
              disableWebPagePreview: Option[Boolean] = None,
              replyMarkup: Option[ReplyMarkup] = None): EditMessageText =
    new EditMessageText(None, None, Some(inlineMessageId), text, parseMode, disableWebPagePreview, replyMarkup)

  implicit val method: Method[EditMessageText, Either[Boolean, TelegramMessage]] =
    new Method[EditMessageText, Either[Boolean, TelegramMessage]] {
      import io.circe.generic.auto._

      def name: String = "editMessageText"

      def encoder: Encoder[EditMessageText] = deriveEncoder[EditMessageText].snakeCase

      def decoder: Decoder[Either[Boolean, TelegramMessage]] =
        Decoder.decodeBoolean.either(TelegramMessage.telegramMessageDecoder)

      def attachments(request: EditMessageText): List[(String, InputFile)] = Nil
    }
} 
Example 47
Source File: SendAnimation.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.ParseMode.ParseMode
import canoe.models.messages.AnimationMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}


final case class SendAnimation(chatId: ChatId,
                               animation: InputFile,
                               duration: Option[Int] = None,
                               width: Option[Int] = None,
                               height: Option[Int] = None,
                               thumb: Option[InputFile] = None,
                               caption: Option[String] = None,
                               parseMode: Option[ParseMode] = None,
                               disableNotification: Option[Boolean] = None,
                               replyToMessageId: Option[Int] = None,
                               replyMarkup: Option[ReplyMarkup] = None)

object SendAnimation {
  import io.circe.generic.auto._

  implicit val method: Method[SendAnimation, AnimationMessage] =
    new Method[SendAnimation, AnimationMessage] {

      def name: String = "sendAnimation"

      def encoder: Encoder[SendAnimation] = deriveEncoder[SendAnimation].snakeCase

      def decoder: Decoder[AnimationMessage] = deriveDecoder[AnimationMessage]

      def attachments(request: SendAnimation): List[(String, InputFile)] =
        List("animation" -> request.animation) ++ request.thumb.map(t => "thumb" -> t).toList
    }
} 
Example 48
Source File: SendVideoNote.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.messages.VideoNoteMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}


final case class SendVideoNote(chatId: ChatId,
                               videoNote: InputFile,
                               duration: Option[Int] = None,
                               length: Option[Int] = None,
                               disableNotification: Option[Boolean] = None,
                               replyToMessageId: Option[Int] = None,
                               replyMarkup: Option[ReplyMarkup] = None)

object SendVideoNote {
  import io.circe.generic.auto._

  implicit val method: Method[SendVideoNote, VideoNoteMessage] =
    new Method[SendVideoNote, VideoNoteMessage] {

      def name: String = "sendVideoNote"

      def encoder: Encoder[SendVideoNote] = deriveEncoder[SendVideoNote].snakeCase

      def decoder: Decoder[VideoNoteMessage] = deriveDecoder[VideoNoteMessage]

      def attachments(request: SendVideoNote): List[(String, InputFile)] =
        List("videoNote" -> request.videoNote)
    }
} 
Example 49
Source File: SendVoice.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.ParseMode.ParseMode
import canoe.models.messages.VoiceMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}


final case class SendVoice(chatId: ChatId,
                           voice: InputFile,
                           caption: Option[String] = None,
                           parseMode: Option[ParseMode] = None,
                           duration: Option[Int] = None,
                           disableNotification: Option[Boolean] = None,
                           replyToMessageId: Option[Int] = None,
                           replyMarkup: Option[ReplyMarkup] = None)

object SendVoice {
  import io.circe.generic.auto._

  implicit val method: Method[SendVoice, VoiceMessage] =
    new Method[SendVoice, VoiceMessage] {

      def name: String = "sendVoice"

      def encoder: Encoder[SendVoice] = deriveEncoder[SendVoice].snakeCase

      def decoder: Decoder[VoiceMessage] = deriveDecoder[VoiceMessage]

      def attachments(request: SendVoice): List[(String, InputFile)] =
        List("voice" -> request.voice)
    }
} 
Example 50
Source File: EditMessageLiveLocation.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.messages.TelegramMessage
import canoe.models.{ChatId, InlineKeyboardMarkup, InputFile}
import io.circe.generic.semiauto.deriveEncoder
import io.circe.{Decoder, Encoder}


  def inlined(inlineMessageId: Int,
              lat: Double,
              long: Double,
              replyMarkup: Option[InlineKeyboardMarkup] = None): EditMessageLiveLocation =
    new EditMessageLiveLocation(None, None, Some(inlineMessageId), lat, long, replyMarkup)

  implicit val method: Method[EditMessageLiveLocation, Either[Boolean, TelegramMessage]] =
    new Method[EditMessageLiveLocation, Either[Boolean, TelegramMessage]] {
      import io.circe.generic.auto._

      def name: String = "editMessageLiveLocation"

      def encoder: Encoder[EditMessageLiveLocation] = deriveEncoder[EditMessageLiveLocation].snakeCase

      def decoder: Decoder[Either[Boolean, TelegramMessage]] =
        Decoder.decodeBoolean.either(TelegramMessage.telegramMessageDecoder)

      def attachments(request: EditMessageLiveLocation): List[(String, InputFile)] = Nil
    }
} 
Example 51
Source File: SendGame.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.messages.GameMessage
import canoe.models.{InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}


final case class SendGame(chatId: Long,
                          gameShortName: String,
                          disableNotification: Option[Boolean] = None,
                          replyToMessageId: Option[Int] = None,
                          replyMarkup: Option[ReplyMarkup] = None)

object SendGame {
  import io.circe.generic.auto._

  implicit val method: Method[SendGame, GameMessage] =
    new Method[SendGame, GameMessage] {

      def name: String = "sendGame"

      def encoder: Encoder[SendGame] = deriveEncoder[SendGame].snakeCase

      def decoder: Decoder[GameMessage] = deriveDecoder[GameMessage]

      def attachments(request: SendGame): List[(String, InputFile)] = Nil
    }
} 
Example 52
Source File: SendSticker.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.messages.StickerMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}


final case class SendSticker(chatId: ChatId,
                             sticker: InputFile,
                             disableNotification: Option[Boolean] = None,
                             replyToMessageId: Option[Int] = None,
                             replyMarkup: Option[ReplyMarkup] = None)

object SendSticker {
  import io.circe.generic.auto._

  implicit val method: Method[SendSticker, StickerMessage] =
    new Method[SendSticker, StickerMessage] {

      def name: String = "sendSticker"

      def encoder: Encoder[SendSticker] = deriveEncoder[SendSticker].snakeCase

      def decoder: Decoder[StickerMessage] = deriveDecoder[StickerMessage]

      def attachments(request: SendSticker): List[(String, InputFile)] =
        List("sticker" -> request.sticker)
    }
} 
Example 53
Source File: SendDice.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.messages.DiceThrownMessage
import canoe.models.{ChatId, DiceEmoji, InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}

final case class SendDice(chatId: ChatId,
                          emoji: DiceEmoji,
                          disableNotification: Option[Boolean] = None,
                          replyToMessageId: Option[Int] = None,
                          replyMarkup: Option[ReplyMarkup] = None)

object SendDice {
  import io.circe.generic.auto._

  implicit val method: Method[SendDice, DiceThrownMessage] =
    new Method[SendDice, DiceThrownMessage] {

      def name: String = "sendDice"

      def encoder: Encoder[SendDice] = deriveEncoder[SendDice].snakeCase

      def decoder: Decoder[DiceThrownMessage] = deriveDecoder[DiceThrownMessage]

      def attachments(request: SendDice): List[(String, InputFile)] = Nil
    }
} 
Example 54
Source File: SendContact.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.messages.ContactMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}


final case class SendContact(chatId: ChatId,
                             phoneNumber: String,
                             firstName: String,
                             lastName: Option[String] = None,
                             vcard: Option[String] = None,
                             disableNotification: Option[Boolean] = None,
                             replyToMessageId: Option[Int] = None,
                             replyMarkup: Option[ReplyMarkup] = None)

object SendContact {
  import io.circe.generic.auto._

  implicit val method: Method[SendContact, ContactMessage] =
    new Method[SendContact, ContactMessage] {

      def name: String = "sendContact"

      def encoder: Encoder[SendContact] = deriveEncoder[SendContact].snakeCase

      def decoder: Decoder[ContactMessage] = deriveDecoder[ContactMessage]

      def attachments(request: SendContact): List[(String, InputFile)] = Nil
    }
} 
Example 55
Source File: SendPhoto.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.ParseMode.ParseMode
import canoe.models.messages.PhotoMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}


final case class SendPhoto(chatId: ChatId,
                           photo: InputFile,
                           caption: Option[String] = None,
                           parseMode: Option[ParseMode] = None,
                           disableNotification: Option[Boolean] = None,
                           replyToMessageId: Option[Int] = None,
                           replyMarkup: Option[ReplyMarkup] = None)

object SendPhoto {
  import io.circe.generic.auto._

  implicit val method: Method[SendPhoto, PhotoMessage] =
    new Method[SendPhoto, PhotoMessage] {

      def name: String = "sendPhoto"

      def encoder: Encoder[SendPhoto] = deriveEncoder[SendPhoto].snakeCase

      def decoder: Decoder[PhotoMessage] = deriveDecoder[PhotoMessage]

      def attachments(request: SendPhoto): List[(String, InputFile)] =
        List("photo" -> request.photo)
    }
} 
Example 56
Source File: SendVenue.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.messages.VenueMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}


final case class SendVenue(chatId: ChatId,
                           latitude: Double,
                           longitude: Double,
                           title: String,
                           address: String,
                           foursquareId: Option[String] = None,
                           foursquareType: Option[String] = None,
                           disableNotification: Option[Boolean] = None,
                           replyToMessageId: Option[Int] = None,
                           replyMarkup: Option[ReplyMarkup] = None)

object SendVenue {
  import io.circe.generic.auto._

  implicit val method: Method[SendVenue, VenueMessage] =
    new Method[SendVenue, VenueMessage] {

      def name: String = "sendVenue"

      def encoder: Encoder[SendVenue] = deriveEncoder[SendVenue].snakeCase

      def decoder: Decoder[VenueMessage] = deriveDecoder[VenueMessage]

      def attachments(request: SendVenue): List[(String, InputFile)] = Nil
    }
} 
Example 57
Source File: SendLocation.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.messages.LocationMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}


final case class SendLocation(chatId: ChatId,
                              latitude: Double,
                              longitude: Double,
                              livePeriod: Option[Int] = None,
                              disableNotification: Option[Boolean] = None,
                              replyToMessageId: Option[Int] = None,
                              replyMarkup: Option[ReplyMarkup] = None)

object SendLocation {
  import io.circe.generic.auto._

  implicit val method: Method[SendLocation, LocationMessage] =
    new Method[SendLocation, LocationMessage] {

      def name: String = "sendLocation"

      def encoder: Encoder[SendLocation] = deriveEncoder[SendLocation].snakeCase

      def decoder: Decoder[LocationMessage] = deriveDecoder[LocationMessage]

      def attachments(request: SendLocation): List[(String, InputFile)] = Nil
    }
} 
Example 58
Source File: EditMessageMedia.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.messages.TelegramMessage
import canoe.models.{ChatId, InlineKeyboardMarkup, InputFile, InputMedia}
import io.circe.generic.semiauto.deriveEncoder
import io.circe.{Decoder, Encoder}


  def inlined(inlineMessageId: String,
              media: InputMedia,
              replyMarkup: Option[InlineKeyboardMarkup] = None): EditMessageMedia =
    new EditMessageMedia(None, None, Some(inlineMessageId), media, replyMarkup)

  implicit val method: Method[EditMessageMedia, Either[Boolean, TelegramMessage]] =
    new Method[EditMessageMedia, Either[Boolean, TelegramMessage]] {
      import io.circe.generic.auto._

      def name: String = "editMessageMedia"

      def encoder: Encoder[EditMessageMedia] =
        deriveEncoder[EditMessageMedia].snakeCase

      def decoder: Decoder[Either[Boolean, TelegramMessage]] =
        Decoder.decodeBoolean.either(TelegramMessage.telegramMessageDecoder)

      def attachments(request: EditMessageMedia): List[(String, InputFile)] =
        request.media.files
    }
} 
Example 59
Source File: SendMessage.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.messages

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.ParseMode.ParseMode
import canoe.models.messages.TextMessage
import canoe.models.{ChatId, InputFile, ReplyMarkup}
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder}


final case class SendMessage(chatId: ChatId,
                             text: String,
                             parseMode: Option[ParseMode] = None,
                             disableWebPagePreview: Option[Boolean] = None,
                             disableNotification: Option[Boolean] = None,
                             replyToMessageId: Option[Int] = None,
                             replyMarkup: Option[ReplyMarkup] = None)

object SendMessage {
  import io.circe.generic.auto._

  implicit val method: Method[SendMessage, TextMessage] =
    new Method[SendMessage, TextMessage] {

      def name: String = "sendMessage"

      def encoder: Encoder[SendMessage] = deriveEncoder[SendMessage].snakeCase

      def decoder: Decoder[TextMessage] = deriveDecoder[TextMessage]

      def attachments(request: SendMessage): List[(String, InputFile)] = Nil
    }
} 
Example 60
Source File: SetGameScore.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.games

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.messages.TelegramMessage
import canoe.models.{ChatId, InputFile}
import io.circe.generic.semiauto.deriveEncoder
import io.circe.{Decoder, Encoder}


  def inlined(inlineMessageId: String,
              userId: Int,
              score: Long,
              force: Option[Boolean] = None,
              disableEditMessage: Option[Boolean] = None): SetGameScore =
    new SetGameScore(userId, score, force, disableEditMessage, inlineMessageId = Some(inlineMessageId))

  implicit val method: Method[SetGameScore, Either[Boolean, TelegramMessage]] =
    new Method[SetGameScore, Either[Boolean, TelegramMessage]] {
      def name: String = "setGameScore"

      def encoder: Encoder[SetGameScore] = deriveEncoder[SetGameScore].snakeCase

      def decoder: Decoder[Either[Boolean, TelegramMessage]] =
        Decoder.decodeBoolean.either(TelegramMessage.telegramMessageDecoder)

      def attachments(request: SetGameScore): List[(String, InputFile)] = Nil
    }
} 
Example 61
Source File: PromoteChatMember.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.methods.chats

import canoe.marshalling.codecs._
import canoe.methods.Method
import canoe.models.{ChatId, InputFile}
import io.circe.generic.semiauto.deriveEncoder
import io.circe.{Decoder, Encoder}


final case class PromoteChatMember(chatId: ChatId,
                                   userId: Int,
                                   canChangeInfo: Option[Boolean] = None,
                                   canPostMessages: Option[Boolean] = None,
                                   canEditMessages: Option[Boolean] = None,
                                   canDeleteMessages: Option[Boolean] = None,
                                   canInviteUsers: Option[Boolean] = None,
                                   canRestrictMembers: Option[Boolean] = None,
                                   canPinMessages: Option[Boolean] = None,
                                   canPromoteMembers: Option[Boolean] = None)

object PromoteChatMember {

  implicit val method: Method[PromoteChatMember, Boolean] =
    new Method[PromoteChatMember, Boolean] {

      def name: String = "promoteChatMember"

      def encoder: Encoder[PromoteChatMember] = deriveEncoder[PromoteChatMember].snakeCase

      def decoder: Decoder[Boolean] = Decoder.decodeBoolean

      def attachments(request: PromoteChatMember): List[(String, InputFile)] = Nil
    }
} 
Example 62
Source File: UpdateType.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.models

import io.circe.Encoder


object UpdateType extends Enumeration {
  type UpdateType = Value
  val Message, EditedMessage, ChannelPost, EditedChannelPost, InlineQuery, ChosenInlineResult, CallbackQuery,
  ShippingQuery, PreCheckoutQuery = Value

  object Filters {
    val MessageUpdates: Seq[UpdateType] = Seq(Message, EditedMessage)
    val ChannelUpdates: Seq[UpdateType] = Seq(ChannelPost, EditedChannelPost)
    val InlineUpdates: Seq[UpdateType] = Seq(InlineQuery, ChosenInlineResult)
    val CallbackUpdates: Seq[UpdateType] = Seq(CallbackQuery)
    val PaymentUpdates: Seq[UpdateType] = Seq(ShippingQuery, PreCheckoutQuery)

    val AllUpdates: Seq[UpdateType] = UpdateType.values.toSeq
  }

  implicit val updatesTypeEncoder: Encoder[UpdateType] =
    Encoder[String].contramap[UpdateType](_.toString)
} 
Example 63
Source File: ChatId.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.models

import io.circe.Encoder
import io.circe.syntax._


sealed trait ChatId {
  def isChannel: Boolean
  def isChat: Boolean = !isChannel
}

object ChatId {
  implicit def fromChat[T](id: Long): ChatId = ChatId(id)
  implicit def fromChannel[T](username: String): ChatId = ChatId(username)

  final case class Chat(id: Long) extends ChatId {
    override def isChannel: Boolean = false
  }

  final case class Channel(id: String) extends ChatId {
    override def isChannel: Boolean = true
  }

  def apply(id: Long): ChatId = Chat(id)
  def apply(username: String): ChatId = Channel(username)

  implicit val chatIdEncoder: Encoder[ChatId] = Encoder.instance {
    case ChatId.Chat(chat)       => chat.asJson
    case ChatId.Channel(channel) => channel.asJson
  }
} 
Example 64
Source File: CodecsSpec.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.marshalling

import canoe.marshalling.codecs._
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder, Json}
import org.scalatest.freespec.AnyFreeSpec

class CodecsSpec extends AnyFreeSpec {
  case class Inner(longName: String)
  case class Outer(longInt: Int, inner: Inner)

  implicit val innerDecoder: Decoder[Inner] = deriveDecoder
  implicit val innerEncoder: Encoder[Inner] = deriveEncoder

  val decoder: Decoder[Outer] = deriveDecoder
  val encoder: Encoder[Outer] = deriveEncoder

  val instance: Outer = Outer(12, Inner("name"))

  "encoder works as expected" in {
    assert(allJsonKeys(encoder(instance)) == List("longInt", "inner", "longName"))
  }

  "snake case encoder encodes keys in snake_case manner" in {
    val encodedKeys = allJsonKeys(encoder.snakeCase(instance))

    assert(encodedKeys.map(_.snakeCase) == encodedKeys)
  }

  "encoded snake_case is decoded in camelCase" in {
    val encodedDecoded = decoder.camelCase.decodeJson(encoder.snakeCase(instance))

    assert(encodedDecoded.contains(instance))
  }

  def allJsonKeys(json: Json): List[String] =
    json.asObject.toList.flatMap(_.toList).flatMap {
      case (k, json) => k :: allJsonKeys(json)
    }
} 
Example 65
Source File: package.scala    From scalanda-v20   with MIT License 5 votes vote down vote up
package com.msilb.scalandav20.model

import java.time.Instant

import com.msilb.scalandav20.model.primitives.{DecimalNumber, InstrumentName}
import io.circe.generic.JsonCodec
import io.circe.generic.extras.semiauto.{deriveEnumerationDecoder, deriveEnumerationEncoder}
import io.circe.syntax._
import io.circe.{Decoder, Encoder}
import io.circe.java8.time._

package object pricing {

  type PriceValue = String

  sealed trait PricingStreamItem

  @JsonCodec
  case class PricingHeartbeat(`type`: String, time: Instant) extends PricingStreamItem

  sealed trait PriceStatus

  object PriceStatus {

    case object tradeable extends PriceStatus

    case object `non-tradeable` extends PriceStatus

    case object invalid extends PriceStatus

    implicit val decodePriceStatus: Decoder[PriceStatus] = deriveEnumerationDecoder
    implicit val encodePriceStatus: Encoder[PriceStatus] = deriveEnumerationEncoder
  }

  @JsonCodec
  case class PriceBucket(price: PriceValue, liquidity: Int)

  @JsonCodec
  case class QuoteHomeConversionFactors(positiveUnits: DecimalNumber, negativeUnits: DecimalNumber)

  @JsonCodec
  case class UnitsAvailableDetails(long: DecimalNumber, short: DecimalNumber)

  @JsonCodec
  case class UnitsAvailable(default: UnitsAvailableDetails,
                            reduceFirst: UnitsAvailableDetails,
                            reduceOnly: UnitsAvailableDetails,
                            openOnly: UnitsAvailableDetails)

  @JsonCodec
  case class Price(`type`: String,
                   instrument: InstrumentName,
                   time: Instant,
                   status: PriceStatus,
                   bids: Seq[PriceBucket],
                   asks: Seq[PriceBucket],
                   closeoutBid: PriceValue,
                   closeoutAsk: PriceValue,
                   quoteHomeConversionFactors: Option[QuoteHomeConversionFactors],
                   unitsAvailable: Option[UnitsAvailable]) extends PricingStreamItem

  object PricingStreamItem {
    implicit val decodePricingStreamItem: Decoder[PricingStreamItem] = Decoder.instance { c =>
      c.downField("type").as[String].flatMap {
        case "HEARTBEAT" => c.as[PricingHeartbeat]
        case _ => c.as[Price]
      }
    }
    implicit val encodePricingStreamItem: Encoder[PricingStreamItem] = Encoder.instance {
      case t: PricingHeartbeat => t.asJson
      case t: Price => t.asJson
    }
  }

} 
Example 66
Source File: QueriesEndpoints.scala    From endpoints4s   with MIT License 5 votes vote down vote up
package cqrs.queries

import java.util.UUID

import endpoints4s.algebra.{BuiltInErrors, MuxEndpoints, MuxRequest, circe}
import io.circe.{Decoder, Encoder, Json}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}


// TODO Enrich with failure information
//#mux-responses
sealed trait QueryResp
case class MaybeResource(value: Option[Meter]) extends QueryResp
case class ResourceList(value: List[Meter]) extends QueryResp
//#mux-responses

object QueryResp {
  implicit val queryDecoder: Decoder[QueryResp] = deriveDecoder
  implicit val queryEncoder: Encoder[QueryResp] = deriveEncoder
} 
Example 67
Source File: CommandsEndpoints.scala    From endpoints4s   with MIT License 5 votes vote down vote up
package cqrs.commands

import java.time.Instant
import java.util.UUID

import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.{Decoder, Encoder}

//#endpoints
import endpoints4s.algebra.Endpoints
import endpoints4s.algebra.circe.JsonEntitiesFromCodecs

trait CommandsEndpoints extends Endpoints with JsonEntitiesFromCodecs {

//#microservice-endpoint-description
  
case class AddRecord(meterId: UUID, date: Instant, value: BigDecimal) extends UpdateCommand

object Command {
  implicit val decoder: Decoder[Command] = deriveDecoder
  implicit val encoder: Encoder[Command] = deriveEncoder
}

case class StoredEvent(timestamp: Long, event: Event)

object StoredEvent {
  implicit val decoder: Decoder[StoredEvent] = deriveDecoder
  implicit val encoder: Encoder[StoredEvent] = deriveEncoder
}

sealed trait Event
case class MeterCreated(id: UUID, label: String) extends Event
case class RecordAdded(id: UUID, date: Instant, value: BigDecimal) extends Event

object Event {
  implicit val decoder: Decoder[Event] = deriveDecoder
  implicit val encoder: Encoder[Event] = deriveEncoder
} 
Example 68
Source File: ErrorCode.scala    From lsp4s   with Apache License 2.0 5 votes vote down vote up
package scala.meta.jsonrpc

import io.circe.Decoder
import io.circe.Encoder

sealed abstract class ErrorCode(val value: Int)
case object ErrorCode {
  case object ParseError extends ErrorCode(-32700)
  case object InvalidRequest extends ErrorCode(-32600)
  case object MethodNotFound extends ErrorCode(-32601)
  case object InvalidParams extends ErrorCode(-32602)
  case object InternalError extends ErrorCode(-32603)
  case object RequestCancelled extends ErrorCode(-32800)

  // Server error: -32000 to -32099
  case class Unknown(override val value: Int) extends ErrorCode(value)

  val builtin: Array[ErrorCode] = Array(
    ParseError,
    InvalidRequest,
    MethodNotFound,
    InvalidParams,
    InternalError,
    RequestCancelled
  )

  implicit val encoder: Encoder[ErrorCode] =
    Encoder.encodeInt.contramap(_.value)
  implicit val decoder: Decoder[ErrorCode] =
    Decoder.decodeInt.map(i => builtin.find(_.value == i).getOrElse(Unknown(i)))
} 
Example 69
Source File: Endpoint.scala    From lsp4s   with Apache License 2.0 5 votes vote down vote up
package scala.meta.jsonrpc

import io.circe.Decoder
import io.circe.Encoder
import monix.eval.Task
import monix.execution.Ack
import scala.concurrent.Future

class Endpoint[A: Decoder: Encoder, B: Decoder: Encoder](val method: String) {
  def encoderA: Encoder[A] = implicitly
  def decoderA: Decoder[A] = implicitly
  def encoderB: Encoder[B] = implicitly
  def decoderB: Decoder[B] = implicitly

  def request(request: A)(
      implicit client: JsonRpcClient
  ): Task[Either[Response.Error, B]] =
    client.request[A, B](method, request)
  def notify(
      notification: A
  )(implicit client: JsonRpcClient): Future[Ack] =
    client.notify[A](method, notification)
}

object Endpoint {
  def request[A: Decoder: Encoder, B: Decoder: Encoder](
      method: String
  ): Endpoint[A, B] =
    new Endpoint(method)
  def notification[A: Decoder: Encoder](method: String): Endpoint[A, Unit] =
    new Endpoint(method)
} 
Example 70
Source File: RequestId.scala    From lsp4s   with Apache License 2.0 5 votes vote down vote up
package scala.meta.jsonrpc

import io.circe.Json
import io.circe.Decoder
import io.circe.Encoder

sealed trait RequestId
object RequestId {
  def apply(n: Int): RequestId.String =
    RequestId.String(Json.fromString(n.toString))
  implicit val decoder: Decoder[RequestId] = Decoder.decodeJson.map {
    case s if s.isString => RequestId.String(s)
    case n if n.isNumber => RequestId.Number(n)
    case n if n.isNull => RequestId.Null
  }
  implicit val encoder: Encoder[RequestId] = Encoder.encodeJson.contramap {
    case RequestId.Number(v) => v
    case RequestId.String(v) => v
    case RequestId.Null => Json.Null
  }
  // implicit val encoder: Decoder =
  case class Number(value: Json) extends RequestId
  case class String(value: Json) extends RequestId
  case object Null extends RequestId
} 
Example 71
Source File: JsonRpcClient.scala    From lsp4s   with Apache License 2.0 5 votes vote down vote up
package scala.meta.jsonrpc

import scala.concurrent.Future
import io.circe.Decoder
import io.circe.Encoder
import monix.eval.Task
import monix.execution.Ack

trait JsonRpcClient {
  final def notify[A](
      endpoint: Endpoint[A, Unit],
      notification: A
  ): Future[Ack] = notify[A](endpoint.method, notification)(endpoint.encoderA)
  def notify[A: Encoder](method: String, notification: A): Future[Ack]
  def serverRespond(response: Response): Future[Ack]
  def clientRespond(response: Response): Unit
  final def request[A, B](
      endpoint: Endpoint[A, B],
      req: A
  ): Task[Either[Response.Error, B]] =
    request[A, B](endpoint.method, req)(endpoint.encoderA, endpoint.decoderB)
  def request[A: Encoder, B: Decoder](
      method: String,
      request: A
  ): Task[Either[Response.Error, B]]
}

object JsonRpcClient {
  val empty: JsonRpcClient = new JsonRpcClient {
    override def notify[A: Encoder](
        method: String,
        notification: A
    ): Future[Ack] = Ack.Continue
    override def serverRespond(response: Response): Future[Ack] = Ack.Continue
    override def clientRespond(response: Response): Unit = ()
    override def request[A: Encoder, B: Decoder](
        method: String,
        request: A
    ): Task[Either[Response.Error, B]] = Task.never
  }
} 
Example 72
Source File: LanguageClient.scala    From lsp4s   with Apache License 2.0 5 votes vote down vote up
package scala.meta.jsonrpc

import cats.syntax.either._
import io.circe.Decoder
import io.circe.Encoder
import io.circe.syntax._
import java.io.OutputStream
import java.nio.ByteBuffer
import monix.eval.Callback
import monix.eval.Task
import monix.execution.Ack
import monix.execution.Cancelable
import monix.execution.atomic.Atomic
import monix.execution.atomic.AtomicInt
import monix.reactive.Observer
import scala.collection.concurrent.TrieMap
import scala.concurrent.Future
import scala.concurrent.duration.Duration
import MonixEnrichments._
import scribe.LoggerSupport

class LanguageClient(out: Observer[ByteBuffer], logger: LoggerSupport)
    extends JsonRpcClient {
  def this(out: OutputStream, logger: LoggerSupport) =
    this(Observer.fromOutputStream(out, logger), logger)
  private val writer = new MessageWriter(out, logger)
  private val counter: AtomicInt = Atomic(1)
  private val activeServerRequests =
    TrieMap.empty[RequestId, Callback[Response]]
  def notify[A: Encoder](method: String, notification: A): Future[Ack] =
    writer.write(Notification(method, Some(notification.asJson)))
  def serverRespond(response: Response): Future[Ack] = response match {
    case Response.Empty => Ack.Continue
    case x: Response.Success => writer.write(x)
    case x: Response.Error =>
      logger.error(s"Response error: $x")
      writer.write(x)
  }
  def clientRespond(response: Response): Unit =
    for {
      id <- response match {
        case Response.Empty => None
        case Response.Success(_, requestId) => Some(requestId)
        case Response.Error(_, requestId) => Some(requestId)
      }
      callback <- activeServerRequests.get(id).orElse {
        logger.error(s"Response to unknown request: $response")
        None
      }
    } {
      activeServerRequests.remove(id)
      callback.onSuccess(response)
    }

  def request[A: Encoder, B: Decoder](
      method: String,
      request: A
  ): Task[Either[Response.Error, B]] = {
    val nextId = RequestId(counter.incrementAndGet())
    val response = Task.create[Response] { (out, cb) =>
      val scheduled = out.scheduleOnce(Duration(0, "s")) {
        val json = Request(method, Some(request.asJson), nextId)
        activeServerRequests.put(nextId, cb)
        writer.write(json)
      }
      Cancelable { () =>
        scheduled.cancel()
        this.notify("$/cancelRequest", CancelParams(nextId.value))
      }
    }
    response.map {
      case Response.Empty =>
        Left(
          Response.invalidParams(
            s"Got empty response for request $request",
            nextId
          )
        )
      case err: Response.Error =>
        Left(err)
      case Response.Success(result, _) =>
        result.as[B].leftMap { err =>
          Response.invalidParams(err.toString, nextId)
        }
    }
  }
}

object LanguageClient {
  def fromOutputStream(out: OutputStream, logger: LoggerSupport) =
    new LanguageClient(Observer.fromOutputStream(out, logger), logger)
} 
Example 73
Source File: Message.scala    From lsp4s   with Apache License 2.0 5 votes vote down vote up
package scala.meta.jsonrpc

import monix.eval.Task
import io.circe.Json
import io.circe.Decoder
import io.circe.Encoder
import io.circe.JsonObject
import io.circe.derivation.annotations.JsonCodec
import io.circe.syntax._

import cats.syntax.either._

sealed trait Message
object Message {
  implicit val encoder: Encoder[Message] = new Encoder[Message] {
    override def apply(a: Message): Json = {
      val json = a match {
        case r: Request => r.asJson
        case r: Notification => r.asJson
        case r: Response => r.asJson
      }
      json.mapObject(_.add("jsonrpc", "2.0".asJson))
    }
  }
  implicit val decoder: Decoder[Message] =
    Decoder.decodeJsonObject.emap { obj =>
      val json = Json.fromJsonObject(obj)
      val result =
        if (obj.contains("id"))
          if (obj.contains("error")) json.as[Response.Error]
          else if (obj.contains("result")) json.as[Response.Success]
          else json.as[Request]
        else json.as[Notification]
      result.leftMap(_.toString)
    }
}

@JsonCodec case class Request(
    method: String,
    params: Option[Json],
    id: RequestId
) extends Message {
  def toError(code: ErrorCode, message: String): Response =
    Response.error(ErrorObject(code, message, None), id)
}

@JsonCodec case class Notification(method: String, params: Option[Json])
    extends Message

sealed trait Response extends Message {
  def isSuccess: Boolean = this.isInstanceOf[Response.Success]
}
object Response {
  implicit val encoderResponse: Encoder[Response] = new Encoder[Response] {
    override def apply(a: Response): Json = a match {
      case r: Response.Success => r.asJson
      case r: Response.Error => r.asJson
      case Response.Empty => JsonObject.empty.asJson
    }
  }
  @JsonCodec case class Success(result: Json, id: RequestId) extends Response
  @JsonCodec case class Error(error: ErrorObject, id: RequestId)
      extends Response
  case object Empty extends Response
  def empty: Response = Empty
  def ok(result: Json, id: RequestId): Response =
    success(result, id)
  def okAsync[T](value: T): Task[Either[Response.Error, T]] =
    Task(Right(value))
  def success(result: Json, id: RequestId): Response =
    Success(result, id)
  def error(error: ErrorObject, id: RequestId): Response.Error =
    Error(error, id)
  def internalError(message: String): Response.Error =
    internalError(message, RequestId.Null)
  def internalError(message: String, id: RequestId): Response.Error =
    Error(ErrorObject(ErrorCode.InternalError, message, None), id)
  def invalidParams(message: String): Response.Error =
    invalidParams(message, RequestId.Null)
  def invalidParams(message: String, id: RequestId): Response.Error =
    Error(ErrorObject(ErrorCode.InvalidParams, message, None), id)
  def invalidRequest(message: String): Response.Error =
    Error(
      ErrorObject(ErrorCode.InvalidRequest, message, None),
      RequestId.Null
    )
  def cancelled(id: Json): Response.Error =
    Error(
      ErrorObject(ErrorCode.RequestCancelled, "", None),
      id.as[RequestId].getOrElse(RequestId.Null)
    )
  def parseError(message: String): Response.Error =
    Error(ErrorObject(ErrorCode.ParseError, message, None), RequestId.Null)
  def methodNotFound(message: String, id: RequestId): Response.Error =
    Error(ErrorObject(ErrorCode.MethodNotFound, message, None), id)
} 
Example 74
Source File: Json.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.bitbucketserver.http4s

import cats.data.NonEmptyList
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.{Decoder, Encoder}
import org.http4s.Uri
import org.scalasteward.core.git.Sha1
import org.scalasteward.core.vcs.data.PullRequestState

object Json {
  case class Page[A](values: List[A])

  case class Repo(id: Int, name: String, forkable: Boolean, project: Project, links: Links)

  case class Project(key: String)

  type Links = Map[String, NonEmptyList[Link]]

  case class Link(href: Uri, name: Option[String])

  case class PR(title: String, state: PullRequestState, links: Links)

  case class NewPR(
      title: String,
      description: String,
      state: PullRequestState,
      open: Boolean,
      closed: Boolean,
      fromRef: Ref,
      toRef: Ref,
      locked: Boolean,
      reviewers: List[Reviewer]
  )

  case class Ref(id: String, repository: Repository)

  case class Repository(slug: String, project: Project)

  case class Condition(reviewers: List[DefaultReviewer])

  case class DefaultReviewer(name: String)

  case class Reviewer(user: User)

  case class User(name: String)

  case class Branches(values: NonEmptyList[Branch])

  case class Branch(id: String, latestCommit: Sha1)

  implicit def pageDecode[A: Decoder]: Decoder[Page[A]] = deriveDecoder
  implicit val repoDecode: Decoder[Repo] = deriveDecoder
  implicit val projectDecode: Decoder[Project] = deriveDecoder
  implicit val linkDecoder: Decoder[Link] = deriveDecoder
  implicit val uriDecoder: Decoder[Uri] = Decoder.decodeString.map(Uri.unsafeFromString)
  implicit val prDecoder: Decoder[PR] = deriveDecoder
  implicit val reviewerDecoder: Decoder[Reviewer] = deriveDecoder
  implicit val userDecoder: Decoder[User] = deriveDecoder
  implicit val defaultReviewerDecoder: Decoder[DefaultReviewer] = deriveDecoder
  implicit val conditionDecoder: Decoder[Condition] = deriveDecoder
  implicit val branchDecoder: Decoder[Branch] = deriveDecoder
  implicit val branchesDecoder: Decoder[Branches] = deriveDecoder

  implicit val encodeNewPR: Encoder[NewPR] = deriveEncoder
  implicit val encodeRef: Encoder[Ref] = deriveEncoder
  implicit val encodeRepository: Encoder[Repository] = deriveEncoder
  implicit val encodeProject: Encoder[Project] = deriveEncoder
  implicit val encodeReviewer: Encoder[Reviewer] = deriveEncoder
  implicit val encodeUser: Encoder[User] = deriveEncoder
} 
Example 75
Source File: Sha1.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.git

import cats.Eq
import cats.implicits._
import eu.timepit.refined.W
import eu.timepit.refined.api.{Refined, RefinedTypeOps}
import eu.timepit.refined.boolean.{And, Or}
import eu.timepit.refined.char.Digit
import eu.timepit.refined.collection.{Forall, Size}
import eu.timepit.refined.generic.Equal
import eu.timepit.refined.numeric.Interval
import io.circe.refined._
import io.circe.{Decoder, Encoder}
import org.scalasteward.core.git.Sha1.HexString

final case class Sha1(value: HexString)

object Sha1 {
  type HexDigit = Digit Or Interval.Closed[W.`'a'`.T, W.`'f'`.T]
  type HexString = String Refined (Forall[HexDigit] And Size[Equal[W.`40`.T]])
  object HexString extends RefinedTypeOps[HexString, String]

  def from(s: String): Either[Throwable, Sha1] =
    HexString.from(s).bimap(new Throwable(_), Sha1.apply)

  implicit val sha1Eq: Eq[Sha1] =
    Eq.by(_.value.value)

  implicit val sha1Decoder: Decoder[Sha1] =
    Decoder[HexString].map(Sha1.apply)

  implicit val sha1Encoder: Encoder[Sha1] =
    Encoder[HexString].contramap(_.value)
} 
Example 76
Source File: UpdatePattern.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.repoconfig

import cats.implicits._
import io.circe.generic.semiauto._
import io.circe.{Decoder, Encoder, HCursor}
import org.scalasteward.core.data.{GroupId, Update}

final case class UpdatePattern(
    groupId: GroupId,
    artifactId: Option[String],
    version: Option[UpdatePattern.Version]
)

object UpdatePattern {
  final case class MatchResult(
      byArtifactId: List[UpdatePattern],
      filteredVersions: List[String]
  )

  final case class Version(prefix: Option[String], suffix: Option[String]) {
    def matches(version: String): Boolean =
      suffix.forall(version.endsWith) && prefix.forall(version.startsWith)
  }

  def findMatch(
      patterns: List[UpdatePattern],
      update: Update.Single,
      include: Boolean
  ): MatchResult = {
    val byGroupId = patterns.filter(_.groupId === update.groupId)
    val byArtifactId = byGroupId.filter(_.artifactId.forall(_ === update.artifactId.name))
    val filteredVersions = update.newerVersions.filter(newVersion =>
      byArtifactId.exists(_.version.forall(_.matches(newVersion))) === include
    )
    MatchResult(byArtifactId, filteredVersions)
  }

  implicit val updatePatternDecoder: Decoder[UpdatePattern] =
    deriveDecoder

  implicit val updatePatternEncoder: Encoder[UpdatePattern] =
    deriveEncoder

  implicit val updatePatternVersionDecoder: Decoder[Version] =
    Decoder[String]
      .map(s => Version(Some(s), None))
      .or((hCursor: HCursor) =>
        for {
          prefix <- hCursor.downField("prefix").as[Option[String]]
          suffix <- hCursor.downField("suffix").as[Option[String]]
        } yield Version(prefix, suffix)
      )

  implicit val updatePatternVersionEncoder: Encoder[Version] =
    deriveEncoder
} 
Example 77
Source File: PullRequestUpdateStrategy.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.repoconfig

import cats.Eq
import io.circe.{Decoder, Encoder}

sealed trait PullRequestUpdateStrategy {
  def name: String
}

object PullRequestUpdateStrategy {
  final case object Always extends PullRequestUpdateStrategy { val name = "always" }
  final case object OnConflicts extends PullRequestUpdateStrategy { val name = "on-conflicts" }
  final case object Never extends PullRequestUpdateStrategy { val name = "never" }

  val default: PullRequestUpdateStrategy = OnConflicts

  def fromString(value: String): PullRequestUpdateStrategy =
    value.trim.toLowerCase match {
      case "on-conflicts" => OnConflicts
      case "never"        => Never
      case "always"       => Always
      case _              => default
    }

  def fromBoolean(value: Boolean): PullRequestUpdateStrategy =
    if (value) OnConflicts
    else Never

  implicit val prUpdateStrategyDecoder: Decoder[PullRequestUpdateStrategy] =
    Decoder[Boolean].map(fromBoolean).or(Decoder[String].map(fromString))
  implicit val prUpdateStrategyEncoder: Encoder[PullRequestUpdateStrategy] =
    Encoder[String].contramap(_.name)
  implicit val eqPRUpdateStrategy: Eq[PullRequestUpdateStrategy] = Eq.fromUniversalEquals
} 
Example 78
Source File: PullRequestFrequency.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.repoconfig

import cats.Eq
import cats.implicits._
import cron4s.lib.javatime._
import io.circe.{Decoder, Encoder}
import org.scalasteward.core.repoconfig.PullRequestFrequency._
import org.scalasteward.core.util.Timestamp
import scala.concurrent.duration._

sealed trait PullRequestFrequency {
  def render: String

  def onSchedule(now: Timestamp): Boolean =
    this match {
      case CronExpr(expr) => expr.datePart.allOf(now.toLocalDateTime)
      case _              => true
    }

  def waitingTime(lastCreated: Timestamp, now: Timestamp): Option[FiniteDuration] = {
    val nextPossible = this match {
      case Asap           => None
      case Daily          => Some(lastCreated + 1.day)
      case Weekly         => Some(lastCreated + 7.days)
      case Monthly        => Some(lastCreated + 30.days)
      case CronExpr(expr) => expr.next(lastCreated.toLocalDateTime).map(Timestamp.fromLocalDateTime)
    }
    nextPossible.map(now.until).filter(_.length > 0)
  }
}

object PullRequestFrequency {
  case object Asap extends PullRequestFrequency { val render = "@asap" }
  case object Daily extends PullRequestFrequency { val render = "@daily" }
  case object Weekly extends PullRequestFrequency { val render = "@weekly" }
  case object Monthly extends PullRequestFrequency { val render = "@monthly" }
  final case class CronExpr(expr: cron4s.CronExpr) extends PullRequestFrequency {
    val render: String = expr.toString
  }

  val default: PullRequestFrequency = Asap

  def fromString(s: String): Either[String, PullRequestFrequency] =
    s.trim.toLowerCase match {
      case Asap.render    => Right(Asap)
      case Daily.render   => Right(Daily)
      case Weekly.render  => Right(Weekly)
      case Monthly.render => Right(Monthly)
      case other          =>
        // cron4s requires exactly 6 fields, but we also want to support the more
        // common format with 5 fields. Therefore we're prepending the "seconds"
        // field ourselves if parsing the original string fails.
        parseCron4s(other).orElse(parseCron4s("0 " + other)).leftMap(_.toString).map(CronExpr.apply)
    }

  private def parseCron4s(s: String): Either[Throwable, cron4s.CronExpr] =
    Either.catchNonFatal(cron4s.Cron.unsafeParse(s))

  implicit val pullRequestFrequencyEq: Eq[PullRequestFrequency] =
    Eq.fromUniversalEquals

  implicit val pullRequestFrequencyDecoder: Decoder[PullRequestFrequency] =
    Decoder[String].emap(fromString)

  implicit val pullRequestFrequencyEncoder: Encoder[PullRequestFrequency] =
    Encoder[String].contramap(_.render)
} 
Example 79
Source File: UpdatesConfig.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.repoconfig

import eu.timepit.refined.types.numeric.PosInt
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto._
import io.circe.refined._
import io.circe.{Decoder, Encoder}
import org.scalasteward.core.data.Update
import org.scalasteward.core.update.FilterAlg.{
  FilterResult,
  IgnoredByConfig,
  NotAllowedByConfig,
  VersionPinnedByConfig
}
import org.scalasteward.core.util.Nel

final case class UpdatesConfig(
    pin: List[UpdatePattern] = List.empty,
    allow: List[UpdatePattern] = List.empty,
    ignore: List[UpdatePattern] = List.empty,
    limit: Option[PosInt] = None,
    includeScala: Option[Boolean] = None,
    fileExtensions: List[String] = List.empty
) {
  def keep(update: Update.Single): FilterResult =
    isAllowed(update).flatMap(isPinned).flatMap(isIgnored)

  def fileExtensionsOrDefault: Set[String] =
    if (fileExtensions.isEmpty)
      UpdatesConfig.defaultFileExtensions
    else
      fileExtensions.toSet

  private def isAllowed(update: Update.Single): FilterResult = {
    val m = UpdatePattern.findMatch(allow, update, include = true)
    if (m.filteredVersions.nonEmpty)
      Right(update.copy(newerVersions = Nel.fromListUnsafe(m.filteredVersions)))
    else if (allow.isEmpty)
      Right(update)
    else Left(NotAllowedByConfig(update))
  }

  private def isPinned(update: Update.Single): FilterResult = {
    val m = UpdatePattern.findMatch(pin, update, include = true)
    if (m.filteredVersions.nonEmpty)
      Right(update.copy(newerVersions = Nel.fromListUnsafe(m.filteredVersions)))
    else if (m.byArtifactId.isEmpty)
      Right(update)
    else Left(VersionPinnedByConfig(update))
  }

  private def isIgnored(update: Update.Single): FilterResult = {
    val m = UpdatePattern.findMatch(ignore, update, include = false)
    if (m.filteredVersions.nonEmpty)
      Right(update.copy(newerVersions = Nel.fromListUnsafe(m.filteredVersions)))
    else
      Left(IgnoredByConfig(update))
  }
}

object UpdatesConfig {
  implicit val customConfig: Configuration =
    Configuration.default.withDefaults

  implicit val updatesConfigDecoder: Decoder[UpdatesConfig] =
    deriveConfiguredDecoder

  implicit val updatesConfigEncoder: Encoder[UpdatesConfig] =
    deriveConfiguredEncoder

  val defaultIncludeScala: Boolean = false

  val defaultFileExtensions: Set[String] =
    Set(".scala", ".sbt", ".sbt.shared", ".sc", ".yml", "pom.xml")

  // prevent IntelliJ from removing the import of io.circe.refined._
  locally(refinedDecoder: Decoder[PosInt])
} 
Example 80
Source File: Scope.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.data

import cats.implicits._
import cats.{Applicative, Eval, Order, Traverse}
import io.circe.generic.semiauto.deriveCodec
import io.circe.{Codec, Decoder, Encoder}


final case class Scope[A](value: A, resolvers: List[Resolver])

object Scope {
  type Dependency = Scope[org.scalasteward.core.data.Dependency]
  type Dependencies = Scope[List[org.scalasteward.core.data.Dependency]]

  implicit def scopeTraverse: Traverse[Scope] =
    new Traverse[Scope] {
      override def traverse[G[_]: Applicative, A, B](fa: Scope[A])(f: A => G[B]): G[Scope[B]] =
        f(fa.value).map(b => fa.copy(value = b))

      override def foldLeft[A, B](fa: Scope[A], b: B)(f: (B, A) => B): B =
        f(b, fa.value)

      override def foldRight[A, B](fa: Scope[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
        f(fa.value, lb)
    }

  implicit def scopeCodec[A: Decoder: Encoder]: Codec[Scope[A]] =
    deriveCodec

  implicit def scopeOrder[A: Order]: Order[Scope[A]] =
    Order.by((scope: Scope[A]) => (scope.value, scope.resolvers))
} 
Example 81
Source File: JsonKeyValueStore.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.persistence

import better.files.File
import cats.Monad
import cats.implicits._
import io.chrisdavenport.log4cats.Logger
import io.circe.parser.decode
import io.circe.syntax._
import io.circe.{Decoder, Encoder, KeyEncoder}
import org.scalasteward.core.io.{FileAlg, WorkspaceAlg}

final class JsonKeyValueStore[F[_], K, V](
    name: String,
    schemaVersion: String,
    maybePrefix: Option[String] = None
)(implicit
    fileAlg: FileAlg[F],
    keyEncoder: KeyEncoder[K],
    logger: Logger[F],
    valueDecoder: Decoder[V],
    valueEncoder: Encoder[V],
    workspaceAlg: WorkspaceAlg[F],
    F: Monad[F]
) extends KeyValueStore[F, K, V] {
  override def get(key: K): F[Option[V]] =
    jsonFile(key).flatMap { file =>
      fileAlg.readFile(file).flatMap {
        case Some(content) =>
          decode[Option[V]](content) match {
            case Right(maybeValue) => F.pure(maybeValue)
            case Left(error) =>
              logger.error(error)(s"Failed to parse or decode JSON from $file").as(Option.empty[V])
          }
        case None => F.pure(Option.empty[V])
      }
    }

  override def put(key: K, value: V): F[Unit] =
    write(key, Some(value))

  override def modifyF(key: K)(f: Option[V] => F[Option[V]]): F[Option[V]] =
    get(key).flatMap(maybeValue => f(maybeValue).flatTap(write(key, _)))

  private def jsonFile(key: K): F[File] = {
    val keyPath = maybePrefix.fold("")(_ + "/") + keyEncoder(key)
    workspaceAlg.rootDir.map(_ / "store" / name / s"v$schemaVersion" / keyPath / s"$name.json")
  }

  private def write(key: K, value: Option[V]): F[Unit] =
    jsonFile(key).flatMap(fileAlg.writeFile(_, value.asJson.toString))
} 
Example 82
Source File: PullRequestState.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.vcs.data

import cats.Eq
import io.circe.{Decoder, Encoder}

sealed trait PullRequestState

object PullRequestState {
  case object Open extends PullRequestState
  case object Closed extends PullRequestState

  implicit val pullRequestStateEq: Eq[PullRequestState] =
    Eq.fromUniversalEquals

  implicit val pullRequestStateDecoder: Decoder[PullRequestState] =
    Decoder[String].emap {
      _.toLowerCase match {
        case "open" | "opened"                => Right(Open)
        case "closed" | "merged" | "declined" => Right(Closed)
        case unknown                          => Left(s"Unexpected string '$unknown'")
      }
    }

  implicit val pullRequestStateEncoder: Encoder[PullRequestState] =
    Encoder[String].contramap {
      case Open   => "open"
      case Closed => "closed"
    }
} 
Example 83
Source File: CreatePullRequestRequest.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.bitbucket.http4s

import io.circe.{Encoder, Json}
import org.scalasteward.core.git.Branch
import org.scalasteward.core.vcs.data.Repo

private[http4s] case class CreatePullRequestRequest(
    title: String,
    sourceBranch: Branch,
    sourceRepo: Repo,
    destinationBranch: Branch,
    description: String
)

private[http4s] object CreatePullRequestRequest {
  implicit val encoder: Encoder[CreatePullRequestRequest] = Encoder.instance { d =>
    Json.obj(
      ("title", Json.fromString(d.title)),
      (
        "source",
        Json.obj(
          ("branch", Json.obj(("name", Json.fromString(d.sourceBranch.name)))),
          (
            "repository",
            Json.obj(("full_name", Json.fromString(s"${d.sourceRepo.owner}/${d.sourceRepo.repo}")))
          )
        )
      ),
      ("description", Json.fromString(d.description)),
      (
        "destination",
        Json.obj(
          ("branch", Json.obj(("name", Json.fromString(d.destinationBranch.name))))
        )
      )
    )
  }
} 
Example 84
Source File: HttpJsonClient.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.util

import cats.effect.Sync
import cats.implicits._
import io.circe.{Decoder, Encoder}
import org.http4s.Method.{GET, POST}
import org.http4s.circe.{jsonEncoderOf, jsonOf}
import org.http4s.client.Client
import org.http4s._
import scala.util.control.NoStackTrace

final class HttpJsonClient[F[_]: Sync](implicit
    client: Client[F]
) {
  type ModReq = Request[F] => F[Request[F]]

  def get[A: Decoder](uri: Uri, modify: ModReq): F[A] =
    request[A](GET, uri, modify)

  def post[A: Decoder](uri: Uri, modify: ModReq): F[A] =
    request[A](POST, uri, modify)

  def postWithBody[A: Decoder, B: Encoder](uri: Uri, body: B, modify: ModReq): F[A] =
    post[A](uri, modify.compose(_.withEntity(body)(jsonEncoderOf[F, B])))

  private def request[A: Decoder](method: Method, uri: Uri, modify: ModReq): F[A] =
    client.expectOr[A](modify(Request[F](method, uri)))(resp =>
      toUnexpectedResponse(uri, method, resp)
    )(jsonOf[F, A].transform(_.leftMap(failure => JsonParseError(uri, method, failure))))

  private def toUnexpectedResponse(
      uri: Uri,
      method: Method,
      response: Response[F]
  ): F[Throwable] = {
    val body = response.body.through(fs2.text.utf8Decode).compile.string
    body.map(UnexpectedResponse(uri, method, response.headers, response.status, _))
  }
}

final case class JsonParseError(
    uri: Uri,
    method: Method,
    underlying: DecodeFailure
) extends DecodeFailure {
  val message = s"uri: $uri\nmethod: $method\nmessage: ${underlying.message}"
  override def cause: Option[Throwable] = underlying.some
  override def toHttpResponse[F[_]](httpVersion: HttpVersion): Response[F] =
    underlying.toHttpResponse(httpVersion)
}

final case class UnexpectedResponse(
    uri: Uri,
    method: Method,
    headers: Headers,
    status: Status,
    body: String
) extends RuntimeException
    with NoStackTrace {
  override def getMessage: String =
    s"uri: $uri\nmethod: $method\nstatus: $status\nheaders: $headers\nbody: $body"
} 
Example 85
Source File: VariableAliasing.scala    From openlaw-core   with Apache License 2.0 5 votes vote down vote up
package org.adridadou.openlaw.parser.template

import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import org.adridadou.openlaw.OpenlawValue
import org.adridadou.openlaw.parser.template.variableTypes.VariableType
import org.adridadou.openlaw.parser.template.expressions.Expression
import org.adridadou.openlaw.result.{Result, Success}

object VariableAliasing {
  implicit val variableAliasingEnc: Encoder[VariableAliasing] = deriveEncoder
  implicit val variableAliasingDec: Decoder[VariableAliasing] = deriveDecoder
}

final case class VariableAliasing(name: VariableName, expr: Expression)
    extends Expression
    with TemplatePart {
  def validate(executionResult: TemplateExecutionResult): Result[Unit] =
    if (name.isAnonymous) {
      Success.unit
    } else {
      expr.validate(executionResult)
    }

  override def expressionType(
      executionResult: TemplateExecutionResult
  ): Result[VariableType] =
    expr.expressionType(executionResult)

  override def evaluate(
      executionResult: TemplateExecutionResult
  ): Result[Option[OpenlawValue]] =
    expr.evaluate(executionResult)

  override def variables(
      executionResult: TemplateExecutionResult
  ): Result[List[VariableName]] =
    expr.variables(executionResult)

  override def missingInput(
      executionResult: TemplateExecutionResult
  ): Result[List[VariableName]] =
    expr.missingInput(executionResult)
} 
Example 86
Source File: SectionType.scala    From openlaw-core   with Apache License 2.0 5 votes vote down vote up
package org.adridadou.openlaw.parser.template.variableTypes

import cats.implicits._
import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.parser.decode
import org.adridadou.openlaw.{OpenlawNativeValue, OpenlawString, OpenlawValue}
import org.adridadou.openlaw.parser.template.formatters.Formatter
import org.adridadou.openlaw.parser.template._
import org.adridadou.openlaw.parser.template.expressions.Expression
import org.adridadou.openlaw.result.{Failure, FailureException, Result, Success}

final case class SectionInfo(
    name: Option[String],
    numbering: String,
    value: String
) extends OpenlawNativeValue

case object SectionType
    extends VariableType(name = "Section")
    with NoShowInFormButRender {

  private implicit val enc: Encoder[SectionInfo] = deriveEncoder
  private implicit val dec: Decoder[SectionInfo] = deriveDecoder

  override def cast(
      value: String,
      executionResult: TemplateExecutionResult
  ): Result[SectionInfo] =
    decode[SectionInfo](value).leftMap(FailureException(_))

  override def internalFormat(value: OpenlawValue): Result[String] =
    value match {
      case SectionInfo(_, _, value) =>
        Success(value)
      case value =>
        VariableType.convert[OpenlawString](value)
    }

  override def defaultFormatter: Formatter = new SectionFormatter

  override def getTypeClass: Class[SectionInfo] = classOf[SectionInfo]

  override def construct(
      constructorParams: Parameter,
      executionResult: TemplateExecutionResult
  ): Result[Option[SectionInfo]] =
    constructorParams match {
      case Parameters(seq) =>
        val map = seq.toMap
        (for {
          numbering <- map.get("numbering")
          reference <- map.get("reference value")
        } yield for {
          numberingValue <- getOneValueConstant(numbering)
          referenceValue <- getOneValueConstant(reference)
        } yield SectionInfo(None, numberingValue, referenceValue)).sequence
      case _ =>
        Failure("""Section requires parameters, not a unique value or a list""")
    }

  def thisType: VariableType = SectionType

  private def getOneValueConstant(value: Parameter): Result[String] =
    value match {
      case OneValueParameter(StringConstant(v)) =>
        Success(v)
      case _ =>
        Failure("""Section requires "numbering" argument.""")
    }
}

class SectionFormatter extends Formatter {
  override def format(
      expression: Expression,
      value: OpenlawValue,
      executionResult: TemplateExecutionResult
  ): Result[List[AgreementElement]] =
    VariableType.convert[SectionInfo](value) map {
      case SectionInfo(_, _, referenceValue) =>
        List(FreeText(Text(referenceValue)))
    }
  override def missingValueFormat(
      expression: Expression
  ): List[AgreementElement] =
    List(FreeText(Text(s"[[$expression]]")))
  override def stringFormat(
      expression: Expression,
      value: OpenlawValue,
      executionResult: TemplateExecutionResult
  ): Result[String] =
    VariableType.convert[SectionInfo](value) map {
      case SectionInfo(_, _, referenceValue) =>
        referenceValue
    }
  override def missingValueString(
      expression: Expression
  ): String = ???
} 
Example 87
Source File: LinkType.scala    From openlaw-core   with Apache License 2.0 5 votes vote down vote up
package org.adridadou.openlaw.parser.template.variableTypes

import cats.implicits._
import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.parser.decode
import org.adridadou.openlaw.{OpenlawNativeValue, OpenlawString, OpenlawValue}
import org.adridadou.openlaw.parser.template.formatters.Formatter
import org.adridadou.openlaw.parser.template._
import org.adridadou.openlaw.parser.template.expressions.Expression
import org.adridadou.openlaw.result.{Failure, FailureException, Result, Success}

object LinkInfo {
  implicit val linkInfoEnc: Encoder[LinkInfo] = deriveEncoder
  implicit val linkInfoDec: Decoder[LinkInfo] = deriveDecoder
}

final case class LinkInfo(label: String, url: String) extends OpenlawNativeValue

case object LinkType
    extends VariableType(name = "Link")
    with NoShowInFormButRender {

  override def cast(
      value: String,
      executionResult: TemplateExecutionResult
  ): Result[LinkInfo] = decode[LinkInfo](value).leftMap(FailureException(_))

  override def internalFormat(value: OpenlawValue): Result[String] =
    VariableType.convert[OpenlawString](value)

  override def defaultFormatter: Formatter = new LinkFormatter

  override def getTypeClass: Class[LinkInfo] = classOf[LinkInfo]

  override def construct(
      constructorParams: Parameter,
      executionResult: TemplateExecutionResult
  ): Result[Option[LinkInfo]] =
    constructorParams match {
      case Parameters(seq) =>
        val map = seq.toMap
        for {
          label <- map.get("label").traverse(getOneValueConstant)
          url <- map.get("url").traverse(getOneValueConstant)
        } yield (label, url) mapN { LinkInfo(_, _) }
      case _ =>
        Failure("""Link requires parameters, not a unique value or a list""")
    }

  def thisType: VariableType = LinkType

  private def getOneValueConstant(value: Parameter): Result[String] =
    value match {
      case OneValueParameter(StringConstant(v)) =>
        Success(v)
      case _ =>
        Failure("""Link requires "label" argument.""")
    }
}

class LinkFormatter extends Formatter {
  override def format(
      expression: Expression,
      value: OpenlawValue,
      executionResult: TemplateExecutionResult
  ): Result[List[AgreementElement]] =
    VariableType.convert[LinkInfo](value) map {
      case LinkInfo(labelValue, urlValue) => List(Link(labelValue, urlValue))
    }

  override def missingValueFormat(
      expression: Expression
  ): List[AgreementElement] =
    List(FreeText(Text(s"[[$expression]]")))
  override def stringFormat(
      expression: Expression,
      value: OpenlawValue,
      executionResult: TemplateExecutionResult
  ): Result[String] =
    VariableType.convert[LinkInfo](value) map {
      case LinkInfo(labelValue, urlValue) => s"$labelValue[$urlValue]"
    }
} 
Example 88
Source File: ResumeContractOracle.scala    From openlaw-core   with Apache License 2.0 5 votes vote down vote up
package org.adridadou.openlaw.oracles

import java.time.Instant

import org.adridadou.openlaw.parser.template.variableTypes._
import org.adridadou.openlaw.vm._
import io.circe.{Decoder, Encoder}
import io.circe.syntax._
import io.circe.generic.semiauto._
import org.adridadou.openlaw.result.Result

import LocalDateTimeHelper._

final case class ResumeContractOracle(crypto: CryptoService)
    extends SignedActionOracle[ResumeExecutionEvent] {

  override def incoming(
      vm: OpenlawVm,
      event: ResumeExecutionEvent
  ): Result[OpenlawVm] =
    checkAction(
      vm,
      crypto,
      event,
      vm.contractDefinition.id(crypto).resumeContract(crypto)
    )

  override def shouldExecute(event: OpenlawVmEvent): Boolean = event match {
    case _: ResumeExecutionEvent => true
    case _                       => false
  }

  def processEvent(
      vm: OpenlawVm,
      event: ResumeExecutionEvent,
      name: String,
      identity: Identity
  ): Result[OpenlawVm] = {
    vm(UpdateExecutionStateCommand(ContractResumed, event))
  }
}

object ResumeExecutionEvent {
  implicit val resumeExecutionEventEnc: Encoder[ResumeExecutionEvent] =
    deriveEncoder
  implicit val resumeExecutionEventDec: Decoder[ResumeExecutionEvent] =
    deriveDecoder
}

final case class ResumeExecutionEvent(
    signature: EthereumSignature,
    signatureDate: Instant
) extends SignedActionEvent {
  override def typeIdentifier: String = className[ResumeExecutionEvent]
  override def serialize: String = this.asJson.noSpaces
} 
Example 89
Source File: StopContractOracle.scala    From openlaw-core   with Apache License 2.0 5 votes vote down vote up
package org.adridadou.openlaw.oracles

import java.time.Instant

import org.adridadou.openlaw.parser.template.variableTypes._
import org.adridadou.openlaw.vm._
import io.circe.{Decoder, Encoder}
import io.circe.syntax._
import io.circe.generic.semiauto._
import org.adridadou.openlaw.result.Result
import LocalDateTimeHelper._

final case class StopContractOracle(crypto: CryptoService)
    extends SignedActionOracle[StopExecutionEvent] {

  override def incoming(
      vm: OpenlawVm,
      event: StopExecutionEvent
  ): Result[OpenlawVm] =
    checkAction(
      vm,
      crypto,
      event,
      vm.contractDefinition.id(crypto).stopContract(crypto)
    )

  override def shouldExecute(event: OpenlawVmEvent): Boolean = event match {
    case _: StopExecutionEvent => true
    case _                     => false
  }

  def processEvent(
      vm: OpenlawVm,
      event: StopExecutionEvent,
      name: String,
      identity: Identity
  ): Result[OpenlawVm] = {
    vm(UpdateExecutionStateCommand(ContractStopped, event))
  }
}

object StopExecutionEvent {
  implicit val stopExecutionEventEnc: Encoder[StopExecutionEvent] =
    deriveEncoder
  implicit val stopExecutionEventDec: Decoder[StopExecutionEvent] =
    deriveDecoder
}

final case class StopExecutionEvent(
    signature: EthereumSignature,
    signatureDate: Instant
) extends SignedActionEvent {
  override def typeIdentifier: String = className[StopExecutionEvent]
  override def serialize: String = this.asJson.noSpaces
} 
Example 90
Source File: TemplateLoadOracle.scala    From openlaw-core   with Apache License 2.0 5 votes vote down vote up
package org.adridadou.openlaw.oracles

import org.adridadou.openlaw.parser.template.variableTypes.EthereumAddress
import org.adridadou.openlaw.values.TemplateId
import org.adridadou.openlaw.vm.{LoadTemplateCommand, OpenlawVm, OpenlawVmEvent}
import cats.implicits._
import TemplateId._
import io.circe.{Decoder, Encoder}
import io.circe.syntax._
import io.circe.generic.semiauto._
import org.adridadou.openlaw.result.{Failure, Result}

final case class TemplateLoadOracle(crypto: CryptoService)
    extends OpenlawOracle[LoadTemplate] {
  override def incoming(
      vm: OpenlawVm,
      event: LoadTemplate
  ): Result[OpenlawVm] = {
    val id = TemplateId(EthereumAddress.bytes2hex(crypto.sha256(event.content)))
    if (vm.contractDefinition.mainTemplate === id) {
      vm(LoadTemplateCommand(id, event))
    } else {
      vm.contractDefinition.templates.values.find(templateId =>
        templateId === id
      ) match {
        case Some(_) =>
          vm(LoadTemplateCommand(id, event))
        case None =>
          Failure(s"invalid template for contract ${vm.contractId}")
      }
    }
  }

  override def shouldExecute(event: OpenlawVmEvent): Boolean = event match {
    case _: LoadTemplate => true
    case _               => false
  }
}

object LoadTemplate {
  implicit val loadTemplateEnc: Encoder[LoadTemplate] = deriveEncoder
  implicit val loadTemplateDec: Decoder[LoadTemplate] = deriveDecoder
}

final case class LoadTemplate(content: String) extends OpenlawVmEvent {
  override def typeIdentifier: String = className[LoadTemplate]
  override def serialize: String = this.asJson.noSpaces
} 
Example 91
Source File: TemplateId.scala    From openlaw-core   with Apache License 2.0 5 votes vote down vote up
package org.adridadou.openlaw.values

import cats.Eq
import io.circe.{Decoder, Encoder, HCursor, Json, KeyDecoder, KeyEncoder}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import cats.implicits._
import org.adridadou.openlaw.parser.template.variableTypes.EthereumAddress

final case class TemplateId(id: String = "") extends Comparable[TemplateId] {
  override def toString: String = id

  override def compareTo(o: TemplateId): Int = id.compareTo(o.id)
}

object TemplateId {

  def apply(data: Array[Byte]): TemplateId =
    TemplateId(EthereumAddress.bytes2hex(data))

  implicit val templateIdEnc: Encoder[TemplateId] = deriveEncoder
  implicit val templateIdDec: Decoder[TemplateId] = deriveDecoder

  implicit val eq: Eq[TemplateId] = Eq.by(_.id)

}

final case class TemplateIdentifier(title: TemplateTitle, version: Int)

final case class TemplateTitle(originalTitle: String, title: String) {
  override def toString: String = title

  override def equals(obj: Any): Boolean = obj match {
    case other: TemplateTitle => this === other
    case _                    => false
  }

  override def hashCode(): Int = this.title.hashCode
}

object TemplateTitle {

  def apply(): TemplateTitle = TemplateTitle("")
  def apply(title: String): TemplateTitle =
    TemplateTitle(originalTitle = title, title = title.toLowerCase())

  implicit val eq: Eq[TemplateTitle] = (x: TemplateTitle, y: TemplateTitle) =>
    x.title === y.title
  implicit val templateTitleEnc: Encoder[TemplateTitle] = (a: TemplateTitle) =>
    Json.fromString(a.originalTitle)
  implicit val templateTitleDec: Decoder[TemplateTitle] = (c: HCursor) =>
    (for {
      title <- c.downField("title").as[String]
    } yield TemplateTitle(title)) match {
      case Right(title) => Right(title)
      case Left(_) =>
        c.as[String].map(TemplateTitle(_))
    }

  implicit val templateTitleKeyEnc: KeyEncoder[TemplateTitle] =
    (key: TemplateTitle) => key.title
  implicit val templateTitleKeyDec: KeyDecoder[TemplateTitle] = (key: String) =>
    Some(TemplateTitle(key))
} 
Example 92
Source File: ContractAccess.scala    From openlaw-core   with Apache License 2.0 5 votes vote down vote up
package org.adridadou.openlaw.values

import cats.Eq
import io.circe.{Decoder, Encoder, HCursor, Json}

sealed abstract class ContractAccess(val name: String)

case object ContractSignable extends ContractAccess("signable")
case object ContractNoAccess extends ContractAccess("noaccess")
case object ContractReadonly extends ContractAccess("readonly")
case object ContractEditable extends ContractAccess("editable")

object ContractAccess {

  def apply(name: String): ContractAccess = name match {
    case ContractReadonly.name => ContractReadonly
    case ContractNoAccess.name => ContractNoAccess
    case ContractSignable.name => ContractSignable
    case ContractEditable.name => ContractEditable
  }

  def unapply(arg: ContractAccess): String = arg.name

  implicit val accessDecoder: Decoder[ContractAccess] = (c: HCursor) => {
    for {
      name <- c.as[String]
    } yield ContractAccess(name)
  }
  implicit val accessEncoder: Encoder[ContractAccess] = (a: ContractAccess) =>
    Json.fromString(a.name)
  implicit val eqForContractAccess: Eq[ContractAccess] = Eq.fromUniversalEquals
} 
Example 93
Source File: ContractId.scala    From openlaw-core   with Apache License 2.0 5 votes vote down vote up
package org.adridadou.openlaw.values

import cats.Eq
import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import org.adridadou.openlaw.oracles.CryptoService
import org.adridadou.openlaw.parser.template.variableTypes.{
  EthereumAddress,
  EthereumData
}

@SerialVersionUID(7843732947346776640L)
final case class ContractId(id: String) {
  def stopContract(cryptoService: CryptoService): EthereumData =
    executionId("_stop_contract", cryptoService)
  def data: EthereumData = EthereumData(id)
  def resumeContract(cryptoService: CryptoService): EthereumData =
    executionId("_resume_contract", cryptoService)
  def executionId(command: String, crypto: CryptoService): EthereumData =
    EthereumData(id + EthereumData(crypto.sha256("_" + command)).toString)

  override def toString(): String = id
}

@SerialVersionUID(7843732947346776640L)
object ContractId {

  def apply(data: Array[Byte]): ContractId =
    ContractId(EthereumAddress.bytes2hex(data))

  implicit val contractIdEnc: Encoder[ContractId] = deriveEncoder
  implicit val contractIdDec: Decoder[ContractId] = deriveDecoder

  implicit val contractEq: Eq[ContractId] = Eq.fromUniversalEquals
} 
Example 94
Source File: GameManager.scala    From telegram   with Apache License 2.0 5 votes vote down vote up
package com.bot4s.telegram.api

import java.net.URLDecoder
import java.nio.charset.StandardCharsets
import java.util.Base64

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{Directive1, Route}
import com.bot4s.telegram.marshalling
import com.bot4s.telegram.methods.{GetGameHighScores, SetGameScore}
import com.bot4s.telegram.models.{CallbackQuery, ChatId, User}
import com.bot4s.telegram.future.BotExecutionContext
import io.circe.generic.extras.semiauto._
import io.circe.generic.semiauto.deriveDecoder
import io.circe.{Decoder, Encoder}

import scala.concurrent.Future
import scala.util.{Failure, Success}


case class Payload(
                    user            : User,
                    chatId          : Option[ChatId] = None,
                    messageId       : Option[Int] = None,
                    inlineMessageId : Option[String] = None,
                    gameManagerHost : String,
                    gameShortName   : String) {

  def toGetGameHighScores = GetGameHighScores(user.id, chatId, messageId, inlineMessageId)

  def base64Encode: String = {
    val payloadJson = marshalling.toJson[Payload](this)
    val encodedPayload = Base64.getEncoder.encodeToString(
      payloadJson.getBytes(StandardCharsets.UTF_8))

    encodedPayload
  }
}

object Payload {

  def base64Decode(encodedPayload: String): Payload = {
    val base64payload = URLDecoder.decode(encodedPayload, "UTF-8")
    val jsonPayload = new String(Base64.getDecoder.decode(base64payload),
      StandardCharsets.UTF_8)
    val payload = marshalling.fromJson[Payload](jsonPayload)

    payload
  }

  def forCallbackQuery(gameManagerHost: String)(implicit cbq: CallbackQuery): Payload = {
    Payload(
      cbq.from,
      cbq.message.map(_.source),
      cbq.message.map(_.messageId),
      cbq.inlineMessageId,
      gameManagerHost,
      cbq.gameShortName.get) // throws if not a game callback
  }

  import marshalling._
  implicit val payloadEncoder: Encoder[Payload] = deriveEncoder[Payload]
  implicit val payloadDecoder: Decoder[Payload] = deriveDecoder[Payload]
} 
Example 95
Source File: YetAnotherAkkaClient.scala    From telegram   with Apache License 2.0 5 votes vote down vote up
package com.bot4s.telegram.clients

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.marshalling.Marshal
import akka.http.scaladsl.model.Uri.Path
import akka.http.scaladsl.model._
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.Materializer
import akka.stream.scaladsl.{Sink, Source}
import cats.instances.future._
import com.bot4s.telegram.api.RequestHandler
import com.bot4s.telegram.methods.{Request, Response}
import io.circe.{Decoder, Encoder}
import slogging.StrictLogging
import com.bot4s.telegram.marshalling.responseDecoder

import scala.concurrent.{ExecutionContext, Future}

class YetAnotherAkkaClient(token: String, telegramHost: String = "api.telegram.org")
                          (implicit system: ActorSystem, materializer: Materializer, ec: ExecutionContext)
  extends RequestHandler[Future] with StrictLogging {

  private val flow = Http().outgoingConnectionHttps(telegramHost)

  import com.bot4s.telegram.marshalling.AkkaHttpMarshalling._

  override def sendRequest[R, T <: Request[_]](request: T)(implicit encT: Encoder[T], decR: Decoder[R]): Future[R] = {
    Source.fromFuture(
      Marshal(request).to[RequestEntity]
        .map {
          re =>
            HttpRequest(HttpMethods.POST, Uri(path = Path(s"/bot$token/" + request.methodName)), entity = re)
        })
      .via(flow)
      .mapAsync(1)(r => Unmarshal(r.entity).to[Response[R]])
      .runWith(Sink.head)
      .map(processApiResponse[R])
  }
} 
Example 96
Source File: AkkaHttpClient.scala    From telegram   with Apache License 2.0 5 votes vote down vote up
package com.bot4s.telegram.clients

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.marshalling._
import akka.http.scaladsl.model._
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.Materializer
import cats.instances.future._
import com.bot4s.telegram.api.RequestHandler
import com.bot4s.telegram.marshalling.AkkaHttpMarshalling
import com.bot4s.telegram.marshalling._
import com.bot4s.telegram.methods.{Request, Response}
import io.circe.{Decoder, Encoder}
import slogging.StrictLogging

import scala.concurrent.{ExecutionContext, Future}


class AkkaHttpClient(token: String, telegramHost: String = "api.telegram.org")
  (implicit system: ActorSystem, materializer: Materializer, ec: ExecutionContext)
  extends RequestHandler[Future] with StrictLogging {

  import AkkaHttpMarshalling._
  private val apiBaseUrl = s"https://$telegramHost/bot$token/"
  private val http = Http()

  override def sendRequest[R, T <: Request[_]](request: T)(implicit encT: Encoder[T], decR: Decoder[R]): Future[R] = {
    Marshal(request).to[RequestEntity]
      .map {
        re =>
          HttpRequest(HttpMethods.POST, Uri(apiBaseUrl + request.methodName), entity = re)
      }
      .flatMap(http.singleRequest(_))
      .flatMap(r => Unmarshal(r.entity).to[Response[R]])
      .map(t => processApiResponse[R](t))
  }
} 
Example 97
Source File: AkkaHttpMarshalling.scala    From telegram   with Apache License 2.0 5 votes vote down vote up
package com.bot4s.telegram.marshalling

import akka.http.scaladsl.marshalling.{Marshaller, Marshalling, ToEntityMarshaller}
import akka.http.scaladsl.model._
import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller}
import com.bot4s.telegram.marshalling
import com.bot4s.telegram.methods.{JsonRequest, MultipartRequest, Request}
import com.bot4s.telegram.models.{AkkaInputFile, InputFile}
import io.circe.{Decoder, Encoder}


object AkkaHttpMarshalling {

  implicit def camelCaseJsonUnmarshaller[R](implicit decR: Decoder[R]): FromEntityUnmarshaller[R] = {
    Unmarshaller
      .stringUnmarshaller
      .forContentTypes(ContentTypes.`application/json`)
      .map(marshalling.fromJson[R])
  }

  implicit def underscore_case_marshaller[T <: Request[_]](implicit encT: Encoder[T]): ToEntityMarshaller[T] = {
    Marshaller.strict {
      request => request match {
        // JSON-only request
        case r: JsonRequest[_] =>
          Marshalling.Opaque(() => HttpEntity(ContentTypes.`application/json`, marshalling.toJson(request)))

        // Request with multipart payload
        case r: MultipartRequest[_] =>
          val files = r.getFiles
          val parts = files.map {
            case (camelKey, inputFile) =>
              val key = CaseConversions.snakenize(camelKey)
              inputFile match {
                case InputFile.FileId(id) => Multipart.FormData.BodyPart(key, HttpEntity(id))

                case InputFile.Contents(filename, contents) =>
                  Multipart.FormData.BodyPart(key, HttpEntity(ContentTypes.`application/octet-stream`, contents),
                    Map("filename" -> filename))

                case InputFile.Path(path) =>
                  Multipart.FormData.BodyPart.fromPath(key, MediaTypes.`application/octet-stream`, path)

                case AkkaInputFile.ByteString(filename, bytes) =>
                  Multipart.FormData.BodyPart(key, HttpEntity(MediaTypes.`application/octet-stream`, bytes),
                    Map("filename" -> filename))

                case other =>
                  throw new RuntimeException(s"InputFile $other not supported")
              }
          }

          val fields = io.circe.parser.parse(marshalling.toJson(request)).fold(throw _, _.asObject.map {
            _.toMap.mapValues {
              json =>
                json.asString.getOrElse(marshalling.printer.pretty(json))
            }
          })

          val params = fields.getOrElse(Map())
          val paramParts = params.map { case (key, value) => Multipart.FormData.BodyPart(key, HttpEntity(value)) }

          Marshalling.Opaque(() => Multipart.FormData((parts ++ paramParts): _*).toEntity())
      }
    }
  }
} 
Example 98
Source File: SttpClient.scala    From telegram   with Apache License 2.0 5 votes vote down vote up
package com.bot4s.telegram.clients

import cats.MonadError
import cats.syntax.functor._
import com.bot4s.telegram.api.RequestHandler
import com.bot4s.telegram.marshalling.CaseConversions
import com.bot4s.telegram.methods.{JsonRequest, MultipartRequest, Response}
import com.softwaremill.sttp.{Request => _, Response => _, _}
import com.bot4s.telegram.marshalling
import com.bot4s.telegram.methods._
import com.bot4s.telegram.models.InputFile
import io.circe.parser.parse
import io.circe.{Decoder, Encoder}
import slogging.StrictLogging

import scala.concurrent.duration._


class SttpClient[F[_]](token: String, telegramHost: String = "api.telegram.org")
                      (implicit backend: SttpBackend[F, Nothing], monadError: MonadError[F, Throwable])
  extends RequestHandler[F]()(monadError) with StrictLogging {

  val readTimeout: Duration = 50.seconds

  private implicit def circeBodySerializer[B : Encoder]: BodySerializer[B] =
    b => StringBody(marshalling.toJson[B](b), "utf-8", Some(MediaTypes.Json))

  private def asJson[B : Decoder]: ResponseAs[B, Nothing] =
    asString("utf-8").map(s => marshalling.fromJson[B](s))

  private val apiBaseUrl = s"https://$telegramHost/bot$token/"

  override def sendRequest[R, T <: Request[_]](request: T)(implicit encT: Encoder[T], decR: Decoder[R]): F[R] = {
    val url = apiBaseUrl + request.methodName

    val sttpRequest: RequestT[Id, String, Nothing] = request match {
      case r: JsonRequest[_] =>
        sttp.post(uri"$url").body(request)

      case r: MultipartRequest[_] =>
        val files = r.getFiles

        val parts = files.map {
          case (camelKey, inputFile) =>
            val key = CaseConversions.snakenize(camelKey)
            inputFile match {
              case InputFile.FileId(id) => multipart(key, id)
              case InputFile.Contents(filename, contents) => multipart(key, contents).fileName(filename)
              //case InputFile.Path(path) => multipartFile(key, path)
              case other =>
                throw new RuntimeException(s"InputFile $other not supported")
            }
        }

        val fields = parse(marshalling.toJson(request)).fold(throw _, _.asObject.map {
          _.toMap.mapValues {
            json =>
              json.asString.getOrElse(marshalling.printer.pretty(json))
          }
        })

        val params = fields.getOrElse(Map())

        sttp.post(uri"$url?$params").multipartBody(parts)
    }

    import com.bot4s.telegram.marshalling.responseDecoder

    val response = sttpRequest
      .readTimeout(readTimeout)
      .parseResponseIf(_ => true) // Always parse response
      .response(asJson[Response[R]])
      .send[F]()

    response
      .map(_.unsafeBody)
      .map(processApiResponse[R])
  }
} 
Example 99
Source File: AutoAckConsumerDemo.scala    From fs2-rabbit   with Apache License 2.0 5 votes vote down vote up
package dev.profunktor.fs2rabbit.examples

import java.nio.charset.StandardCharsets.UTF_8

import cats.data.Kleisli
import cats.effect._
import cats.implicits._
import dev.profunktor.fs2rabbit.config.declaration.DeclarationQueueConfig
import dev.profunktor.fs2rabbit.interpreter.RabbitClient
import dev.profunktor.fs2rabbit.json.Fs2JsonEncoder
import dev.profunktor.fs2rabbit.model.AckResult.Ack
import dev.profunktor.fs2rabbit.model.AmqpFieldValue.{LongVal, StringVal}
import dev.profunktor.fs2rabbit.model._
import fs2.{Pipe, Pure, Stream}
import io.circe.Encoder

class AutoAckConsumerDemo[F[_]: Concurrent](R: RabbitClient[F]) {
  private val queueName    = QueueName("testQ")
  private val exchangeName = ExchangeName("testEX")
  private val routingKey   = RoutingKey("testRK")
  implicit val stringMessageEncoder =
    Kleisli[F, AmqpMessage[String], AmqpMessage[Array[Byte]]](s => s.copy(payload = s.payload.getBytes(UTF_8)).pure[F])

  def logPipe: Pipe[F, AmqpEnvelope[String], AckResult] = _.evalMap { amqpMsg =>
    putStrLn(s"Consumed: $amqpMsg").as(Ack(amqpMsg.deliveryTag))
  }

  val program: F[Unit] = R.createConnectionChannel.use { implicit channel =>
    for {
      _         <- R.declareQueue(DeclarationQueueConfig.default(queueName))
      _         <- R.declareExchange(exchangeName, ExchangeType.Topic)
      _         <- R.bindQueue(queueName, exchangeName, routingKey)
      publisher <- R.createPublisher[AmqpMessage[String]](exchangeName, routingKey)
      consumer  <- R.createAutoAckConsumer[String](queueName)
      _         <- new AutoAckFlow[F, String](consumer, logPipe, publisher).flow.compile.drain
    } yield ()
  }

}

class AutoAckFlow[F[_]: Concurrent, A](
    consumer: Stream[F, AmqpEnvelope[A]],
    logger: Pipe[F, AmqpEnvelope[A], AckResult],
    publisher: AmqpMessage[String] => F[Unit]
) {

  import io.circe.generic.auto._

  case class Address(number: Int, streetName: String)
  case class Person(id: Long, name: String, address: Address)

  private def jsonEncoder = new Fs2JsonEncoder

  def encoderPipe[T: Encoder]: Pipe[F, AmqpMessage[T], AmqpMessage[String]] =
    _.map(jsonEncoder.jsonEncode[T])

  val jsonPipe: Pipe[Pure, AmqpMessage[Person], AmqpMessage[String]] = _.map(jsonEncoder.jsonEncode[Person])

  val simpleMessage =
    AmqpMessage("Hey!", AmqpProperties(headers = Map("demoId" -> LongVal(123), "app" -> StringVal("fs2RabbitDemo"))))
  val classMessage = AmqpMessage(Person(1L, "Sherlock", Address(212, "Baker St")), AmqpProperties.empty)

  val flow: Stream[F, Unit] =
    Stream(
      Stream(simpleMessage).covary[F].evalMap(publisher),
      Stream(classMessage).covary[F].through(encoderPipe[Person]).evalMap(publisher),
      consumer.through(logger).through(_.evalMap(putStrLn(_)))
    ).parJoin(3)

} 
Example 100
Source File: package.scala    From sbt-kubeyml   with MIT License 5 votes vote down vote up
package kubeyml

import java.io.{File, PrintWriter}

import io.circe.Encoder
import io.circe.syntax._
import io.circe.yaml.syntax._

package object plugin {

  private[kubeyml] def writePlan[A](a: A, buildTarget: File, kind: String)(implicit encoder: Encoder[A]) = {
    val genTarget = new File(buildTarget, "kubeyml")
    genTarget.mkdirs()
    val file = new File(genTarget, s"${kind}.yml")
    val printWriter = new PrintWriter(file)
    try {
      printWriter.println(a.asJson.asYaml.spaces4)
    } finally {
      printWriter.close()
    }
  }

  private[kubeyml] def writePlansInSingle[A, B](a: A, b: B, buildTarget: File, kind: String)(implicit
                                              encoderA: Encoder[A], encoder: Encoder[B]
  ) = {
    val genTarget = new File(buildTarget, "kubeyml")
    genTarget.mkdirs()
    val file = new File(genTarget, s"${kind}.yml")
    val printWriter = new PrintWriter(file)
    try {
      printWriter.println(a.asJson.asYaml.spaces4)
      printWriter.println("---")
      printWriter.println(b.asJson.asYaml.spaces4)
    } finally {
      printWriter.close()
    }
  }
} 
Example 101
Source File: json_support.scala    From sbt-kubeyml   with MIT License 5 votes vote down vote up
package kubeyml.ingress

import io.circe.{Encoder, Json}
import io.circe.generic.auto._
import io.circe.syntax._
import kubeyml.protocol.json_support._

object json_support {

  private val defaultIngressParts: Json = Json.obj(
    "kind" -> "Ingress".asJson
  )

  implicit val apiVersionEncoder: Encoder[ApiVersion] = Encoder.instance(_.show.asJson)

  implicit val hostEncoder: Encoder[Host] = Encoder.encodeString.contramap(_.value)

  implicit val pathEncoder: Encoder[Path] = Encoder.instance {
    case Path(ServiceMapping(serviceName, servicePort), path) =>
      Json.obj(
        "backend" -> Json.obj(
          "serviceName" -> serviceName.asJson,
          "servicePort" -> servicePort.asJson
        ),
        "path" -> path.asJson
      )
  }

  private val httpRuleEncoder: Encoder[HttpRule] = Encoder.instance { httpRule =>
    Json.obj(
      "host" -> httpRule.host.asJson,
      "http" -> Json.obj("paths" -> httpRule.paths.asJson)
    )
  }

  implicit val ruleEncoder: Encoder[Rule] = Encoder.instance {
    case r: HttpRule => httpRuleEncoder(r)
  }

  private val customIngressEncoder: Encoder[CustomIngress] = Encoder.instance(
    custom =>
      Json.obj(
        "apiVersion" -> custom.apiVersion.asJson,
        "metadata" -> Json.obj(
          "annotations" -> custom.annotations.asJson,
          "name" -> custom.name.asJson,
          "namespace" -> custom.namespace.asJson
        ),
        "spec" -> custom.spec.asJson
      )
  )

  implicit val ingressEncoder: Encoder[Ingress] = Encoder.instance {
    case custom: CustomIngress =>
      defaultIngressParts deepMerge customIngressEncoder(custom)
  }

} 
Example 102
Source File: json_support.scala    From sbt-kubeyml   with MIT License 5 votes vote down vote up
package kubeyml.service

import io.circe.{Encoder, Json}
import io.circe.syntax._
import io.circe.generic.semiauto._
import kubeyml.protocol.json_support._

object json_support {

  implicit val serviceTypeEncoder: Encoder[ServiceType] = Encoder.encodeString.contramap {
    case NodePort => "NodePort"
  }

  implicit val selectorEncoder: Encoder[Selector] = Encoder.instance {
    case AppSelector(appName) =>
      Json.obj("app" -> appName.asJson)
  }

  implicit val networkProtocolEncoder: Encoder[NetworkProtocol] = Encoder.encodeString.contramap {
    case TCP => "TCP"
  }

  implicit val targetPortEncoder: Encoder[TargetPort] = Encoder.instance {
    case NamedTargetPort(name) =>
      name.asJson
    case NumberedTargetPort(num) =>
      num.asJson
  }

  implicit val portEncoder: Encoder[Port] = deriveEncoder

  implicit val specEncoder: Encoder[Spec] = deriveEncoder

  implicit val serviceEncoder: Encoder[Service] = Encoder.instance { service =>
    Json.obj(
      "kind" -> "Service".asJson,
      "apiVersion" -> "v1".asJson,
      "metadata" -> Json.obj(
        "name" -> service.name.asJson,
        "namespace" -> service.namespace.asJson
      ),
      "spec" -> service.spec.asJson
    )
  }
} 
Example 103
Source File: json_support.scala    From sbt-kubeyml   with MIT License 5 votes vote down vote up
package kubeyml.roles

import io.circe.{Encoder, Json}
import io.circe.generic.auto._
import io.circe.syntax._
object json_support {
  import kubeyml.protocol.json_support._

  implicit val verbsEncoder: Encoder[Verb] = Encoder.encodeString.contramap {
    case Verb.Get => "get"
    case Verb.Watch => "watch"
    case Verb.List => "list"
  }
  implicit val apiGroupEncoder: Encoder[ApiGroup] = Encoder.encodeString.contramap {
    case ApiGroup.Core => ""
  }
  implicit val resourceEncoder: Encoder[Resource] = Encoder.encodeString.contramap {
    case Pods => "pods"
  }

  implicit val roleEncoder: Encoder[Role] = Encoder.instance {
    case role =>
      Json.obj("metadata" -> role.metadata.asJson,
        "rules" -> role.rules.asJson,
        "kind" -> "Role".asJson,
        "apiVersion" -> "rbac.authorization.k8s.io/v1".asJson
      )
  }

  implicit val roleRefEncoder: Encoder[RoleRef] = Encoder.instance {
    case RoleRef(Role(RoleMetadata(name, _), _)) =>
      Json.obj(
        "kind" -> "Role".asJson,
        "name" -> name.asJson,
        "apiGroup" -> "rbac.authorization.k8s.io".asJson
      )
  }

  implicit val subjectEncoder: Encoder[Subject] = Encoder.instance {
    case UserSubject(serviceAccount, namespace) =>
      val identifier = s"system:serviceaccount:${namespace.value}:${serviceAccount.value}"
      Json.obj(
        "kind" -> "User".asJson,
        "name" -> identifier.asJson
      )
  }

  implicit val roleBindingEncoder: Encoder[RoleBinding] = Encoder.instance {
    case RoleBinding(metadata, subjects, roleRef) =>
      Json.obj(
        "kind" -> "RoleBinding".asJson,
        "apiVersion" -> "rbac.authorization.k8s.io/v1".asJson,
        "metadata" -> metadata.asJson,
        "subjects" -> subjects.asJson,
        "roleRef" -> roleRef.asJson
      )
  }

} 
Example 104
Source File: JobState.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.common

import io.circe.{Decoder, Encoder}

sealed trait JobState { self: Product =>
  def name: String =
    productPrefix.toLowerCase
}

object JobState {

  
  case object Success extends JobState {}

  val all: Set[JobState] =
    Set(Waiting, Scheduled, Running, Stuck, Failed, Cancelled, Success)
  val queued: Set[JobState]     = Set(Waiting, Scheduled, Stuck)
  val done: Set[JobState]       = Set(Failed, Cancelled, Success)
  val inProgress: Set[JobState] = Set(Scheduled, Running, Stuck)

  def parse(str: String): Either[String, JobState] =
    str.toLowerCase match {
      case "waiting"   => Right(Waiting)
      case "scheduled" => Right(Scheduled)
      case "running"   => Right(Running)
      case "stuck"     => Right(Stuck)
      case "failed"    => Right(Failed)
      case "cancelled" => Right(Cancelled)
      case "success"   => Right(Success)
      case _           => Left(s"Not a job state: $str")
    }

  def unsafe(str: String): JobState =
    parse(str).fold(sys.error, identity)

  def asString(state: JobState): String =
    state.name

  implicit val jobStateEncoder: Encoder[JobState] =
    Encoder.encodeString.contramap(_.name)

  implicit val jobStateDecoder: Decoder[JobState] =
    Decoder.decodeString.emap(JobState.parse)

} 
Example 105
Source File: NerTag.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.common

import io.circe.{Decoder, Encoder}

sealed trait NerTag { self: Product =>

  final def name: String =
    productPrefix.toLowerCase
}

object NerTag {

  case object Organization extends NerTag
  case object Person       extends NerTag
  case object Location     extends NerTag
  case object Misc         extends NerTag
  case object Email        extends NerTag
  case object Website      extends NerTag
  case object Date         extends NerTag

  val all: List[NerTag] = List(Organization, Person, Location)

  def fromString(str: String): Either[String, NerTag] =
    str.toLowerCase match {
      case "organization" => Right(Organization)
      case "person"       => Right(Person)
      case "location"     => Right(Location)
      case "misc"         => Right(Misc)
      case "email"        => Right(Email)
      case "website"      => Right(Website)
      case "date"         => Right(Date)
      case _              => Left(s"Invalid ner tag: $str")
    }

  def unsafe(str: String): NerTag =
    fromString(str).fold(sys.error, identity)

  implicit val jsonDecoder: Decoder[NerTag] =
    Decoder.decodeString.emap(fromString)
  implicit val jsonEncoder: Encoder[NerTag] =
    Encoder.encodeString.contramap(_.name)
} 
Example 106
Source File: LogLevel.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.common

import io.circe.{Decoder, Encoder}

sealed trait LogLevel { self: Product =>
  def toInt: Int
  final def name: String =
    productPrefix.toLowerCase
}

object LogLevel {

  case object Debug extends LogLevel { val toInt = 0 }
  case object Info  extends LogLevel { val toInt = 1 }
  case object Warn  extends LogLevel { val toInt = 2 }
  case object Error extends LogLevel { val toInt = 3 }

  def fromInt(n: Int): LogLevel =
    n match {
      case 0 => Debug
      case 1 => Info
      case 2 => Warn
      case 3 => Error
      case _ => Debug
    }

  def fromString(str: String): Either[String, LogLevel] =
    str.toLowerCase match {
      case "debug"   => Right(Debug)
      case "info"    => Right(Info)
      case "warn"    => Right(Warn)
      case "warning" => Right(Warn)
      case "error"   => Right(Error)
      case _         => Left(s"Invalid log-level: $str")
    }

  def unsafeString(str: String): LogLevel =
    fromString(str).fold(sys.error, identity)

  implicit val jsonDecoder: Decoder[LogLevel] =
    Decoder.decodeString.emap(fromString)
  implicit val jsonEncoder: Encoder[LogLevel] =
    Encoder.encodeString.contramap(_.name)
} 
Example 107
Source File: Priority.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.common

import cats.Order
import cats.implicits._

import io.circe.{Decoder, Encoder}

sealed trait Priority { self: Product =>

  final def name: String =
    productPrefix.toLowerCase
}

object Priority {

  case object High extends Priority

  case object Low extends Priority

  def fromString(str: String): Either[String, Priority] =
    str.toLowerCase match {
      case "high" => Right(High)
      case "low"  => Right(Low)
      case _      => Left(s"Invalid priority: $str")
    }

  def unsafe(str: String): Priority =
    fromString(str).fold(sys.error, identity)

  def fromInt(n: Int): Priority =
    if (n <= toInt(Low)) Low
    else High

  def toInt(p: Priority): Int =
    p match {
      case Low  => 0
      case High => 10
    }

  implicit val priorityOrder: Order[Priority] =
    Order.by[Priority, Int](toInt)

  implicit val jsonEncoder: Encoder[Priority] =
    Encoder.encodeString.contramap(_.name)
  implicit val jsonDecoder: Decoder[Priority] =
    Decoder.decodeString.emap(fromString)
} 
Example 108
Source File: Ident.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.common

import java.security.SecureRandom
import java.util.UUID

import cats.Eq
import cats.effect.Sync
import cats.implicits._

import io.circe.{Decoder, Encoder}
import scodec.bits.ByteVector

case class Ident(id: String) {
  def isEmpty: Boolean =
    id.trim.isEmpty

  def nonEmpty: Boolean =
    !isEmpty

  def /(next: Ident): Ident =
    new Ident(id + "." + next.id)
}

object Ident {
  implicit val identEq: Eq[Ident] =
    Eq.by(_.id)

  val chars: Set[Char] = (('A' to 'Z') ++ ('a' to 'z') ++ ('0' to '9') ++ "-_.").toSet

  def randomUUID[F[_]: Sync]: F[Ident] =
    Sync[F].delay(unsafe(UUID.randomUUID.toString))

  def randomId[F[_]: Sync]: F[Ident] =
    Sync[F].delay {
      val random = new SecureRandom()
      val buffer = new Array[Byte](32)
      random.nextBytes(buffer)
      unsafe(ByteVector.view(buffer).toBase58.grouped(11).mkString("-"))
    }

  def apply(str: String): Either[String, Ident] =
    fromString(str)

  def fromString(s: String): Either[String, Ident] =
    if (s.forall(chars.contains)) Right(new Ident(s))
    else Left(s"Invalid identifier: '$s'. Allowed chars: ${chars.toList.sorted.mkString}")

  def fromBytes(bytes: ByteVector): Ident =
    unsafe(bytes.toBase58)

  def fromByteArray(bytes: Array[Byte]): Ident =
    fromBytes(ByteVector.view(bytes))

  def unsafe(s: String): Ident =
    fromString(s) match {
      case Right(id) => id
      case Left(err) => sys.error(err)
    }

  def unapply(arg: String): Option[Ident] =
    fromString(arg).toOption

  implicit val encodeIdent: Encoder[Ident] =
    Encoder.encodeString.contramap(_.id)

  implicit val decodeIdent: Decoder[Ident] =
    Decoder.decodeString.emap(Ident.fromString)

} 
Example 109
Source File: ContactKind.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.common

import io.circe.{Decoder, Encoder}

sealed trait ContactKind { self: Product =>

  def asString: String = self.productPrefix
}

object ContactKind {
  val all = List()

  case object Phone    extends ContactKind
  case object Mobile   extends ContactKind
  case object Fax      extends ContactKind
  case object Email    extends ContactKind
  case object Docspell extends ContactKind
  case object Website  extends ContactKind

  def fromString(s: String): Either[String, ContactKind] =
    s.toLowerCase match {
      case "phone"    => Right(Phone)
      case "mobile"   => Right(Mobile)
      case "fax"      => Right(Fax)
      case "email"    => Right(Email)
      case "docspell" => Right(Docspell)
      case "website"  => Right(Website)
      case _          => Left(s"Not a state value: $s")
    }

  def unsafe(str: String): ContactKind =
    fromString(str).fold(sys.error, identity)

  def asString(s: ContactKind): String =
    s.asString.toLowerCase

  implicit val contactKindEncoder: Encoder[ContactKind] =
    Encoder.encodeString.contramap(_.asString)

  implicit val contactKindDecoder: Decoder[ContactKind] =
    Decoder.decodeString.emap(ContactKind.fromString)

} 
Example 110
Source File: CollectiveState.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.common

import io.circe.{Decoder, Encoder}

sealed trait CollectiveState
object CollectiveState {
  val all = List(Active, ReadOnly, Closed, Blocked)

  
  case object Blocked extends CollectiveState

  def fromString(s: String): Either[String, CollectiveState] =
    s.toLowerCase match {
      case "active"   => Right(Active)
      case "readonly" => Right(ReadOnly)
      case "closed"   => Right(Closed)
      case "blocked"  => Right(Blocked)
      case _          => Left(s"Unknown state: $s")
    }

  def unsafe(str: String): CollectiveState =
    fromString(str).fold(sys.error, identity)

  def asString(state: CollectiveState): String =
    state match {
      case Active   => "active"
      case Blocked  => "blocked"
      case Closed   => "closed"
      case ReadOnly => "readonly"
    }

  implicit val collectiveStateEncoder: Encoder[CollectiveState] =
    Encoder.encodeString.contramap(CollectiveState.asString)

  implicit val collectiveStateDecoder: Decoder[CollectiveState] =
    Decoder.decodeString.emap(CollectiveState.fromString)

} 
Example 111
Source File: ItemState.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.common

import cats.data.NonEmptyList

import io.circe.{Decoder, Encoder}

sealed trait ItemState { self: Product =>

  final def name: String =
    productPrefix.toLowerCase

  def isValid: Boolean =
    ItemState.validStates.exists(_ == this)

  def isInvalid: Boolean =
    ItemState.invalidStates.exists(_ == this)
}

object ItemState {

  case object Premature  extends ItemState
  case object Processing extends ItemState
  case object Created    extends ItemState
  case object Confirmed  extends ItemState

  def fromString(str: String): Either[String, ItemState] =
    str.toLowerCase match {
      case "premature"  => Right(Premature)
      case "processing" => Right(Processing)
      case "created"    => Right(Created)
      case "confirmed"  => Right(Confirmed)
      case _            => Left(s"Invalid item state: $str")
    }

  val validStates: NonEmptyList[ItemState] =
    NonEmptyList.of(Created, Confirmed)

  val invalidStates: NonEmptyList[ItemState] =
    NonEmptyList.of(Premature, Processing)

  def unsafe(str: String): ItemState =
    fromString(str).fold(sys.error, identity)

  implicit val jsonDecoder: Decoder[ItemState] =
    Decoder.decodeString.emap(fromString)
  implicit val jsonEncoder: Encoder[ItemState] =
    Encoder.encodeString.contramap(_.name)
} 
Example 112
Source File: OUserTask.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.backend.ops

import cats.data.OptionT
import cats.effect._
import cats.implicits._
import fs2.Stream

import docspell.common._
import docspell.store.queue.JobQueue
import docspell.store.usertask._

import io.circe.Encoder

trait OUserTask[F[_]] {

  
  def executeNow[A](account: AccountId, task: UserTask[A])(implicit
      E: Encoder[A]
  ): F[Unit]
}

object OUserTask {

  def apply[F[_]: Effect](
      store: UserTaskStore[F],
      queue: JobQueue[F],
      joex: OJoex[F]
  ): Resource[F, OUserTask[F]] =
    Resource.pure[F, OUserTask[F]](new OUserTask[F] {

      def executeNow[A](account: AccountId, task: UserTask[A])(implicit
          E: Encoder[A]
      ): F[Unit] =
        for {
          ptask <- task.encode.toPeriodicTask(account)
          job   <- ptask.toJob
          _     <- queue.insert(job)
          _     <- joex.notifyAllNodes
        } yield ()

      def getScanMailbox(account: AccountId): Stream[F, UserTask[ScanMailboxArgs]] =
        store
          .getByName[ScanMailboxArgs](account, ScanMailboxArgs.taskName)

      def findScanMailbox(
          id: Ident,
          account: AccountId
      ): OptionT[F, UserTask[ScanMailboxArgs]] =
        OptionT(getScanMailbox(account).find(_.id == id).compile.last)

      def deleteTask(account: AccountId, id: Ident): F[Unit] =
        (for {
          _ <- store.getByIdRaw(account, id)
          _ <- OptionT.liftF(store.deleteTask(account, id))
        } yield ()).getOrElse(())

      def submitScanMailbox(
          account: AccountId,
          task: UserTask[ScanMailboxArgs]
      ): F[Unit] =
        for {
          _ <- store.updateTask[ScanMailboxArgs](account, task)
          _ <- joex.notifyAllNodes
        } yield ()

      def getNotifyDueItems(account: AccountId): Stream[F, UserTask[NotifyDueItemsArgs]] =
        store
          .getByName[NotifyDueItemsArgs](account, NotifyDueItemsArgs.taskName)

      def findNotifyDueItems(
          id: Ident,
          account: AccountId
      ): OptionT[F, UserTask[NotifyDueItemsArgs]] =
        OptionT(getNotifyDueItems(account).find(_.id == id).compile.last)

      def submitNotifyDueItems(
          account: AccountId,
          task: UserTask[NotifyDueItemsArgs]
      ): F[Unit] =
        for {
          _ <- store.updateTask[NotifyDueItemsArgs](account, task)
          _ <- joex.notifyAllNodes
        } yield ()
    })

} 
Example 113
Source File: UserTask.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.store.usertask

import cats.effect._
import cats.implicits._

import docspell.common._
import docspell.common.syntax.all._
import docspell.store.records.RPeriodicTask

import com.github.eikek.calev.CalEvent
import io.circe.Decoder
import io.circe.Encoder

case class UserTask[A](
    id: Ident,
    name: Ident,
    enabled: Boolean,
    timer: CalEvent,
    args: A
) {

  def encode(implicit E: Encoder[A]): UserTask[String] =
    copy(args = E(args).noSpaces)

}

object UserTask {

  implicit final class UserTaskCodec(ut: UserTask[String]) {

    def decode[A](implicit D: Decoder[A]): Either[String, UserTask[A]] =
      ut.args
        .parseJsonAs[A]
        .left
        .map(_.getMessage)
        .map(a => ut.copy(args = a))

    def toPeriodicTask[F[_]: Sync](
        account: AccountId
    ): F[RPeriodicTask] =
      RPeriodicTask
        .create[F](
          ut.enabled,
          ut.name,
          account.collective,
          ut.args,
          s"${account.user.id}: ${ut.name.id}",
          account.user,
          Priority.Low,
          ut.timer
        )
        .map(r => r.copy(id = ut.id))
  }
} 
Example 114
Source File: DoobieMeta.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.store.impl

import java.time.format.DateTimeFormatter
import java.time.{Instant, LocalDate}

import docspell.common._
import docspell.common.syntax.all._

import com.github.eikek.calev.CalEvent
import doobie._
import doobie.implicits.legacy.instant._
import doobie.util.log.Success
import emil.doobie.EmilDoobieMeta
import io.circe.{Decoder, Encoder}

trait DoobieMeta extends EmilDoobieMeta {

  implicit val sqlLogging = LogHandler({
    case e @ Success(_, _, _, _) =>
      DoobieMeta.logger.trace("SQL " + e)
    case e =>
      DoobieMeta.logger.error(s"SQL Failure: $e")
  })

  def jsonMeta[A](implicit d: Decoder[A], e: Encoder[A]): Meta[A] =
    Meta[String].imap(str => str.parseJsonAs[A].fold(ex => throw ex, identity))(a =>
      e.apply(a).noSpaces
    )

  implicit val metaCollectiveState: Meta[CollectiveState] =
    Meta[String].imap(CollectiveState.unsafe)(CollectiveState.asString)

  implicit val metaUserState: Meta[UserState] =
    Meta[String].imap(UserState.unsafe)(UserState.asString)

  implicit val metaPassword: Meta[Password] =
    Meta[String].imap(Password(_))(_.pass)

  implicit val metaIdent: Meta[Ident] =
    Meta[String].imap(Ident.unsafe)(_.id)

  implicit val metaContactKind: Meta[ContactKind] =
    Meta[String].imap(ContactKind.unsafe)(_.asString)

  implicit val metaTimestamp: Meta[Timestamp] =
    Meta[Instant].imap(Timestamp(_))(_.value)

  implicit val metaJobState: Meta[JobState] =
    Meta[String].imap(JobState.unsafe)(_.name)

  implicit val metaDirection: Meta[Direction] =
    Meta[Boolean].imap(flag =>
      if (flag) Direction.Incoming: Direction else Direction.Outgoing: Direction
    )(d => Direction.isIncoming(d))

  implicit val metaPriority: Meta[Priority] =
    Meta[Int].imap(Priority.fromInt)(Priority.toInt)

  implicit val metaLogLevel: Meta[LogLevel] =
    Meta[String].imap(LogLevel.unsafeString)(_.name)

  implicit val metaLenientUri: Meta[LenientUri] =
    Meta[String].imap(LenientUri.unsafe)(_.asString)

  implicit val metaNodeType: Meta[NodeType] =
    Meta[String].imap(NodeType.unsafe)(_.name)

  implicit val metaLocalDate: Meta[LocalDate] =
    Meta[String].imap(str => LocalDate.parse(str))(_.format(DateTimeFormatter.ISO_DATE))

  implicit val metaItemState: Meta[ItemState] =
    Meta[String].imap(ItemState.unsafe)(_.name)

  implicit val metNerTag: Meta[NerTag] =
    Meta[String].imap(NerTag.unsafe)(_.name)

  implicit val metaNerLabel: Meta[NerLabel] =
    jsonMeta[NerLabel]

  implicit val metaNerLabelList: Meta[List[NerLabel]] =
    jsonMeta[List[NerLabel]]

  implicit val metaItemProposal: Meta[MetaProposal] =
    jsonMeta[MetaProposal]

  implicit val metaItemProposalList: Meta[MetaProposalList] =
    jsonMeta[MetaProposalList]

  implicit val metaLanguage: Meta[Language] =
    Meta[String].imap(Language.unsafe)(_.iso3)

  implicit val metaCalEvent: Meta[CalEvent] =
    Meta[String].timap(CalEvent.unsafe)(_.asString)
}

object DoobieMeta extends DoobieMeta {
  import org.log4s._
  private val logger = getLogger

} 
Example 115
Source File: package.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.api

import cats.implicits._
import com.azavea.franklin.database.{temporalExtentFromString, temporalExtentToString}
import com.azavea.franklin.datamodel.PaginationToken
import com.azavea.franklin.error.InvalidPatch
import com.azavea.franklin.extensions.validation.ExtensionName
import com.azavea.stac4s._
import geotrellis.vector.Geometry
import io.circe.{Encoder, Json}
import sttp.tapir.Codec.PlainCodec
import sttp.tapir.json.circe._
import sttp.tapir.{Codec, DecodeResult, Schema}

import scala.util.Try

package object schemas {

  implicit val extensionNameCodec: PlainCodec[ExtensionName] =
    Codec.string.mapDecode(s => DecodeResult.Value(ExtensionName.fromString(s)))(_.toString)

  implicit val schemaForTemporalExtent: Schema[TemporalExtent] = Schema(
    schemaForCirceJson.schemaType
  )
  implicit val schemaForGeometry: Schema[Geometry] = Schema(schemaForCirceJson.schemaType)

  implicit val schemaForStacItem: Schema[StacItem]         = Schema(schemaForCirceJson.schemaType)
  implicit val schemaForInvalidPatch: Schema[InvalidPatch] = Schema(schemaForCirceJson.schemaType)

  def decode(s: String): DecodeResult[TemporalExtent] = {
    temporalExtentFromString(s) match {
      case Left(e)  => DecodeResult.Mismatch("valid timestamp", e)
      case Right(v) => DecodeResult.Value(v)
    }
  }

  // or, using the type alias for codecs in the TextPlain format and String as the raw value:
  implicit val teCodec: PlainCodec[TemporalExtent] = Codec.string
    .mapDecode(decode)(temporalExtentToString)

  def bboxFromString(s: String): DecodeResult[Bbox] = {
    val numberList = s.split(",").map(d => Try(d.toDouble).toEither)
    val failed     = numberList.find(_.isLeft)
    failed match {
      case Some(Left(error)) => DecodeResult.Error("invalid bbox", error)
      case _ => {
        numberList.flatMap(_.toOption).toList match {
          case xmin :: ymin :: zmin :: xmax :: ymax :: zmax :: _ =>
            DecodeResult.Value(ThreeDimBbox(xmin, ymin, zmin, xmax, ymax, zmax))
          case xmin :: ymin :: xmax :: ymax :: _ =>
            DecodeResult.Value(TwoDimBbox(xmin, ymin, xmax, ymax))
          case _ => DecodeResult.Mismatch("must be 4 or 6 numbers separated by commas", s)
        }
      }
    }
  }

  def bboxToString(bbox: Bbox): String = bbox match {
    case ThreeDimBbox(xmin, ymin, zmin, xmax, ymax, zmax) => s"$xmin,$ymin,$zmin,$xmax,$ymax,$zmax"
    case TwoDimBbox(xmin, ymin, xmax, ymax)               => s"$xmin,$ymin,$xmax,$ymax"
  }

  implicit val bboxCodec: PlainCodec[Bbox] =
    Codec.string.mapDecode(bboxFromString)(bboxToString)

  def commaSeparatedStrings(s: String): DecodeResult[List[String]] =
    DecodeResult.Value(s.split(",").toList)
  def listToCSV(collections: List[String]): String = collections.mkString(",")

  implicit val csvListCodec: PlainCodec[List[String]] =
    Codec.string.mapDecode(commaSeparatedStrings)(listToCSV)

  def decStacItem(json: Json): DecodeResult[StacItem] = json.as[StacItem] match {
    case Left(err) => DecodeResult.Error(err.getMessage, err)
    case Right(v)  => DecodeResult.Value(v)
  }
  def encStacItem(stacItem: StacItem): Json = Encoder[StacItem].apply(stacItem)

  val jsonCodec: Codec.JsonCodec[Json] = implicitly[Codec.JsonCodec[Json]]

  implicit val codecStacItem: Codec.JsonCodec[StacItem] =
    jsonCodec.mapDecode(decStacItem)(encStacItem)

  implicit val codecPaginationToken: Codec.PlainCodec[PaginationToken] =
    Codec.string.mapDecode(PaginationToken.decPaginationToken)(PaginationToken.encPaginationToken)
} 
Example 116
Source File: database.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin

import cats.implicits._
import com.azavea.stac4s.TemporalExtent
import doobie.implicits.javasql._
import doobie.util.meta.Meta
import doobie.util.{Read, Write}
import io.circe.{Decoder, Encoder}

import java.sql.Timestamp
import java.time.Instant

package object database extends CirceJsonbMeta with GeotrellisWktMeta with Filterables {

  implicit val instantMeta: Meta[Instant]   = Meta[Timestamp].imap(_.toInstant)(Timestamp.from)
  implicit val instantRead: Read[Instant]   = Read[Timestamp].imap(_.toInstant)(Timestamp.from)
  implicit val instantWrite: Write[Instant] = Write[Timestamp].imap(_.toInstant)(Timestamp.from)

  def stringToInstant: String => Either[Throwable, Instant] =
    (s: String) => Either.catchNonFatal(Instant.parse(s))

  def temporalExtentToString(te: TemporalExtent): String = {
    te.value match {
      case Some(start) :: Some(end) :: _ if start != end => s"${start.toString}/${end.toString}"
      case Some(start) :: Some(end) :: _ if start == end => s"${start.toString}"
      case Some(start) :: None :: _                      => s"${start.toString}/.."
      case None :: Some(end) :: _                        => s"../${end.toString}"
    }
  }

  def temporalExtentFromString(str: String): Either[String, TemporalExtent] = {
    str.split("/").toList match {
      case ".." :: endString :: _ =>
        val parsedEnd: Either[Throwable, Instant] = stringToInstant(endString)
        parsedEnd match {
          case Left(_)             => Left(s"Could not decode instant: $str")
          case Right(end: Instant) => Right(TemporalExtent(None, end))
        }
      case startString :: ".." :: _ =>
        val parsedStart: Either[Throwable, Instant] = stringToInstant(startString)
        parsedStart match {
          case Left(_)               => Left(s"Could not decode instant: $str")
          case Right(start: Instant) => Right(TemporalExtent(start, None))
        }
      case startString :: endString :: _ =>
        val parsedStart: Either[Throwable, Instant] = stringToInstant(startString)
        val parsedEnd: Either[Throwable, Instant]   = stringToInstant(endString)
        (parsedStart, parsedEnd).tupled match {
          case Left(_)                               => Left(s"Could not decode instant: $str")
          case Right((start: Instant, end: Instant)) => Right(TemporalExtent(start, end))
        }
      case _ =>
        Either.catchNonFatal(Instant.parse(str)) match {
          case Left(_)           => Left(s"Could not decode instant: $str")
          case Right(t: Instant) => Right(TemporalExtent(t, t))
        }
    }
  }

  implicit val encoderTemporalExtent: Encoder[TemporalExtent] =
    Encoder.encodeString.contramap[TemporalExtent] { extent => temporalExtentToString(extent) }

  implicit val decoderTemporalExtent: Decoder[TemporalExtent] = Decoder.decodeString.emap { str =>
    temporalExtentFromString(str)
  }
} 
Example 117
Source File: ExtensionName.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.extensions.validation

import io.circe.{Decoder, Encoder}

sealed abstract class ExtensionName(val repr: String) {
  override def toString: String = repr
}

object ExtensionName {

  def fromString(s: String): ExtensionName = s.toLowerCase match {
    case "label" => Label
    case "layer" => Layer
    case _       => Unchecked(s)
  }

  implicit val encExtensionName: Encoder[ExtensionName] = Encoder.encodeString.contramap(_.repr)
  implicit val decExtensionName: Decoder[ExtensionName] = Decoder.decodeString.map(fromString)
}

case object Label                        extends ExtensionName("label")
case object Layer                        extends ExtensionName("layer")
case class Unchecked(underlying: String) extends ExtensionName(underlying) 
Example 118
Source File: PagingLinkExtension.scala.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.extensions.paging

import com.azavea.franklin.database.SearchFilters
import com.azavea.stac4s.extensions.LinkExtension
import eu.timepit.refined.types.string.NonEmptyString
import io.circe.generic.semiauto._
import io.circe.refined._
import io.circe.syntax._
import io.circe.{Decoder, Encoder, Json}

// https://github.com/radiantearth/stac-api-spec/blob/7a6e12868113c94b17dead8989f49d978d5dd865/api-spec.md#paging-extension
// the method for us is always POST, since otherwise we toss the params in the query string
// and don't use this
final case class PagingLinkExtension(
    headers: Map[NonEmptyString, String],
    body: SearchFilters,
    merge: Boolean
)

object PagingLinkExtension {
  implicit val decPagingLinkExtension: Decoder[PagingLinkExtension] = deriveDecoder

  implicit val encPagingLinkExtension: Encoder.AsObject[PagingLinkExtension] = Encoder
    .AsObject[Map[String, Json]]
    .contramapObject((linkExtensionFields: PagingLinkExtension) =>
      Map(
        "method"  -> "POST".asJson,
        "headers" -> linkExtensionFields.headers.asJson,
        "body"    -> linkExtensionFields.body.asJson,
        "merge"   -> linkExtensionFields.merge.asJson
      )
    )

  implicit val linkExtensionPagingLinkExtension: LinkExtension[PagingLinkExtension] =
    LinkExtension.instance
} 
Example 119
Source File: CollectionItemsResponse.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.datamodel

import com.azavea.stac4s.{StacItem, StacLink}
import io.circe.{Decoder, Encoder}

final case class CollectionItemsResponse(
    features: List[StacItem],
    links: List[StacLink]
)

object CollectionItemsResponse {

  implicit val encCollectionItemsResponse: Encoder[CollectionItemsResponse] = Encoder.forProduct3(
    "type",
    "features",
    "links"
  )(resp => ("FeatureCollection", resp.features, resp.links))

  implicit val decCollectionItemsResponse: Decoder[CollectionItemsResponse] = Decoder.forProduct3(
    "type",
    "features",
    "links"
  )((_: String, features: List[StacItem], links: List[StacLink]) =>
    CollectionItemsResponse(features, links)
  )
} 
Example 120
Source File: PaginationToken.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.datamodel

import com.azavea.stac4s.meta._
import eu.timepit.refined.types.numeric.PosInt
import io.circe.generic.semiauto._
import io.circe.parser._
import io.circe.refined._
import io.circe.syntax._
import io.circe.{Decoder, Encoder}
import sttp.tapir.DecodeResult

import java.time.Instant
import java.util.Base64

final case class PaginationToken(
    timestampAtLeast: Instant,
    serialIdGreaterThan: PosInt
)

object PaginationToken {

  implicit class ToTapirDecodeResult[T](circeResult: Either[io.circe.Error, T]) {

    def toDecodeResult: DecodeResult[T] = {
      circeResult match {
        case Left(err) =>
          DecodeResult.Error(err.getMessage, err)
        case Right(value) =>
          DecodeResult.Value(value)
      }
    }
  }

  implicit val dec: Decoder[PaginationToken] = deriveDecoder
  implicit val enc: Encoder[PaginationToken] = deriveEncoder

  val b64Encoder = Base64.getEncoder()
  val b64Decoder = Base64.getDecoder()

  def encPaginationToken(token: PaginationToken): String = b64Encoder.encodeToString(
    token.asJson.noSpaces.getBytes
  )

  def decPaginationToken(encoded: String): DecodeResult[PaginationToken] = {
    val jsonString: String = new String(b64Decoder.decode(encoded))
    val circeResult = for {
      js      <- parse(jsonString)
      decoded <- js.as[PaginationToken]
    } yield decoded
    circeResult.toDecodeResult
  }

} 
Example 121
Source File: Link.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.datamodel

import com.azavea.stac4s.{StacLinkType, StacMediaType}
import eu.timepit.refined.types.string.NonEmptyString
import io.circe.Encoder
import io.circe.generic.semiauto._

case class Link(
    href: NonEmptyString,
    rel: StacLinkType,
    _type: Option[StacMediaType],
    title: Option[NonEmptyString]
)

object Link {

  implicit val encStacLink: Encoder[Link] = Encoder.forProduct4(
    "href",
    "rel",
    "type",
    "title"
  )(link => (link.href, link.rel, link._type, link.title))

  implicit val decoderLink = deriveDecoder[Link]
} 
Example 122
Source File: ProjectionProgressSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.sourcing.projections

import java.util.UUID

import akka.persistence.query.{Offset, Sequence, TimeBasedUUID}
import ch.epfl.bluebrain.nexus.sourcing.projections.ProjectionProgress._
import ch.epfl.bluebrain.nexus.sourcing.projections.implicits._
import io.circe.Encoder
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike
import org.scalatest.{EitherValues, Inspectors}

class ProjectionProgressSpec extends AnyWordSpecLike with Matchers with Inspectors with TestHelpers with EitherValues {

  "A ProjectionProgress" should {
    val mapping = Map(
      OffsetProgress(Sequence(14L), 2, 0, 1)                                                            ->
        jsonContentOf("/indexing/sequence-offset-progress.json"),
      OffsetProgress(TimeBasedUUID(UUID.fromString("ee7e4360-39ca-11e9-9ed5-dbdaa32f8986")), 32, 5, 10) ->
        jsonContentOf("/indexing/timebaseduuid-offset-progress.json"),
      NoProgress                                                                                        ->
        jsonContentOf("/indexing/no-offset-progress.json"),
      OffsetsProgress(Map("noOffset" -> NoProgress, "other" -> OffsetProgress(Sequence(2L), 10L, 2L, 0L))) ->
        jsonContentOf("/indexing/offsets-progress.json")
    )

    "properly encode progress values" in {
      forAll(mapping.toList) {
        case (prog, repr) =>
          Encoder[ProjectionProgress].apply(prog) shouldEqual repr
      }
    }

    "properly decode progress values" in {
      forAll(mapping.toList) {
        case (prog, repr) =>
          repr.as[ProjectionProgress].rightValue shouldEqual prog
      }
    }

    "Add progress" in {
      val progress =
        OffsetsProgress(Map("noOffset" -> NoProgress, "other" -> OffsetProgress(Sequence(2L), 10L, 2L, 0L)))
      progress + ("noOffset", Sequence(1L), ProgressStatus.Failed("some error")) shouldEqual
        OffsetsProgress(
          Map(
            "noOffset" -> OffsetProgress(Sequence(1L), 1L, 0L, 1L),
            "other"    -> OffsetProgress(Sequence(2L), 10L, 2L, 0L)
          )
        )
      progress + ("other", Sequence(3L), ProgressStatus.Discarded) shouldEqual
        OffsetsProgress(Map("noOffset" -> NoProgress, "other" -> OffsetProgress(Sequence(3L), 11L, 3L, 0L)))
    }

    "fetch minimum progress" in {
      val progress = OffsetsProgress(
        Map(
          "one"   -> OffsetProgress(Sequence(1L), 2L, 1L, 0L),
          "other" -> OffsetProgress(Sequence(2L), 10L, 2L, 0L),
          "a"     -> OffsetProgress(Sequence(0L), 0L, 0L, 0L)
        )
      )
      progress.minProgressFilter(_.length > 1) shouldEqual OffsetProgress(Sequence(1L), 2L, 1L, 0L)
      progress.minProgress shouldEqual OffsetProgress(Sequence(0L), 0L, 0L, 0L)
    }

    "test TimeBasedUUIDd ordering" in {
      val time1 =
        TimeBasedUUID(UUID.fromString("49225740-2019-11ea-a752-ffae2393b6e4")) // 2019-12-16T15:32:36.148Z[UTC]
      val time2 =
        TimeBasedUUID(UUID.fromString("91be23d0-2019-11ea-a752-ffae2393b6e4")) // 2019-12-16T15:34:37.965Z[UTC]
      val time3 =
        TimeBasedUUID(UUID.fromString("91f95810-2019-11ea-a752-ffae2393b6e4")) // 2019-12-16T15:34:38.353Z[UTC]
      val offset1: Offset = time1
      val offset2: Offset = time2
      val offset3: Offset = time3
      time1.asInstant.isBefore(time2.asInstant) shouldEqual true
      time2.asInstant.isBefore(time3.asInstant) shouldEqual true
      offset1.gt(offset2) shouldEqual false
      offset3.gt(offset2) shouldEqual true
      List(time2, time1, time3).sorted(offsetOrdering) shouldEqual List(time1, time2, time3)
    }
  }
} 
Example 123
Source File: AdminError.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.admin.exceptions

import akka.http.scaladsl.model.StatusCodes
import ch.epfl.bluebrain.nexus.commons.http.directives.StatusFrom
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.Contexts._
import ch.epfl.bluebrain.nexus.service.exceptions.ServiceError
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}

import scala.annotation.nowarn


  final case object InvalidFormat extends AdminError("The json representation is incorrectly formatted.")

  @nowarn("cat=unused")
  implicit val adminErrorEncoder: Encoder[AdminError] = {
    implicit val rejectionConfig: Configuration = Configuration.default.withDiscriminator("@type")
    val enc                                     = deriveConfiguredEncoder[AdminError].mapJson(_ addContext errorCtxUri)
    Encoder.instance(r => enc(r) deepMerge Json.obj("reason" -> Json.fromString(r.msg)))
  }

  implicit val adminErrorStatusFrom: StatusFrom[AdminError] = {
    case NotFound             => StatusCodes.NotFound
    case AuthenticationFailed => StatusCodes.Unauthorized
    case AuthorizationFailed  => StatusCodes.Forbidden
    case InvalidFormat        => StatusCodes.BadRequest
    case _                    => StatusCodes.InternalServerError
  }
} 
Example 124
Source File: EventSerializer.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.admin.persistence

import akka.actor.ExtendedActorSystem
import akka.serialization.SerializerWithStringManifest
import ch.epfl.bluebrain.nexus.admin.organizations.OrganizationEvent
import ch.epfl.bluebrain.nexus.admin.projects.ProjectEvent
import ch.epfl.bluebrain.nexus.commons.serialization.AkkaCoproductSerializer
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import ch.epfl.bluebrain.nexus.service.config.Settings
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.{deriveConfiguredDecoder, deriveConfiguredEncoder}
import io.circe.{Decoder, Encoder}
import shapeless.{:+:, CNil}

import scala.annotation.nowarn

@nowarn("cat=unused")
class EventSerializer(system: ExtendedActorSystem) extends SerializerWithStringManifest {

  implicit private val httpConfig: HttpConfig = Settings(system).serviceConfig.http

  implicit private val config: Configuration = Configuration.default.withDiscriminator("@type")

  implicit private val projectEventDecoder: Decoder[ProjectEvent]           = deriveConfiguredDecoder[ProjectEvent]
  implicit private val projectEventEncoder: Encoder[ProjectEvent]           = deriveConfiguredEncoder[ProjectEvent]
  implicit private val organizationEventDecoder: Decoder[OrganizationEvent] = deriveConfiguredDecoder[OrganizationEvent]
  implicit private val organizationEventEncoder: Encoder[OrganizationEvent] = deriveConfiguredEncoder[OrganizationEvent]

  private val serializer = new AkkaCoproductSerializer[OrganizationEvent :+: ProjectEvent :+: CNil](1129)

  override val identifier: Int = serializer.identifier

  override def manifest(o: AnyRef): String = serializer.manifest(o)

  override def toBinary(o: AnyRef): Array[Byte] = serializer.toBinary(o)

  override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef = serializer.fromBinary(bytes, manifest)
} 
Example 125
Source File: ProjectRejection.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.admin.projects

import java.util.UUID

import akka.http.scaladsl.model.StatusCodes.{BadRequest, Conflict, NotFound}
import ch.epfl.bluebrain.nexus.commons.http.directives.StatusFrom
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.Contexts._
import ch.epfl.bluebrain.nexus.service.routes.ResourceRejection
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}

import scala.annotation.nowarn

sealed abstract class ProjectRejection(val msg: String) extends ResourceRejection

object ProjectRejection {

  
  final case class IncorrectRev(expected: Long, provided: Long)
      extends ProjectRejection(
        s"Incorrect revision '$provided' provided, expected '$expected', the project may have been updated since last seen."
      )

  @nowarn("cat=unused")
  implicit val projectRejectionEncoder: Encoder[ProjectRejection] = {
    implicit val rejectionConfig: Configuration = Configuration.default.withDiscriminator("@type")
    val enc                                     = deriveConfiguredEncoder[ProjectRejection].mapJson(_ addContext errorCtxUri)
    Encoder.instance(r => enc(r) deepMerge Json.obj("reason" -> Json.fromString(r.msg)))
  }

  implicit val projectStatusFrom: StatusFrom[ProjectRejection] = StatusFrom {
    case _: IncorrectRev             => Conflict
    case _: ProjectAlreadyExists     => Conflict
    case _: ProjectNotFound          => NotFound
    case _: OrganizationNotFound     => NotFound
    case _: ProjectIsDeprecated      => BadRequest
    case _: OrganizationIsDeprecated => BadRequest
    case _: InvalidProjectFormat     => BadRequest
  }

} 
Example 126
Source File: Project.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.admin.projects

import java.util.UUID

import ch.epfl.bluebrain.nexus.rdf.Iri.{AbsoluteIri, Path}
import ch.epfl.bluebrain.nexus.rdf.Iri.Path._
import io.circe.{Encoder, Json}


  def path: Path = organizationLabel / label
}

object Project {

  implicit val projectEncoder: Encoder[Project] = Encoder.encodeJson.contramap { p =>
    Json
      .obj(
        "_label"             -> Json.fromString(p.label),
        "_organizationUuid"  -> Json.fromString(p.organizationUuid.toString),
        "_organizationLabel" -> Json.fromString(p.organizationLabel),
        "apiMappings"        -> Json.arr(p.apiMappings.toList.map {
          case (prefix, namespace) =>
            Json.obj("prefix" -> Json.fromString(prefix), "namespace" -> Json.fromString(namespace.asString))
        }: _*),
        "base"               -> Json.fromString(p.base.asString),
        "vocab"              -> Json.fromString(p.vocab.asString)
      )
      .deepMerge(p.description match {
        case Some(desc) => Json.obj("description" -> Json.fromString(desc))
        case None       => Json.obj()
      })
  }
} 
Example 127
Source File: OrganizationRejection.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.admin.organizations

import java.util.UUID

import akka.http.scaladsl.model.StatusCodes.{BadRequest, Conflict, NotFound}
import ch.epfl.bluebrain.nexus.commons.http.directives.StatusFrom
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.Contexts._
import ch.epfl.bluebrain.nexus.service.routes.ResourceRejection
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}

import scala.annotation.nowarn

sealed abstract class OrganizationRejection(val msg: String) extends ResourceRejection

object OrganizationRejection {

  
  final case class IncorrectRev(expected: Long, provided: Long)
      extends OrganizationRejection(
        s"Incorrect revision '$provided' provided, expected '$expected', the organization may have been updated since last seen."
      )

  @nowarn("cat=unused")
  implicit val organizationRejectionEncoder: Encoder[OrganizationRejection] = {
    implicit val rejectionConfig: Configuration = Configuration.default.withDiscriminator("@type")
    val enc                                     = deriveConfiguredEncoder[OrganizationRejection].mapJson(_ addContext errorCtxUri)
    Encoder.instance(r => enc(r) deepMerge Json.obj("reason" -> Json.fromString(r.msg)))
  }

  implicit val organizationStatusFrom: StatusFrom[OrganizationRejection] = StatusFrom {
    case _: IncorrectRev              => Conflict
    case _: OrganizationAlreadyExists => Conflict
    case _: OrganizationNotFound      => NotFound
    case _: InvalidOrganizationFormat => BadRequest
  }
} 
Example 128
Source File: OrganizationEvent.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.admin.organizations

import java.time.Instant
import java.util.UUID

import ch.epfl.bluebrain.nexus.iam.types.Identity.Subject
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.Contexts._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import ch.epfl.bluebrain.nexus.service.config.Vocabulary.nxv
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto._
import io.circe.syntax._
import io.circe.{Encoder, Json}

import scala.annotation.nowarn


  final case class OrganizationDeprecated(
      id: UUID,
      rev: Long,
      instant: Instant,
      subject: Subject
  ) extends OrganizationEvent

  object JsonLd {

    @nowarn("cat=unused")
    implicit private val config: Configuration = Configuration.default
      .withDiscriminator("@type")
      .copy(transformMemberNames = {
        case nxv.`@id`.name        => nxv.uuid.prefix
        case nxv.label.name        => nxv.label.prefix
        case nxv.rev.name          => nxv.rev.prefix
        case nxv.instant.name      => nxv.instant.prefix
        case nxv.eventSubject.name => nxv.eventSubject.prefix
        case other                 => other
      })

    @nowarn("cat=unused")
    implicit private def subjectIdEncoder(implicit http: HttpConfig): Encoder[Subject] =
      Encoder.encodeJson.contramap(_.id.asJson)

    @nowarn("cat=unused")
    implicit final def orgEventEncoder(implicit http: HttpConfig): Encoder[OrganizationEvent] =
      Encoder.encodeJson.contramap[OrganizationEvent] { ev =>
        deriveConfiguredEncoder[OrganizationEvent]
          .mapJson { json =>
            val rev = Json.obj(nxv.rev.prefix -> Json.fromLong(ev.rev))
            json
              .deepMerge(rev)
              .addContext(adminCtxUri)
              .addContext(resourceCtxUri)
          }
          .apply(ev)
      }
  }
} 
Example 129
Source File: QueryResult.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.commons.search

import cats.Functor
import cats.syntax.functor._
import io.circe.Encoder


  final case class UnscoredQueryResult[A](source: A) extends QueryResult[A]

  implicit final val queryResultFunctor: Functor[QueryResult] =
    new Functor[QueryResult] {
      override def map[A, B](fa: QueryResult[A])(f: A => B): QueryResult[B] =
        fa match {
          case sqr: ScoredQueryResult[A]   => sqr.map(f)
          case uqr: UnscoredQueryResult[A] => uqr.map(f)
        }
    }

  implicit final val scoredQueryResultFunctor: Functor[ScoredQueryResult] =
    new Functor[ScoredQueryResult] {
      override def map[A, B](fa: ScoredQueryResult[A])(f: A => B): ScoredQueryResult[B] =
        fa.copy(source = f(fa.source))
    }

  implicit final val sourceQueryResultFunctor: Functor[UnscoredQueryResult] =
    new Functor[UnscoredQueryResult] {
      override def map[A, B](fa: UnscoredQueryResult[A])(f: A => B): UnscoredQueryResult[B] =
        fa.copy(source = f(fa.source))
    }

  implicit final def queryResultEncoder[A](implicit
      S: Encoder[ScoredQueryResult[A]],
      U: Encoder[UnscoredQueryResult[A]]
  ): Encoder[QueryResult[A]] =
    Encoder.instance {
      case s: ScoredQueryResult[A]   => S.apply(s)
      case u: UnscoredQueryResult[A] => U.apply(u)
    }
} 
Example 130
Source File: ErrorDirectives.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.commons.http.directives

import akka.http.scaladsl.marshalling.{Marshaller, ToResponseMarshaller}
import akka.http.scaladsl.model._
import ch.epfl.bluebrain.nexus.commons.circe.ContextUri
import ch.epfl.bluebrain.nexus.commons.circe.syntax._
import ch.epfl.bluebrain.nexus.commons.http.JsonLdCirceSupport.OrderedKeys
import ch.epfl.bluebrain.nexus.commons.http.RdfMediaTypes
import io.circe.{Encoder, Printer}


  implicit final def jsonLdMarshallerFromStatusAndEncoder[A](implicit
      statusFrom: StatusFrom[A],
      encoder: Encoder[A],
      context: ContextUri,
      orderedKeys: OrderedKeys = OrderedKeys(List("@context", "code", "message", "details", "")),
      printer: Printer = Printer.noSpaces.copy(dropNullValues = true)
  ): ToResponseMarshaller[A] =
    Marshaller.withFixedContentType(RdfMediaTypes.`application/ld+json`) { value =>
      HttpResponse(
        status = statusFrom(value),
        entity = HttpEntity(
          RdfMediaTypes.`application/ld+json`,
          printer.print(encoder.mapJson(_.addContext(context)).apply(value).sortKeys)
        )
      )
    }
} 
Example 131
Source File: TagRoutes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.http.scaladsl.model.StatusCodes.{Created, OK}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.admin.client.types.Project
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.types.Identity.Subject
import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission}
import ch.epfl.bluebrain.nexus.kg.config.Contexts.tagCtxUri
import ch.epfl.bluebrain.nexus.kg.directives.ProjectDirectives._
import ch.epfl.bluebrain.nexus.kg.marshallers.instances._
import ch.epfl.bluebrain.nexus.kg.resources._
import ch.epfl.bluebrain.nexus.kg.resources.syntax._
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import ch.epfl.bluebrain.nexus.rdf.Iri.Path._
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig
import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives
import io.circe.syntax._
import io.circe.{Encoder, Json}
import kamon.Kamon
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global

class TagRoutes private[routes] (
    resourceType: String,
    tags: Tags[Task],
    acls: Acls[Task],
    realms: Realms[Task],
    schema: Ref,
    write: Permission
)(implicit
    caller: Caller,
    project: Project,
    config: ServiceConfig
) extends AuthDirectives(acls, realms) {

  private val projectPath               = project.organizationLabel / project.label
  implicit private val subject: Subject = caller.subject

  
  def routes(id: AbsoluteIri): Route =
    // Consume the tag segment
    pathPrefix("tags") {
      concat(
        // Create tag
        (post & parameter("rev".as[Long]) & pathEndOrSingleSlash) { rev =>
          operationName(opName) {
            (authorizeFor(projectPath, write) & projectNotDeprecated) {
              entity(as[Json]) { source =>
                Kamon.currentSpan().tag("resource.operation", "create")
                complete(tags.create(Id(project.ref, id), rev, source, schema).value.runWithStatus(Created))
              }
            }
          }
        },
        // Fetch a tag
        (get & projectNotDeprecated & pathEndOrSingleSlash) {
          operationName(opName) {
            authorizeFor(projectPath, read)(caller) {
              parameter("rev".as[Long].?) {
                case Some(rev) => complete(tags.fetch(Id(project.ref, id), rev, schema).value.runWithStatus(OK))
                case _         => complete(tags.fetch(Id(project.ref, id), schema).value.runWithStatus(OK))
              }
            }
          }
        }
      )
    }

  implicit private def tagsEncoder: Encoder[TagSet] =
    Encoder.instance(tags => Json.obj("tags" -> Json.arr(tags.map(_.asJson).toSeq: _*)).addContext(tagCtxUri))

  private def opName: String                        =
    resourceType match {
      case "resources" => s"/${config.http.prefix}/resources/{org}/{project}/{schemaId}/{id}/tags"
      case _           => s"/${config.http.prefix}/$resourceType/{org}/{project}/{id}/tags"
    }
} 
Example 132
Source File: EventCommonRoutes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes
import java.util.UUID

import akka.NotUsed
import akka.actor.ActorSystem
import akka.http.javadsl.server.Rejections.validationRejection
import akka.http.scaladsl.model.headers.`Last-Event-ID`
import akka.http.scaladsl.model.sse.ServerSentEvent
import akka.http.scaladsl.server.Directive1
import akka.http.scaladsl.server.Directives.{optionalHeaderValueByName, provide, reject}
import akka.persistence.query._
import akka.persistence.query.scaladsl.EventsByTagQuery
import akka.stream.scaladsl.Source
import ch.epfl.bluebrain.nexus.commons.circe.syntax._
import ch.epfl.bluebrain.nexus.kg.resources.Event
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig
import io.circe.syntax._
import io.circe.{Encoder, Printer}

import scala.concurrent.duration._
import scala.util.{Failure, Success, Try}


  protected def lastEventId: Directive1[Offset] =
    optionalHeaderValueByName(`Last-Event-ID`.name)
      .map(_.map(id => `Last-Event-ID`(id)))
      .flatMap {
        case Some(header) =>
          Try[Offset](TimeBasedUUID(UUID.fromString(header.id))) orElse Try(Sequence(header.id.toLong)) match {
            case Success(value) => provide(value)
            case Failure(_)     => reject(validationRejection("The value of the `Last-Event-ID` header is not valid."))
          }
        case None         => provide(NoOffset)
      }

  private def aToSse[A: Encoder](a: A, offset: Offset): ServerSentEvent = {
    val json = a.asJson.sortKeys(ServiceConfig.orderedKeys)
    ServerSentEvent(
      data = json.printWith(printer),
      eventType = json.hcursor.get[String]("@type").toOption,
      id = offset match {
        case NoOffset            => None
        case Sequence(value)     => Some(value.toString)
        case TimeBasedUUID(uuid) => Some(uuid.toString)
      }
    )
  }

  protected def eventToSse(envelope: EventEnvelope)(implicit enc: Encoder[Event]): Option[ServerSentEvent] =
    envelope.event match {
      case value: Event => Some(aToSse(value, envelope.offset))
      case _            => None
    }
} 
Example 133
Source File: Tag.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.resources

import cats.implicits._
import ch.epfl.bluebrain.nexus.kg.config.Contexts._
import ch.epfl.bluebrain.nexus.kg.resources.Rejection.InvalidResourceFormat
import ch.epfl.bluebrain.nexus.kg.resources.syntax._
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.rdf.{GraphDecoder, NonEmptyString}
import ch.epfl.bluebrain.nexus.service.config.Vocabulary.nxv
import io.circe.{Encoder, Json}


  final def apply(resId: ResId, json: Json): Either[Rejection, Tag] = {
    val completeJson = (json deepMerge tagCtx).id(resId.value)
    for {
      g <- completeJson.toGraph(resId.value).leftMap(_ => InvalidResourceFormat(resId.ref, "Empty or wrong Json-LD."))
      t <- tagGraphDecoder(g.cursor).leftRejectionFor(resId.ref)
    } yield t
  }

  // format: on

  implicit final val tagEncoder: Encoder[Tag] = Encoder.instance {
    case Tag(rev, tag) => Json.obj("tag" -> Json.fromString(tag), "rev" -> Json.fromLong(rev))
  }

  implicit final val tagGraphDecoder: GraphDecoder[Tag] = GraphDecoder.instance { c =>
    for {
      rev <- c.down(nxv.rev).as[Long]
      tag <- c.down(nxv.tag).as[NonEmptyString].map(_.asString)
    } yield Tag(rev, tag)
  }
} 
Example 134
Source File: IdentifiedProgress.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.indexing

import cats.Functor
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import io.circe.{Encoder, Json}
import io.circe.syntax._

final case class IdentifiedProgress[A](sourceId: Option[AbsoluteIri], projectionId: Option[AbsoluteIri], value: A)

object IdentifiedProgress {

  def apply[A](sourceId: AbsoluteIri, projectionId: AbsoluteIri, value: A): IdentifiedProgress[A] =
    IdentifiedProgress(Some(sourceId), Some(projectionId), value)

  def apply[A](sourceId: AbsoluteIri, value: A): IdentifiedProgress[A] =
    IdentifiedProgress(Some(sourceId), None, value)

  def apply[A](value: A): IdentifiedProgress[A] =
    IdentifiedProgress(None, None, value)

  private def optionalIdJson(prefix: String, value: Option[AbsoluteIri]): Json =
    value.map(id => Json.obj(prefix -> id.asString.asJson)).getOrElse(Json.obj())

  implicit val functorProgress: Functor[IdentifiedProgress]                    = new Functor[IdentifiedProgress] {
    override def map[A, B](fa: IdentifiedProgress[A])(f: A => B): IdentifiedProgress[B] = fa.copy(value = f(fa.value))
  }

  implicit def encoderProgressIdentifiedValue[A: Encoder]: Encoder[IdentifiedProgress[A]] =
    Encoder.instance {
      case IdentifiedProgress(sourceId, projectionId, value) =>
        optionalIdJson("sourceId", sourceId) deepMerge optionalIdJson(
          "projectionId",
          projectionId
        ) deepMerge value.asJson
    }

  implicit def orderingIdentifiedProgress[A]: Ordering[IdentifiedProgress[A]] =
    (x: IdentifiedProgress[A], y: IdentifiedProgress[A]) => {
      val sourceId1     = x.sourceId.map(_.asString).getOrElse("")
      val sourceId2     = y.sourceId.map(_.asString).getOrElse("")
      val projectionId1 = x.projectionId.map(_.asString).getOrElse("")
      val projectionId2 = y.projectionId.map(_.asString).getOrElse("")
      s"$sourceId1$projectionId1" compareTo s"$sourceId2$projectionId2"
    }
} 
Example 135
Source File: QueryResultEncoder.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.search

import akka.http.scaladsl.model.Uri
import akka.http.scaladsl.model.Uri.Query
import ch.epfl.bluebrain.nexus.commons.search.QueryResult.{ScoredQueryResult, UnscoredQueryResult}
import ch.epfl.bluebrain.nexus.commons.search.QueryResults.{ScoredQueryResults, UnscoredQueryResults}
import ch.epfl.bluebrain.nexus.commons.search.{FromPagination, QueryResult, QueryResults}
import ch.epfl.bluebrain.nexus.kg.config.Contexts.{resourceCtxUri, searchCtxUri}
import ch.epfl.bluebrain.nexus.kg.directives.QueryDirectives.{after, from, size}
import ch.epfl.bluebrain.nexus.kg.indexing.SparqlLink
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import ch.epfl.bluebrain.nexus.service.config.Vocabulary.nxv
import io.circe.syntax._
import io.circe.{Encoder, Json}
trait LowPriorityQueryResultsEncoder {

  implicit def qrsEncoderLowPrio[A: Encoder]: Encoder[QueryResults[A]] =
    Encoder.instance(qrsEncoderJsonLinks[A](None).apply(_))

  implicit private val uriEncoder: Encoder[Uri] = Encoder.encodeString.contramap(_.toString)

  protected def qrsEncoderJsonLinks[A: Encoder](next: Option[Uri]): Encoder[QueryResults[A]] = {
    implicit def qrEncoderJson: Encoder[QueryResult[A]]     =
      Encoder.instance {
        case UnscoredQueryResult(v)      => v.asJson.removeKeys(nxv.original_source.prefix)
        case ScoredQueryResult(score, v) =>
          v.asJson.removeKeys(nxv.original_source.prefix) deepMerge
            Json.obj(nxv.score.prefix -> Json.fromFloatOrNull(score))
      }
    def json(total: Long, list: List[QueryResult[A]]): Json =
      Json
        .obj(nxv.total.prefix -> Json.fromLong(total), nxv.results.prefix -> Json.arr(list.map(qrEncoderJson(_)): _*))
        .addContext(searchCtxUri)
        .addContext(resourceCtxUri)

    Encoder.instance {
      case UnscoredQueryResults(total, list, _)         =>
        json(total, list) deepMerge Json.obj(nxv.next.prefix -> next.asJson)
      case ScoredQueryResults(total, maxScore, list, _) =>
        json(total, list) deepMerge
          Json.obj(nxv.maxScore.prefix -> maxScore.asJson, nxv.next.prefix -> next.asJson)
    }
  }
}

object QueryResultEncoder extends LowPriorityQueryResultsEncoder {

  implicit def qrsEncoderJson(implicit searchUri: Uri, http: HttpConfig): Encoder[QueryResults[Json]] =
    Encoder.instance { results =>
      val nextLink = results.token.flatMap(next(searchUri, _))
      qrsEncoderJsonLinks[Json](nextLink).apply(results)
    }

  implicit def qrsEncoderJson(implicit
      searchUri: Uri,
      pagination: FromPagination,
      http: HttpConfig
  ): Encoder[QueryResults[SparqlLink]] =
    Encoder.instance { results =>
      val nextLink = next(searchUri, results.total, pagination)
      qrsEncoderJsonLinks[SparqlLink](nextLink).apply(results)
    }

  private def next(current: Uri, total: Long, pagination: FromPagination)(implicit http: HttpConfig): Option[Uri] = {
    val nextFrom = pagination.from + pagination.size
    if (nextFrom < total.toInt) {
      val params = current.query().toMap + (from -> nextFrom.toString) + (size -> pagination.size.toString)
      Some(toPublic(current).withQuery(Query(params)))
    } else None
  }

  private def next(current: Uri, afterToken: String)(implicit http: HttpConfig): Option[Uri] =
    current.query().get(after) match {
      case Some(`afterToken`) => None
      case _                  =>
        val params = current.query().toMap + (after -> afterToken) - from
        Some(toPublic(current).withQuery(Query(params)))
    }

  private def toPublic(uri: Uri)(implicit http: HttpConfig): Uri =
    uri.copy(scheme = http.publicUri.scheme, authority = http.publicUri.authority)
} 
Example 136
Source File: QueryBuilder.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.search

import ch.epfl.bluebrain.nexus.kg.routes.SearchParams
import ch.epfl.bluebrain.nexus.rdf.implicits._
import io.circe.syntax._
import io.circe.{Encoder, Json}
import ch.epfl.bluebrain.nexus.kg.indexing.View.ElasticSearchView._
import ch.epfl.bluebrain.nexus.service.config.Vocabulary._

object QueryBuilder {

  private def baseQuery(terms: List[Json], withScore: Boolean): Json = {
    val eval = if (withScore) "must" else "filter"
    Json.obj("query" -> Json.obj("bool" -> Json.obj(eval -> Json.arr(terms: _*))))

  }

  private def term[A: Encoder](k: String, value: A): Json    =
    Json.obj("term" -> Json.obj(k -> value.asJson))

  private def `match`[A: Encoder](k: String, value: A): Json =
    Json.obj("match" -> Json.obj(k -> value.asJson))

  
  def queryFor(params: SearchParams): Json                   =
    baseQuery(
      terms = params.types.map(term("@type", _)) ++ params.id.map(term("@id", _)) ++ params.q
        .map(`match`(allField, _)) ++ params.schema.map(term(nxv.constrainedBy.prefix, _)) ++ params.deprecated
        .map(term(nxv.deprecated.prefix, _)) ++ params.rev.map(term(nxv.rev.prefix, _)) ++ params.createdBy
        .map(term(nxv.createdBy.prefix, _)) ++ params.updatedBy.map(term(nxv.updatedBy.prefix, _)),
      withScore = params.q.isDefined
    )
} 
Example 137
Source File: PermissionsEvent.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.permissions

import java.time.Instant

import ch.epfl.bluebrain.nexus.iam.types.Identity.Subject
import ch.epfl.bluebrain.nexus.iam.types.{Identity, Permission}
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.Contexts._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import io.circe.Encoder
import io.circe.generic.extras.Configuration

import scala.annotation.nowarn


  final case class PermissionsDeleted(
      rev: Long,
      instant: Instant,
      subject: Subject
  ) extends PermissionsEvent

  object JsonLd {
    import io.circe.generic.extras.semiauto._

    @nowarn("cat=unused")
    implicit def permissionsEventEncoder(implicit http: HttpConfig): Encoder[Event] = {
      implicit val config: Configuration            = Configuration.default
        .withDiscriminator("@type")
        .copy(transformMemberNames = {
          case "rev"     => "_rev"
          case "instant" => "_instant"
          case "subject" => "_subject"
          case other     => other
        })
      implicit val subjectEncoder: Encoder[Subject] = Identity.subjectIdEncoder
      deriveConfiguredEncoder[Event]
        .mapJson { json =>
          json
            .addContext(iamCtxUri)
            .addContext(resourceCtxUri)
        }
    }
  }
} 
Example 138
Source File: AclRejection.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.acls

import akka.http.scaladsl.model.StatusCodes.{BadRequest, Conflict, NotFound}
import ch.epfl.bluebrain.nexus.commons.http.directives.StatusFrom
import ch.epfl.bluebrain.nexus.iam.types.Permission
import ch.epfl.bluebrain.nexus.rdf.Iri.Path
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.Contexts.errorCtxUri
import ch.epfl.bluebrain.nexus.service.routes.ResourceRejection
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}

import scala.annotation.nowarn

sealed abstract class AclRejection(val msg: String) extends ResourceRejection

object AclRejection {

  
  final case class UnknownPermissions(permissions: Set[Permission])
      extends AclRejection(
        s"Some of the permissions specified are not known: '${permissions.mkString("\"", ", ", "\"")}'"
      )

  @nowarn("cat=unused")
  implicit val aclRejectionEncoder: Encoder[AclRejection] = {
    implicit val rejectionConfig: Configuration = Configuration.default.withDiscriminator("@type")
    val enc                                     = deriveConfiguredEncoder[AclRejection].mapJson(_ addContext errorCtxUri)
    Encoder.instance(r => enc(r) deepMerge Json.obj("reason" -> Json.fromString(r.msg)))
  }

  implicit val aclRejectionStatusFrom: StatusFrom[AclRejection] =
    StatusFrom {
      case _: NothingToBeUpdated                        => BadRequest
      case _: AclIsEmpty                                => BadRequest
      case _: AclCannotContainEmptyPermissionCollection => BadRequest
      case _: AclNotFound                               => NotFound
      case _: IncorrectRev                              => Conflict
      case _: UnknownPermissions                        => BadRequest
    }
} 
Example 139
Source File: AclEvent.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.acls

import java.time.Instant

import ch.epfl.bluebrain.nexus.iam.types.Identity
import ch.epfl.bluebrain.nexus.iam.types.Identity.Subject
import ch.epfl.bluebrain.nexus.rdf.Iri.Path
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.Contexts._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import io.circe.Encoder
import io.circe.generic.extras.Configuration

import scala.annotation.nowarn


  final case class AclDeleted(
      path: Path,
      rev: Long,
      instant: Instant,
      subject: Subject
  ) extends AclEvent

  object JsonLd {
    import io.circe.generic.extras.semiauto._

    @nowarn("cat=unused")
    implicit def aclEventEncoder(implicit httpConfig: HttpConfig): Encoder[AclEvent] = {
      implicit val config: Configuration                    = Configuration.default
        .withDiscriminator("@type")
        .copy(transformMemberNames = {
          case "rev"     => "_rev"
          case "instant" => "_instant"
          case "subject" => "_subject"
          case "path"    => "_path"
          case other     => other
        })
      implicit val arrayEncoder: Encoder[AccessControlList] = AccessControlList.aclArrayEncoder
      implicit val subjectEncoder: Encoder[Subject]         = Identity.subjectIdEncoder
      deriveConfiguredEncoder[AclEvent]
        .mapJson { json =>
          json
            .addContext(iamCtxUri)
            .addContext(resourceCtxUri)
        }
    }
  }
} 
Example 140
Source File: ActiveRealm.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.realms

import ch.epfl.bluebrain.nexus.iam.types.GrantType.Camel._
import ch.epfl.bluebrain.nexus.iam.types.{GrantType, Label}
import ch.epfl.bluebrain.nexus.rdf.Iri.Url
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.Vocabulary.nxv
import com.nimbusds.jose.jwk.{JWK, JWKSet}
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}

import scala.util.Try


final case class ActiveRealm(
    id: Label,
    name: String,
    openIdConfig: Url,
    issuer: String,
    grantTypes: Set[GrantType],
    logo: Option[Url],
    authorizationEndpoint: Url,
    tokenEndpoint: Url,
    userInfoEndpoint: Url,
    revocationEndpoint: Option[Url],
    endSessionEndpoint: Option[Url],
    keys: Set[Json]
) {

  private[realms] lazy val keySet: JWKSet = {
    val jwks = keys.foldLeft(Set.empty[JWK]) {
      case (acc, e) => Try(JWK.parse(e.noSpaces)).map(acc + _).getOrElse(acc)
    }
    import scala.jdk.CollectionConverters._
    new JWKSet(jwks.toList.asJava)
  }
}

object ActiveRealm {
  implicit private[ActiveRealm] val config: Configuration = Configuration.default.copy(transformMemberNames = {
    case "issuer"                => nxv.issuer.prefix
    case "grantTypes"            => nxv.grantTypes.prefix
    case "authorizationEndpoint" => nxv.authorizationEndpoint.prefix
    case "tokenEndpoint"         => nxv.tokenEndpoint.prefix
    case "userInfoEndpoint"      => nxv.userInfoEndpoint.prefix
    case "revocationEndpoint"    => nxv.revocationEndpoint.prefix
    case "endSessionEndpoint"    => nxv.endSessionEndpoint.prefix
    case other                   => other
  })
  implicit val activeEncoder: Encoder[ActiveRealm] = {
    val default = deriveConfiguredEncoder[ActiveRealm]
    Encoder
      .instance[ActiveRealm] { realm =>
        default(realm) deepMerge Json.obj(
          nxv.label.prefix      -> Json.fromString(realm.id.value),
          nxv.deprecated.prefix -> Json.fromBoolean(false)
        )
      }
      .mapJson(_.removeKeys("keys", "id"))
  }
} 
Example 141
Source File: ResourceF.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.types

import java.time.Instant

import ch.epfl.bluebrain.nexus.iam.syntax._
import ch.epfl.bluebrain.nexus.iam.types.Identity.Subject
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.Contexts._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import ch.epfl.bluebrain.nexus.service.config.Vocabulary.nxv
import io.circe.syntax._
import io.circe.{Encoder, Json}


  def unit(
      id: AbsoluteIri,
      rev: Long,
      types: Set[AbsoluteIri],
      createdAt: Instant,
      createdBy: Subject,
      updatedAt: Instant,
      updatedBy: Subject
  ): ResourceF[Unit] =
    ResourceF(id, rev, types, createdAt, createdBy, updatedAt, updatedBy, ())

  implicit val permsEncoder: Encoder[Set[Permission]]                                         =
    Encoder.instance(perms => Json.obj("permissions" -> Json.fromValues(perms.toList.sortBy(_.value).map(_.asJson))))

  implicit def resourceFEncoder[A: Encoder](implicit http: HttpConfig): Encoder[ResourceF[A]] =
    Encoder.encodeJson.contramap { r => resourceMetaEncoder.apply(r.discard) deepMerge r.value.asJson }

  implicit def resourceMetaEncoder(implicit http: HttpConfig): Encoder[ResourceMetadata] =
    Encoder.encodeJson.contramap {
      case ResourceF(id, rev, types, createdAt, createdBy, updatedAt, updatedBy, _: Unit) =>
        val jsonTypes = types.toList match {
          case Nil      => Json.Null
          case t :: Nil => Json.fromString(t.lastSegment.getOrElse(t.asString))
          case _        => Json.arr(types.map(t => Json.fromString(t.lastSegment.getOrElse(t.asString))).toSeq: _*)
        }
        Json
          .obj(
            "@id"                -> id.asJson,
            "@type"              -> jsonTypes,
            nxv.rev.prefix       -> Json.fromLong(rev),
            nxv.createdBy.prefix -> createdBy.id.asJson,
            nxv.updatedBy.prefix -> updatedBy.id.asJson,
            nxv.createdAt.prefix -> Json.fromString(createdAt.toString),
            nxv.updatedAt.prefix -> Json.fromString(updatedAt.toString)
          )
          .addContext(iamCtxUri)
          .addContext(resourceCtxUri)
    }
} 
Example 142
Source File: Caller.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.types

import ch.epfl.bluebrain.nexus.iam.acls.AccessControlLists
import ch.epfl.bluebrain.nexus.iam.types.Identity.{Anonymous, Subject}
import ch.epfl.bluebrain.nexus.kg.resources.ProjectIdentifier.ProjectLabel
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.Contexts._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import io.circe.{Encoder, Json}


  val anonymous: Caller = Caller(Anonymous: Subject, Set[Identity](Anonymous))

  object JsonLd {
    implicit final def callerEncoder(implicit
        I: Encoder[Identity],
        http: HttpConfig
    ): Encoder[Caller] =
      Encoder.instance[Caller] { caller =>
        Json
          .obj(
            "identities" -> Encoder.encodeList(I)(caller.identities.toList.sortBy(_.id.asUri))
          )
          .addContext(iamCtxUri)
          .addContext(resourceCtxUri)
      }
  }
} 
Example 143
Source File: TokenRejection.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.auth

import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}

import scala.annotation.nowarn


  final case object InvalidAccessToken
      extends TokenRejection(
        "The token is invalid; possible causes are: incorrect signature, the token is expired or the 'nbf' value was not met."
      )

  @nowarn("cat=unused")
  implicit val tokenRejectionEncoder: Encoder[TokenRejection] = {
    implicit val rejectionConfig: Configuration = Configuration.default.withDiscriminator("@type")
    val enc                                     = deriveConfiguredEncoder[TokenRejection]
    Encoder.instance(r => enc(r) deepMerge Json.obj("reason" -> Json.fromString(r.msg)))
  }
} 
Example 144
Source File: EventSerializer.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.io

import java.nio.charset.Charset

import akka.actor.ExtendedActorSystem
import akka.serialization.SerializerWithStringManifest
import ch.epfl.bluebrain.nexus.iam.acls.AclEvent
import ch.epfl.bluebrain.nexus.iam.permissions.PermissionsEvent
import ch.epfl.bluebrain.nexus.iam.realms.RealmEvent
import ch.epfl.bluebrain.nexus.iam.types.GrantType.Camel._
import ch.epfl.bluebrain.nexus.rdf.Iri.Url
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import ch.epfl.bluebrain.nexus.service.config.Settings
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto._
import io.circe.parser._
import io.circe.syntax._
import io.circe.{Decoder, Encoder, Printer}


class EventSerializer(system: ExtendedActorSystem) extends SerializerWithStringManifest {
  private val utf8 = Charset.forName("UTF-8")

  private val printer = Printer.noSpaces.copy(dropNullValues = true)

  implicit private[io] val http: HttpConfig = Settings(system).serviceConfig.http

  implicit private[io] val config: Configuration = Configuration.default.withDiscriminator("@type")

  implicit private[io] val urlEncoder: Encoder[Url] =
    Encoder.encodeString.contramap(_.asUri)
  implicit private[io] val urlDecoder: Decoder[Url] =
    Decoder.decodeString.emap(Url.apply)

  implicit private[io] val permissionEventEncoder: Encoder[PermissionsEvent] = deriveConfiguredEncoder[PermissionsEvent]
  implicit private[io] val permissionEventDecoder: Decoder[PermissionsEvent] = deriveConfiguredDecoder[PermissionsEvent]
  implicit private[io] val aclEventEncoder: Encoder[AclEvent]                = deriveConfiguredEncoder[AclEvent]
  implicit private[io] val aclEventDecoder: Decoder[AclEvent]                = deriveConfiguredDecoder[AclEvent]
  implicit private[io] val realmEventEncoder: Encoder[RealmEvent]            = deriveConfiguredEncoder[RealmEvent]
  implicit private[io] val realmEventDecoder: Decoder[RealmEvent]            = deriveConfiguredDecoder[RealmEvent]

  override val identifier: Int = 1225

  override def manifest(o: AnyRef): String                              =
    o match {
      case _: PermissionsEvent => "permissions-event"
      case _: AclEvent         => "acl-event"
      case _: RealmEvent       => "realm-event"
      case other               =>
        throw new IllegalArgumentException(
          s"Cannot determine manifest for unknown type: '${other.getClass.getCanonicalName}'"
        )
    }
  override def toBinary(o: AnyRef): Array[Byte]                         =
    o match {
      case ev: PermissionsEvent => ev.asJson.printWith(printer).getBytes(utf8)
      case ev: AclEvent         => ev.asJson.printWith(printer).getBytes(utf8)
      case ev: RealmEvent       => ev.asJson.printWith(printer).getBytes(utf8)
      case other                =>
        throw new IllegalArgumentException(s"Cannot serialize unknown type: '${other.getClass.getCanonicalName}'")
    }
  override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef =
    manifest match {
      case "permissions-event" =>
        val str = new String(bytes, utf8)
        decode[PermissionsEvent](str)
          .getOrElse(throw new IllegalArgumentException(s"Cannot deserialize value: '$str' to 'PermissionsEvent'"))
      case "acl-event"         =>
        val str = new String(bytes, utf8)
        decode[AclEvent](str)
          .getOrElse(throw new IllegalArgumentException(s"Cannot deserialize value: '$str' to 'AclEvent'"))
      case "realm-event"       =>
        val str = new String(bytes, utf8)
        decode[RealmEvent](str)
          .getOrElse(throw new IllegalArgumentException(s"Cannot deserialize value: '$str' to 'RealmEvent'"))
      case other               =>
        throw new IllegalArgumentException(s"Cannot deserialize type with unknown manifest: '$other'")
    }
} 
Example 145
Source File: ServiceError.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.service.exceptions

import ch.epfl.bluebrain.nexus.admin.exceptions.AdminError
import ch.epfl.bluebrain.nexus.iam.types.IamError
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.Contexts._
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}

import scala.annotation.nowarn

@SuppressWarnings(Array("IncorrectlyNamedExceptions"))
abstract class ServiceError(val msg: String) extends Exception with Product with Serializable

object ServiceError {

  
  @SuppressWarnings(Array("IncorrectlyNamedExceptions"))
  final case class InternalError(reason: String) extends ServiceError(reason)

  @nowarn("cat=unused")
  implicit val internalErrorEncoder: Encoder[InternalError] = {
    implicit val rejectionConfig: Configuration = Configuration.default.withDiscriminator("@type")
    val enc                                     = deriveConfiguredEncoder[InternalError].mapJson(_ addContext errorCtxUri)
    Encoder.instance(r => {
      enc(r) deepMerge Json
        .obj("@type" -> Json.fromString(r.getClass.getSimpleName), "reason" -> Json.fromString(r.msg))
    })
  }

  implicit val serviceErrorEncoder: Encoder[ServiceError] = Encoder.instance {
    case i: IamError   => IamError.iamErrorEncoder(i)
    case a: AdminError => AdminError.adminErrorEncoder(a)
    case r             =>
      Json.obj(
        "@type"  -> Json.fromString(r.getClass.getSimpleName),
        "reason" -> Json.fromString(r.msg)
      ) addContext errorCtxUri
  }
} 
Example 146
Source File: QueryResultSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.commons.search

import cats.syntax.functor._
import ch.epfl.bluebrain.nexus.commons.search.QueryResult.ScoredQueryResult
import io.circe.generic.auto._
import io.circe.{Encoder, Json}
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

class QueryResultSpec extends AnyWordSpecLike with Matchers {

  "A QueryResult Functor" should {
    implicit val queryResultEncoder: Encoder[ScoredQueryResult[Int]] =
      Encoder.encodeJson.contramap { qr =>
        Json.obj(
          "resultId" -> Json.fromString("/some/path"),
          "score"    -> Json.fromFloatOrString(qr.score),
          "source"   -> Json.fromInt(qr.source)
        )
      }
    "transform the source value" in {
      ScoredQueryResult(1f, 1).map(_ + 1) shouldEqual ScoredQueryResult(1f, 2)
    }
    "encodes a queryResult" in {
      import io.circe.syntax._
      val result = ScoredQueryResult(1f, 1): QueryResult[Int]
      result.asJson shouldEqual Json.obj(
        "resultId" -> Json.fromString("/some/path"),
        "score"    -> Json.fromFloatOrString(1f),
        "source"   -> Json.fromInt(result.source)
      )
    }
  }

} 
Example 147
Source File: EventRoutesSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.NotUsed
import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.headers.`Last-Event-ID`
import akka.http.scaladsl.model.sse.ServerSentEvent
import akka.persistence.query.{EventEnvelope, NoOffset, Offset, Sequence}
import akka.stream.scaladsl.Source
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission}
import ch.epfl.bluebrain.nexus.kg.resources.Event
import ch.epfl.bluebrain.nexus.kg.routes.EventRoutesSpec.TestableEventRoutes
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig
import ch.epfl.bluebrain.nexus.rdf.Iri.Path._
import io.circe.Encoder
import monix.eval.Task

class EventRoutesSpec extends EventsSpecBase {

  private val aclsApi = mock[Acls[Task]]
  private val realms  = mock[Realms[Task]]

  val eventRoutes = new TestableEventRoutes(events, aclsApi, realms, caller)

  "EventRoutes" should {
    val read = Permission.unsafe("resources/read")
    aclsApi.hasPermission("org" / "project", read)(caller) shouldReturn Task.pure(true)
    aclsApi.hasPermission(/ + "org", read)(caller) shouldReturn Task.pure(true)

    "return all events for a project" in {
      Get("/") ~> eventRoutes.routes(project) ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected)
      }
    }

    "return all events for a project from the last seen" in {
      Get("/").addHeader(`Last-Event-ID`(0.toString)) ~> eventRoutes.routes(project) ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected, 1)
      }
    }

    "return all events for an organization" in {
      Get("/") ~> eventRoutes.routes(organization) ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected)
      }
    }

    "return all events for an organization from the last seen" in {
      Get("/").addHeader(`Last-Event-ID`(0.toString)) ~> eventRoutes.routes(organization) ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected, 1)
      }
    }
  }

}

object EventRoutesSpec {

  class TestableEventRoutes(events: List[Event], acls: Acls[Task], realms: Realms[Task], caller: Caller)(implicit
      as: ActorSystem,
      config: ServiceConfig
  ) extends EventRoutes(acls, realms, caller) {

    private val envelopes = events.zipWithIndex.map {
      case (ev, idx) =>
        EventEnvelope(Sequence(idx.toLong), "persistenceid", 1L, ev, 1L)
    }

    override protected def source(
        tag: String,
        offset: Offset
    )(implicit enc: Encoder[Event]): Source[ServerSentEvent, NotUsed] = {
      val toDrop = offset match {
        case NoOffset    => 0
        case Sequence(v) => v + 1
      }
      Source(envelopes).drop(toDrop).flatMapConcat(ee => Source(eventToSse(ee).toList))
    }
  }
} 
Example 148
Source File: GlobalEventRoutesSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.NotUsed
import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.headers.`Last-Event-ID`
import akka.http.scaladsl.model.sse.ServerSentEvent
import akka.persistence.query.{EventEnvelope, NoOffset, Offset, Sequence}
import akka.stream.scaladsl.Source
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.types.Caller
import ch.epfl.bluebrain.nexus.kg.resources.Event
import ch.epfl.bluebrain.nexus.kg.routes.GlobalEventRoutesSpec.TestableEventRoutes
import ch.epfl.bluebrain.nexus.rdf.Iri.Path
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig
import io.circe.Encoder
import monix.eval.Task

class GlobalEventRoutesSpec extends EventsSpecBase {

  private val aclsApi = mock[Acls[Task]]
  private val realms  = mock[Realms[Task]]

  val routes = new TestableEventRoutes(events, aclsApi, realms, caller).routes
  aclsApi.hasPermission(Path./, read)(caller) shouldReturn Task.pure(true)

  "GlobalEventRoutes" should {

    "return all events for a project" in {
      Get("/") ~> routes ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected)
      }
    }

    "return all events for a project from the last seen" in {
      Get("/").addHeader(`Last-Event-ID`(0.toString)) ~> routes ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected, 1)
      }
    }
  }
}

object GlobalEventRoutesSpec {

  class TestableEventRoutes(events: List[Event], acls: Acls[Task], realms: Realms[Task], caller: Caller)(implicit
      as: ActorSystem,
      config: ServiceConfig
  ) extends GlobalEventRoutes(acls, realms, caller) {

    private val envelopes = events.zipWithIndex.map {
      case (ev, idx) =>
        EventEnvelope(Sequence(idx.toLong), "persistenceid", 1L, ev, 1L)
    }

    override protected def source(
        tag: String,
        offset: Offset
    )(implicit enc: Encoder[Event]): Source[ServerSentEvent, NotUsed] = {
      val toDrop = offset match {
        case NoOffset    => 0
        case Sequence(v) => v + 1
      }
      Source(envelopes).drop(toDrop).flatMapConcat(ee => Source(eventToSse(ee).toList))
    }
  }
} 
Example 149
Source File: GrantTypeSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.types

import ch.epfl.bluebrain.nexus.util.EitherValues
import ch.epfl.bluebrain.nexus.iam.types.GrantType._
import io.circe.{Decoder, Encoder, Json}
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike
import org.scalatest.Inspectors

class GrantTypeSpec extends AnyWordSpecLike with Matchers with Inspectors with EitherValues {

  "A GrantType" when {
    "using Camel encoders" should {
      import GrantType.Camel._
      val map = Map(
        AuthorizationCode -> "authorizationCode",
        Implicit          -> "implicit",
        Password          -> "password",
        ClientCredentials -> "clientCredentials",
        DeviceCode        -> "deviceCode",
        RefreshToken      -> "refreshToken"
      )
      "be encoded properly" in {
        val encoder = implicitly[Encoder[GrantType]]
        forAll(map.toList) {
          case (gt, expected) =>
            encoder(gt) shouldEqual Json.fromString(expected)
        }
      }
      "be decoded properly" in {
        val decoder = implicitly[Decoder[GrantType]]
        forAll(map.toList) {
          case (expected, gt) =>
            decoder.decodeJson(Json.fromString(gt)).rightValue shouldEqual expected
        }
      }
      "fail to decode for unknown string" in {
        val decoder = implicitly[Decoder[GrantType]]
        decoder.decodeJson(Json.fromString("incorrect")).leftValue
      }
    }
    "using Snake encoders" should {
      import GrantType.Snake._
      val map = Map(
        AuthorizationCode -> "authorization_code",
        Implicit          -> "implicit",
        Password          -> "password",
        ClientCredentials -> "client_credentials",
        DeviceCode        -> "device_code",
        RefreshToken      -> "refresh_token"
      )
      "be encoded properly" in {
        val encoder = implicitly[Encoder[GrantType]]
        forAll(map.toList) {
          case (gt, expected) =>
            encoder(gt) shouldEqual Json.fromString(expected)
        }
      }
      "be decoded properly" in {
        val decoder = implicitly[Decoder[GrantType]]
        forAll(map.toList) {
          case (expected, gtString) =>
            decoder.decodeJson(Json.fromString(gtString)).rightValue shouldEqual expected
        }
      }
      "fail to decode for unknown string" in {
        val decoder = implicitly[Decoder[GrantType]]
        decoder.decodeJson(Json.fromString("incorrect")).leftValue
      }
    }
  }

} 
Example 150
Source File: RdfCirceInstances.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.rdf.jsonld.instances

import ch.epfl.bluebrain.nexus.rdf.{GraphDecoder, GraphEncoder, Iri}
import ch.epfl.bluebrain.nexus.rdf.Iri.{AbsoluteIri, Path, RelativeIri, Url, Urn}
import io.circe.{Decoder, Encoder, Json}
import io.circe.parser._
import cats.implicits._

trait RdfCirceInstances {
  implicit final val absoluteIriEncoder: Encoder[AbsoluteIri] = Encoder.encodeString.contramap(_.asString)
  implicit final val absoluteIriDecoder: Decoder[AbsoluteIri] = Decoder.decodeString.emap(Iri.absolute)

  implicit final val iriPathEncoder: Encoder[Path] = Encoder.encodeString.contramap(_.asString)
  implicit final val iriPathDecoder: Decoder[Path] = Decoder.decodeString.emap(Path.apply)

  implicit final val iriEncoder: Encoder[Iri] = Encoder.encodeString.contramap(_.asString)
  implicit final val iriDecoder: Decoder[Iri] = Decoder.decodeString.emap(Iri.apply)

  implicit final def urlEncoder(implicit E: Encoder[AbsoluteIri]): Encoder[Url] = E.contramap(identity)
  implicit final val urlDecoder: Decoder[Url]                                   = Decoder.decodeString.emap(Url.apply)

  implicit final def urnEncoder(implicit E: Encoder[AbsoluteIri]): Encoder[Urn] = E.contramap(identity)
  implicit final val urnDecoder: Decoder[Urn]                                   = Decoder.decodeString.emap(Urn.apply)

  implicit final val relativeIriEncoder: Encoder[RelativeIri] = Encoder.encodeString.contramap(_.asString)
  implicit final val relativeIriDecoder: Decoder[RelativeIri] = Decoder.decodeString.emap(Iri.relative)

  implicit final val jsonGraphEncoder: GraphEncoder[Json] = GraphEncoder.graphEncodeString.contramap(_.noSpaces)
  implicit final val jsonGraphDecoder: GraphDecoder[Json] =
    GraphDecoder.graphDecodeString.emap(str => parse(str).leftMap(_.message))
}

object RdfCirceInstances extends RdfCirceInstances 
Example 151
Source File: ValidationReport.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.rdf.shacl

import cats.implicits._
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import ch.epfl.bluebrain.nexus.rdf.Node.{BNode, IriNode}
import ch.epfl.bluebrain.nexus.rdf.jena.syntax.all._
import ch.epfl.bluebrain.nexus.rdf.jsonld.syntax._
import ch.epfl.bluebrain.nexus.rdf.shacl.Vocabulary._
import ch.epfl.bluebrain.nexus.rdf.syntax.all._
import io.circe.parser.parse
import io.circe.{Encoder, Json}
import org.apache.jena.rdf.model.Resource

import scala.io.Source


  def isValid(ignoreTargetedNodes: Boolean = false): Boolean =
    (ignoreTargetedNodes && conforms) || (!ignoreTargetedNodes && targetedNodes > 0 && conforms)
}

object ValidationReport {

  final def apply(report: Resource): Either[String, ValidationReport] =
    // format: off
    for {
      tmp     <- report.getModel.asRdfGraph(BNode())
      subject <- tmp.triples.find { case (_, p ,_ ) => p == IriNode(sh.conforms) }.map(_._1).toRight("Unable to find predicate sh:conforms in the validation report graph")
      graph    = tmp.withRoot(subject)
      cursor   = graph.cursor
      conforms <- cursor.down(sh.conforms).as[Boolean].leftMap(_.message)
      targeted <- cursor.down(nxsh.targetedNodes).as[Int].leftMap(_.message)
      json     <- graph.toJson(shaclCtx)
    } yield ValidationReport(conforms, targeted, json.removeKeys("@context", "@id").addContext(shaclCtxUri))
  // format: on

  private val shaclCtxUri: AbsoluteIri = url"https://bluebrain.github.io/nexus/contexts/shacl-20170720.json"
  private val shaclCtx: Json           = jsonContentOf("/shacl-context-resp.json")

  implicit val reportEncoder: Encoder[ValidationReport] = Encoder.instance(_.json)

  private def jsonContentOf(resourcePath: String): Json =
    parse(Source.fromInputStream(getClass.getResourceAsStream(resourcePath)).mkString)
      .getOrElse(throw new IllegalArgumentException)
} 
Example 152
Source File: JsonLdCirceSupport.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.storage

import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller}
import akka.http.scaladsl.model.MediaTypes.`application/json`
import akka.http.scaladsl.model.{ContentTypeRange, HttpEntity}
import ch.epfl.bluebrain.nexus.commons.http.RdfMediaTypes
import ch.epfl.bluebrain.nexus.storage.JsonLdCirceSupport.{sortKeys, OrderedKeys}
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import io.circe.syntax._
import io.circe.{Encoder, Json, JsonObject, Printer}

import scala.collection.immutable.Seq


  def sortKeys(json: Json)(implicit keys: OrderedKeys): Json = {

    implicit val customStringOrdering: Ordering[String] = new Ordering[String] {
      private val middlePos = keys.withPosition("")

      private def position(key: String): Int = keys.withPosition.getOrElse(key, middlePos)

      override def compare(x: String, y: String): Int = {
        val posX = position(x)
        val posY = position(y)
        if (posX == middlePos && posY == middlePos) x compareTo y
        else posX compareTo posY
      }
    }

    def canonicalJson(json: Json): Json =
      json.arrayOrObject[Json](json, arr => Json.fromValues(arr.map(canonicalJson)), obj => sorted(obj).asJson)

    def sorted(jObj: JsonObject): JsonObject =
      JsonObject.fromIterable(jObj.toVector.sortBy(_._1).map { case (k, v) => k -> canonicalJson(v) })

    canonicalJson(json)
  }
} 
Example 153
Source File: StorageError.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.storage

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.Uri.Path
import ch.epfl.bluebrain.nexus.storage.routes.StatusFrom
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}

import scala.annotation.nowarn


  final case class OperationTimedOut(override val msg: String) extends StorageError(msg)

  @nowarn("cat=unused")
  implicit private val config: Configuration = Configuration.default.withDiscriminator("@type")

  private val derivedEncoder = deriveConfiguredEncoder[StorageError].mapJson(jsonError)

  implicit val storageErrorEncoder: Encoder[StorageError]       =
    Encoder.instance(r => derivedEncoder(r) deepMerge Json.obj("reason" -> Json.fromString(r.msg)))

  implicit val storageErrorStatusFrom: StatusFrom[StorageError] = {
    case _: PathNotFound      => StatusCodes.NotFound
    case _: PathInvalid       => StatusCodes.BadRequest
    case AuthenticationFailed => StatusCodes.Unauthorized
    case AuthorizationFailed  => StatusCodes.Forbidden
    case _                    => StatusCodes.InternalServerError
  }
} 
Example 154
Source File: File.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.storage

import akka.http.scaladsl.model.{ContentType, Uri}
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.storage.config.Contexts.resourceCtxUri
import scala.annotation.nowarn
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto._
import io.circe.{Decoder, Encoder}

// $COVERAGE-OFF$
object File {

  @nowarn("cat=unused")
  implicit private val config: Configuration = Configuration.default
    .copy(transformMemberNames = {
      case "@context" => "@context"
      case key        => s"_$key"
    })

  
  final case class Digest(algorithm: String, value: String)

  object Digest {
    val empty: Digest                           = Digest("", "")
    implicit val digestEncoder: Encoder[Digest] = deriveConfiguredEncoder[Digest]
    implicit val digestDecoder: Decoder[Digest] = deriveConfiguredDecoder[Digest]
  }

}
// $COVERAGE-ON$ 
Example 155
Source File: Rejection.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.storage

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.Uri.Path
import akka.http.scaladsl.server.{Rejection => AkkaRejection}
import ch.epfl.bluebrain.nexus.storage.routes.StatusFrom
import scala.annotation.nowarn
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}


  final case class EmptyFilename(name: String)

  implicit def statusCodeFrom: StatusFrom[Rejection] =
    StatusFrom {
      case _: PathContainsLinks => StatusCodes.BadRequest
      case _: PathAlreadyExists => StatusCodes.Conflict
      case _: BucketNotFound    => StatusCodes.NotFound
      case _: PathNotFound      => StatusCodes.NotFound
    }

  @nowarn("cat=unused")
  implicit val rejectionEncoder: Encoder[Rejection] = {
    implicit val rejectionConfig: Configuration = Configuration.default.withDiscriminator("@type")
    val enc                                     = deriveConfiguredEncoder[Rejection].mapJson(jsonError)
    Encoder.instance(r => enc(r) deepMerge Json.obj("reason" -> Json.fromString(r.msg)))
  }
} 
Example 156
Source File: HeroFragmentQuery.scala    From sbt-graphql   with Apache License 2.0 5 votes vote down vote up
import io.circe.{ Decoder, Encoder }
import io.circe.generic.semiauto.{ deriveDecoder, deriveEncoder }
import sangria.macros._
import types._
object HeroFragmentQuery {
  object HeroFragmentQuery extends GraphQLQuery {
    val document: sangria.ast.Document = graphql"""query HeroFragmentQuery {
  hero {
    ...CharacterInfo
  }
  human(id: "Lea") {
    ...CharacterInfo
  }
}

fragment CharacterInfo on Character {
  name
}"""
    case class Variables()
    object Variables { implicit val jsonEncoder: Encoder[Variables] = deriveEncoder[Variables] }
    case class Data(hero: Hero, human: Option[Human])
    object Data { implicit val jsonDecoder: Decoder[Data] = deriveDecoder[Data] }
    case class Hero(name: Option[String]) extends CharacterInfo
    object Hero {
      implicit val jsonDecoder: Decoder[Hero] = deriveDecoder[Hero]
      implicit val jsonEncoder: Encoder[Hero] = deriveEncoder[Hero]
    }
    case class Human(name: Option[String]) extends CharacterInfo
    object Human {
      implicit val jsonDecoder: Decoder[Human] = deriveDecoder[Human]
      implicit val jsonEncoder: Encoder[Human] = deriveEncoder[Human]
    }
  }
} 
Example 157
Source File: EpisodeEnumTypes.scala    From sbt-graphql   with Apache License 2.0 5 votes vote down vote up
import io.circe.{ Decoder, Encoder }
import io.circe.generic.semiauto.{ deriveDecoder, deriveEncoder }
object types {
  sealed trait Episode
  object Episode {
    case object NEWHOPE extends Episode
    case object EMPIRE extends Episode
    case object JEDI extends Episode
    implicit val jsonDecoder: Decoder[Episode] = Decoder.decodeString.emap({
      case "NEWHOPE" =>
        Right(NEWHOPE)
      case "EMPIRE" =>
        Right(EMPIRE)
      case "JEDI" =>
        Right(JEDI)
      case other =>
        Left("invalid enum value: " + other)
    })
    implicit val jsonEncoder: Encoder[Episode] = Encoder.encodeString.contramap({
      case NEWHOPE => "NEWHOPE"
      case EMPIRE => "EMPIRE"
      case JEDI => "JEDI"
    })
  }
} 
Example 158
Source File: HeroAndFriends.scala    From sbt-graphql   with Apache License 2.0 5 votes vote down vote up
import io.circe.{ Decoder, Encoder }
import io.circe.generic.semiauto.{ deriveDecoder, deriveEncoder }
import sangria.macros._
import types._
object HeroAndFriends {
  object HeroAndFriends extends GraphQLQuery {
    val document: sangria.ast.Document = graphql"""query HeroAndFriends {
  hero {
    name
    friends {
      name
      friends {
        name
        friends {
          name
          friends {
            name
          }
        }
      }
    }
  }
}"""
    case class Variables()
    object Variables { implicit val jsonEncoder: Encoder[Variables] = deriveEncoder[Variables] }
    case class Data(hero: Hero)
    object Data { implicit val jsonDecoder: Decoder[Data] = deriveDecoder[Data] }
    case class Hero(name: Option[String], friends: Option[List[Option[Hero.Friends]]])
    object Hero {
      implicit val jsonDecoder: Decoder[Hero] = deriveDecoder[Hero]
      implicit val jsonEncoder: Encoder[Hero] = deriveEncoder[Hero]
      case class Friends(name: Option[String], friends: Option[List[Option[Friends.Friends]]])
      object Friends {
        implicit val jsonDecoder: Decoder[Friends] = deriveDecoder[Friends]
        implicit val jsonEncoder: Encoder[Friends] = deriveEncoder[Friends]
        case class Friends(name: Option[String], friends: Option[List[Option[Friends.Friends]]])
        object Friends {
          implicit val jsonDecoder: Decoder[Friends] = deriveDecoder[Friends]
          implicit val jsonEncoder: Encoder[Friends] = deriveEncoder[Friends]
          case class Friends(name: Option[String], friends: Option[List[Option[Friends.Friends]]])
          object Friends {
            implicit val jsonDecoder: Decoder[Friends] = deriveDecoder[Friends]
            implicit val jsonEncoder: Encoder[Friends] = deriveEncoder[Friends]
            case class Friends(name: Option[String])
            object Friends {
              implicit val jsonDecoder: Decoder[Friends] = deriveDecoder[Friends]
              implicit val jsonEncoder: Encoder[Friends] = deriveEncoder[Friends]
            }
          }
        }
      }
    }
  }
} 
Example 159
Source File: InputVariables.scala    From sbt-graphql   with Apache License 2.0 5 votes vote down vote up
import io.circe.{ Decoder, Encoder }
import io.circe.generic.semiauto.{ deriveDecoder, deriveEncoder }
import sangria.macros._
import types._
object InputVariables {
  object InputVariables extends GraphQLQuery {
    val document: sangria.ast.Document = graphql"""query InputVariables($$humanId: String!) {
  human(id: $$humanId) {
    name
    homePlanet
  }
}"""
    case class Variables(humanId: String)
    object Variables { implicit val jsonEncoder: Encoder[Variables] = deriveEncoder[Variables] }
    case class Data(human: Option[Human])
    object Data { implicit val jsonDecoder: Decoder[Data] = deriveDecoder[Data] }
    case class Human(name: Option[String], homePlanet: Option[String])
    object Human {
      implicit val jsonDecoder: Decoder[Human] = deriveDecoder[Human]
      implicit val jsonEncoder: Encoder[Human] = deriveEncoder[Human]
    }
  }
} 
Example 160
Source File: SearchQuery.scala    From sbt-graphql   with Apache License 2.0 5 votes vote down vote up
import io.circe.{ Decoder, Encoder }
import io.circe.generic.semiauto.{ deriveDecoder, deriveEncoder }
import sangria.macros._
import types._
object SearchQuery {
  object SearchQuery extends GraphQLQuery {
    val document: sangria.ast.Document = graphql"""query SearchQuery($$text: String!) {
  search(text: $$text) {
    __typename
    ... on Human {
      name
      secretBackstory
    }
    ... on Droid {
      name
      primaryFunction
    }
    ... on Starship {
      name
    }
  }
}"""
    case class Variables(text: String)
    object Variables { implicit val jsonEncoder: Encoder[Variables] = deriveEncoder[Variables] }
    case class Data(search: List[Search])
    object Data { implicit val jsonDecoder: Decoder[Data] = deriveDecoder[Data] }
    sealed trait Search {
      def __typename: String
      def name: Option[String]
    }
    object Search {
      case class Human(__typename: String, name: Option[String], secretBackstory: Option[String]) extends Search
      object Human {
        implicit val jsonDecoder: Decoder[Human] = deriveDecoder[Human]
        implicit val jsonEncoder: Encoder[Human] = deriveEncoder[Human]
      }
      case class Droid(__typename: String, name: Option[String], primaryFunction: Option[String]) extends Search
      object Droid {
        implicit val jsonDecoder: Decoder[Droid] = deriveDecoder[Droid]
        implicit val jsonEncoder: Encoder[Droid] = deriveEncoder[Droid]
      }
      case class Starship(__typename: String, name: Option[String]) extends Search
      object Starship {
        implicit val jsonDecoder: Decoder[Starship] = deriveDecoder[Starship]
        implicit val jsonEncoder: Encoder[Starship] = deriveEncoder[Starship]
      }
      implicit val jsonDecoder: Decoder[Search] = for (typeDiscriminator <- Decoder[String].prepare(_.downField("__typename")); value <- typeDiscriminator match {
        case "Human" =>
          Decoder[Human]
        case "Droid" =>
          Decoder[Droid]
        case "Starship" =>
          Decoder[Starship]
        case other =>
          Decoder.failedWithMessage("invalid type: " + other)
      }) yield value
    }
  }
} 
Example 161
Source File: HeroNameQuery.scala    From sbt-graphql   with Apache License 2.0 5 votes vote down vote up
import io.circe.{ Decoder, Encoder }
import io.circe.generic.semiauto.{ deriveDecoder, deriveEncoder }
import sangria.macros._
import types._
object HeroNameQuery {
  object HeroNameQuery extends GraphQLQuery {
    val document: sangria.ast.Document = graphql"""query HeroNameQuery {
  hero {
    name
  }
}"""
    case class Variables()
    object Variables { implicit val jsonEncoder: Encoder[Variables] = deriveEncoder[Variables] }
    case class Data(hero: Hero)
    object Data { implicit val jsonDecoder: Decoder[Data] = deriveDecoder[Data] }
    case class Hero(name: Option[String])
    object Hero {
      implicit val jsonDecoder: Decoder[Hero] = deriveDecoder[Hero]
      implicit val jsonEncoder: Encoder[Hero] = deriveEncoder[Hero]
    }
  }
} 
Example 162
Source File: EpisodeEnum.scala    From sbt-graphql   with Apache License 2.0 5 votes vote down vote up
import io.circe.{ Decoder, Encoder }
import io.circe.generic.semiauto.{ deriveDecoder, deriveEncoder }
import sangria.macros._
import types._
object EpisodeEnum {
  object EpisodeEnum extends GraphQLQuery {
    val document: sangria.ast.Document = graphql"""query EpisodeEnum {
  hero {
    name
    appearsIn
  }
}"""
    case class Variables()
    object Variables { implicit val jsonEncoder: Encoder[Variables] = deriveEncoder[Variables] }
    case class Data(hero: Hero)
    object Data { implicit val jsonDecoder: Decoder[Data] = deriveDecoder[Data] }
    case class Hero(name: Option[String], appearsIn: Option[List[Option[Episode]]])
    object Hero {
      implicit val jsonDecoder: Decoder[Hero] = deriveDecoder[Hero]
      implicit val jsonEncoder: Encoder[Hero] = deriveEncoder[Hero]
    }
  }
} 
Example 163
Source File: AffineTransform.scala    From evilplot   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package com.cibo.evilplot.geometry

import com.cibo.evilplot.numeric.Point
import io.circe.{Decoder, Encoder}

final case class AffineTransform(
  scaleX: Double = 1,
  shearX: Double = 0,
  shearY: Double = 0,
  scaleY: Double = 1,
  shiftX: Double = 0,
  shiftY: Double = 0
) {

  def scale(x: Double = 1, y: Double = 1): AffineTransform =
    this.compose(AffineTransform.scale(x, y))

  def translate(dx: Double, dy: Double): AffineTransform =
    this.compose(AffineTransform.translate(dx, dy))

  
  def rotateDegrees(degs: Double): AffineTransform = rotate(degs / 180 * Math.PI)

  def flipOverX: AffineTransform = scale(y = -1)

  def flipOverY: AffineTransform = scale(x = -1)

  def rotateClockwise: AffineTransform = rotateDegrees(-90)

  def rotateCounterClockwise: AffineTransform = rotateDegrees(90)

  def compose(trans: AffineTransform): AffineTransform = {
    val newScaleX = trans.scaleX * scaleX + trans.shearX * shearY
    val newShearX = trans.scaleX * shearX + trans.shearX * scaleY
    val newShiftX = trans.scaleX * shiftX + trans.shearX * shiftY + trans.shiftX
    val newShearY = trans.shearY * scaleX + trans.scaleY * shearY
    val newScaleY = trans.shearY * shearX + trans.scaleY * scaleY
    val newShiftY = trans.shearY * shiftX + trans.scaleY * shiftY + trans.shiftY

    AffineTransform(newScaleX, newShearX, newShearY, newScaleY, newShiftX, newShiftY)
  }

  def apply(x: Double, y: Double): (Double, Double) = {
    val tx = x * scaleX + y * shearX + shiftX
    val ty = x * shearY + y * scaleY + shiftY
    (tx, ty)
  }

  def apply(p: Point): Point = Point.tupled(this.apply(p.x, p.y))
}

object AffineTransform {

  implicit val encoder: Encoder[AffineTransform] =
    io.circe.generic.semiauto.deriveEncoder[AffineTransform]
  implicit val decoder: Decoder[AffineTransform] =
    io.circe.generic.semiauto.deriveDecoder[AffineTransform]

  def identity: AffineTransform = AffineTransform()

  private def scale(sx: Double, sy: Double): AffineTransform =
    AffineTransform(scaleX = sx, scaleY = sy)

  private def translate(dx: Double, dy: Double): AffineTransform =
    AffineTransform(shiftX = dx, shiftY = dy)

  private def rotate(theta: Double): AffineTransform =
    AffineTransform(
      scaleX = Math.cos(theta),
      shearX = -Math.sin(theta),
      shearY = Math.sin(theta),
      scaleY = Math.cos(theta))
} 
Example 164
Source File: Gradient2D.scala    From evilplot   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package com.cibo.evilplot.geometry

import com.cibo.evilplot.JSONUtils.minifyProperties
import com.cibo.evilplot.colors.Color
import com.cibo.evilplot.numeric.{Point, Point2d}
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto._
import io.circe.{Decoder, Encoder, ObjectEncoder}

sealed trait Gradient2d {
  val stops: Seq[GradientStop]
}
object Gradient2d {
  implicit val decoder: Decoder[Gradient2d] = deriveDecoder[Gradient2d]
  implicit val encoder: Encoder[Gradient2d] = deriveEncoder[Gradient2d]
}

case class GradientStop(offset: Double, color: Color)
object GradientStop {
  implicit val decoder: Decoder[GradientStop] = deriveDecoder[GradientStop]
  implicit val encoder: Encoder[GradientStop] = deriveEncoder[GradientStop]
}

case class LinearGradient(x0: Double, y0: Double, x1: Double, y1: Double, stops: Seq[GradientStop])
    extends Gradient2d

object LinearGradient {
  implicit val decoder: Decoder[LinearGradient] = deriveDecoder[LinearGradient]
  implicit val encoder: Encoder[LinearGradient] = deriveEncoder[LinearGradient]

  def leftToRight(ex: Extent, stops: Seq[GradientStop]): LinearGradient =
    LinearGradient(0, 0, x1 = ex.width, 0, stops)

  def rightToLeft(ex: Extent, stops: Seq[GradientStop]): LinearGradient =
    LinearGradient(x0 = ex.width, 0, 0, 0, stops)

  def topToBottom(ex: Extent, stops: Seq[GradientStop]): LinearGradient =
    LinearGradient(0, 0, 0, y1 = ex.height, stops)

  def bottomToTop(ex: Extent, stops: Seq[GradientStop]): LinearGradient = {
    LinearGradient(0, y0 = ex.height, 0, 0, stops)
  }
}

case class RadialGradient(
  x0: Double,
  y0: Double,
  r0: Double,
  x1: Double,
  y1: Double,
  stops: Seq[GradientStop])
    extends Gradient2d

object RadialGradient {
  implicit val decoder: Decoder[RadialGradient] = deriveDecoder[RadialGradient]
  implicit val encoder: Encoder[RadialGradient] = deriveEncoder[RadialGradient]

  def withinExtent(extent: Extent, stops: Seq[GradientStop]): RadialGradient = {
    val radius = extent.height.min(extent.width) / 2

    RadialGradient(
      extent.width / 2,
      extent.height / 2,
      radius,
      extent.width / 2,
      extent.height / 2,
      stops
    )
  }
} 
Example 165
Source File: LineStyle.scala    From evilplot   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package com.cibo.evilplot.geometry

import com.cibo.evilplot.JSONUtils
import io.circe.{Decoder, Encoder}
import io.circe.generic.extras.Configuration


final case class LineStyle(
  dashPattern: Seq[Double] = Seq.empty[Double],
  offset: Double = 0.0
) {
  require(dashPattern.forall(_ > 0), "A dash pattern must only contain positive values.")
}
object LineStyle {
  import io.circe.generic.extras.semiauto._
  private implicit val jsonConfig: Configuration = JSONUtils.minifyProperties
  implicit val lineStyleEncoder: Encoder[LineStyle] = deriveEncoder[LineStyle]
  implicit val lineStyleDecoder: Decoder[LineStyle] = deriveDecoder[LineStyle]

  val Solid: LineStyle = LineStyle()
  val Dotted: LineStyle = LineStyle(Seq(1, 2))
  val DashDot: LineStyle = LineStyle(Seq(6, 3, 1, 3))
  val Dashed: LineStyle = LineStyle(Seq(6))
  def evenlySpaced(dist: Double): LineStyle = LineStyle(Seq(dist))
} 
Example 166
Source File: Extent.scala    From evilplot   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package com.cibo.evilplot.geometry

import com.cibo.evilplot.JSONUtils
import com.cibo.evilplot.numeric.{Point, Point2d}
import io.circe.generic.extras.Configuration
import io.circe.{Decoder, Encoder}


case class Extent(width: Double, height: Double) {
  def *(scale: Double): Extent = Extent(scale * width, scale * height)
  def -(w: Double = 0.0, h: Double = 0.0): Extent = Extent(width - w, height - h)

  private[evilplot] def contains(p: Point2d): Boolean = {
    p.x >= 0 && p.x <= width && p.y >= 0 && p.y <= height
  }
}

object Extent {
  private implicit val cfg: Configuration = JSONUtils.minifyProperties
  implicit val extentEncoder: Encoder[Extent] =
    io.circe.generic.extras.semiauto.deriveEncoder[Extent]
  implicit val extentDecoder: Decoder[Extent] =
    io.circe.generic.extras.semiauto.deriveDecoder[Extent]
} 
Example 167
Source File: JSONUtils.scala    From evilplot   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package com.cibo.evilplot

import io.circe.generic.extras.Configuration
import io.circe.parser.decode
import io.circe.syntax._
import io.circe.{Decoder, Encoder, Error}

object JSONUtils {
  // This should only be used for colors, drawables, and extents.
  private[evilplot] implicit val minifyProperties: Configuration = Configuration.default.copy(
    transformMemberNames = s => s.take(2).toString,
    transformConstructorNames = shortenedName
  )

  // scalastyle:off
  private def shortenedName(s: String): String = {
    s match {
      case "EmptyDrawable" => "E"
      case "Line"          => "L"
      case "Path"          => "P"
      case "Polygon"       => "p"
      case "Rect"          => "R"
      case "BorderRect"    => "B"
      case "Disc"          => "D"
      case "Wedge"         => "W"
      case "Translate"     => "T"
      case "Affine"        => "A"
      case "Scale"         => "C"
      case "Rotate"        => "O"
      case "Group"         => "G"
      case "Resize"        => "Re"
      case "Style"         => "S"
      case "StrokeStyle"   => "Y"
      case "StrokeWeight"  => "H"
      case "LineDash"      => "l"
      case "Text"          => "X"
      case "HSLA"          => "c"
      case "GradientFill"  => "gf"
      case other           => other
    }
  }
  // scalastyle:on

  // Wrap the Circe JSON decode method and return just the desired type, not an Either.
  // If parsing returns an error, throw the error rather than returning it.
  def decodeStr[A: Decoder](input: String): A = {
    val a: Either[Error, A] = decode[A](input)
    a match {
      case Left(error)   => throw error
      case Right(result) => result
    }
  }

  // Encode the input object to JSON, then convert the JSON to a string and return it.
  def encodeObj[A: Encoder](input: A): String = {
    input.asJson.noSpaces
  }
} 
Example 168
Source File: Bounds.scala    From evilplot   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package com.cibo.evilplot.numeric

import scala.language.implicitConversions
import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto._

final case class Bounds(min: Double, max: Double) {
  if (!min.isNaN && !max.isNaN) {
    require(min <= max, s"Bounds min must be <= max, $min !<= $max")
  }

  
  def pad(p: Double): Bounds = Bounds(min - range * p, max + range * p)
  def padMax(p: Double): Bounds = Bounds(min, max + range * p)
  def padMin(p: Double): Bounds = Bounds(min - range * p, max)
}

object Bounds {

  implicit val encoder: Encoder[Bounds] = deriveEncoder[Bounds]
  implicit val decoder: Decoder[Bounds] = deriveDecoder[Bounds]

  private def lift[T](expr: => T): Option[T] = {
    try {
      Some(expr)
    } catch {
      case _: Exception => None
    }
  }

  def union(bounds: Seq[Bounds]): Bounds = bounds reduce { _ union _ }

  def getBy[T](data: Seq[T])(f: T => Double): Option[Bounds] = {
    val mapped = data.map(f).filterNot(_.isNaN)
    for {
      min <- lift(mapped.min)
      max <- lift(mapped.max)
    } yield Bounds(min, max)
  }

  def of(data: Seq[Double]): Bounds = Bounds.get(data) getOrElse Bounds.empty

  def get(data: Seq[Double]): Option[Bounds] = {
    data.foldLeft(None: Option[Bounds]) { (bounds, value) =>
      bounds match {
        case None => Some(Bounds(value, value))
        case Some(Bounds(min, max)) =>
          Some(Bounds(math.min(min, value), math.max(max, value)))
      }
    }
  }
  def empty: Bounds = Bounds(0d, 0d)

  def widest(bounds: Seq[Option[Bounds]]): Option[Bounds] =
    bounds.flatten.foldLeft(None: Option[Bounds]) { (acc, curr) =>
      if (acc.isEmpty) Some(curr)
      else
        Some(Bounds(math.min(acc.get.min, curr.min), math.max(acc.get.max, curr.max)))
    }
} 
Example 169
Source File: Points.scala    From evilplot   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package com.cibo.evilplot.numeric

import scala.language.implicitConversions
import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto._

trait Point2d {
  val x: Double
  val y: Double
  def withXY(x: Double = this.x, y: Double = this.y): Point2d
}

case class Point3d[Z: Numeric](x: Double, y: Double, z: Z) extends Datum2d[Point3d[Z]] {
  def withXY(x: Double, y: Double): Point3d[Z] = this.copy(x, y, z)
}

trait Datum2d[A <: Datum2d[A]] extends Point2d {
  val x: Double
  val y: Double
  def withXY(x: Double = this.x, y: Double = this.y): A
}

final case class Point(x: Double, y: Double) extends Datum2d[Point] {
  def -(that: Point): Point = Point(x - that.x, y - that.y)

  def withXY(x: Double = this.x, y: Double = this.y): Point = this.copy(x = x, y = y)
}

object Point {
  implicit val encoder: Encoder[Point] = io.circe.generic.semiauto.deriveEncoder[Point]
  implicit val decoder: Decoder[Point] = io.circe.generic.semiauto.deriveDecoder[Point]
  def tupled(t: (Double, Double)): Point = Point(t._1, t._2)
  implicit def toTuple(p: Point): (Double, Double) = (p.x, p.y)
}

final case class Point3(x: Double, y: Double, z: Double)

object Point3 {
  def tupled(t: (Double, Double, Double)): Point3 = Point3(t._1, t._2, t._3)
} 
Example 170
Source File: BoxPlotSummaryStatistics.scala    From evilplot   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package com.cibo.evilplot.numeric

import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto._

case class BoxPlotSummaryStatistics(
  min: Double,
  max: Double,
  lowerWhisker: Double,
  upperWhisker: Double,
  lowerQuantile: Double,
  middleQuantile: Double,
  upperQuantile: Double,
  outliers: Seq[Double],
  allPoints: Seq[Double]) {
  override def toString: String = {
    s"""lowerWhisker $lowerWhisker lowerQuantile $lowerQuantile middleQuantile
       |$middleQuantile upperQuantile $upperQuantile upperWhisker $upperWhisker
     """.stripMargin
  }
}


object BoxPlotSummaryStatistics {

  implicit val encoder: Encoder[BoxPlotSummaryStatistics] = deriveEncoder[BoxPlotSummaryStatistics]
  implicit val decoder: Decoder[BoxPlotSummaryStatistics] = deriveDecoder[BoxPlotSummaryStatistics]

  def apply(
    data: Seq[Double],
    quantiles: (Double, Double, Double) = (0.25, 0.50, 0.75),
    includeAllPoints: Boolean = false): BoxPlotSummaryStatistics = {
    val sorted = data.sorted

    require(
      quantiles._1 < quantiles._2 && quantiles._2 < quantiles._3,
      "Supplied quantiles must be strictly increasing")
    val (lowerQuantile, middleQuantile, upperQuantile) =
      quantile(data, quantiles match { case (l, m, u) => Seq(l, m, u) }) match {
        case Seq(l, m, u) => (l, m, u)
      }

    // Summary stats
    val min: Double = sorted.head
    val max: Double = sorted.last

    val interQuartileRange = upperQuantile - lowerQuantile
    val lowerWhiskerLimit = lowerQuantile - 1.5 * interQuartileRange
    val upperWhiskerLimit = upperQuantile + 1.5 * interQuartileRange

    val outliersLeft =
      if (min < lowerWhiskerLimit) sorted.takeWhile(_ < lowerWhiskerLimit)
      else Nil
    val outliersRight =
      if (max > upperWhiskerLimit) sorted.dropWhile(_ < upperWhiskerLimit)
      else Nil

    val outliers: Seq[Double] = outliersLeft ++ outliersRight
    val lowerWhisker: Double = math.max(lowerWhiskerLimit, min)
    val upperWhisker: Double = math.min(upperWhiskerLimit, max)

    BoxPlotSummaryStatistics(
      min,
      max,
      lowerWhisker,
      upperWhisker,
      lowerQuantile,
      middleQuantile,
      upperQuantile,
      outliers,
      data)
  }
} 
Example 171
Source File: package.scala    From evilplot   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package com.cibo.evilplot

import scala.language.implicitConversions
import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto._

package object numeric {
  type Grid = Vector[Vector[Double]]

  final case class GridData(
    grid: Grid,
    xBounds: Bounds,
    yBounds: Bounds,
    zBounds: Bounds,
    xSpacing: Double,
    ySpacing: Double)

  private val normalConstant = 1.0 / math.sqrt(2 * math.Pi)

  // with sigma = 1.0 and mu = 0, like R's dnorm.
  private[numeric] def probabilityDensityInNormal(x: Double): Double =
    normalConstant * math.exp(-math.pow(x, 2) / 2)

  // quantiles using linear interpolation.
  private[numeric] def quantile(data: Seq[Double], quantiles: Seq[Double]): Seq[Double] = {
    if (data.isEmpty) Seq.fill(quantiles.length)(Double.NaN)
    else {
      val length = data.length
      val sorted = data.sorted
      for {
        quantile <- quantiles
        _ = require(quantile >= 0.0 && quantile <= 1.0)
        index = quantile * (length - 1)
        result = {
          if (index >= length - 1) sorted.last
          else {
            val lower = sorted(math.floor(index).toInt)
            val upper = sorted(math.ceil(index).toInt)
            lower + (upper - lower) * (index - math.floor(index))
          }
        }
      } yield result
    }
  }

  private[numeric] def mean(data: Seq[Double]): Double = data.sum / data.length

  private[numeric] def variance(data: Seq[Double]): Double = {
    val _mean = mean(data)
    data.map(x => math.pow(x - _mean, 2)).sum / (data.length - 1)
  }

  private[numeric] def standardDeviation(data: Seq[Double]): Double = math.sqrt(variance(data))

} 
Example 172
Source File: ColorBar.scala    From evilplot   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package com.cibo.evilplot.colors

import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
import io.circe.{Decoder, Encoder}

sealed trait ColorBar {
  val nColors: Int
  def getColor(z: Int): Color
}

// Use when one color is wanted but a ColorBar is needed.
case class SingletonColorBar(color: Color) extends ColorBar {
  val nColors: Int = 1
  def getColor(z: Int): Color = {
    require(z == 1)
    color
  }
}

// Map a sequence of colors to a continuous variable z.
case class ScaledColorBar(colorSeq: Seq[Color], zMin: Double, zMax: Double) extends ColorBar {
  val nColors: Int = colorSeq.length

  private val zWidth = (zMax - zMin) / nColors.toFloat

  def getColor(i: Int): Color = colorSeq(i)
  def getColor(z: Double): Color = getColor(colorIndex(z))

  def colorIndex(z: Double): Int =
    math.min(math.round(math.floor(math.max(z - zMin, 0.0) / zWidth)).toInt, nColors - 1)
  def colorValue(i: Int): Double = i * zWidth + zMin
}

object ColorBar {
  implicit val encoder: Encoder[ColorBar] = deriveEncoder[ColorBar]
  implicit val decoder: Decoder[ColorBar] = deriveDecoder[ColorBar]
} 
Example 173
Source File: AkkaHttpLambdaHandlerSpec.scala    From scala-server-lambda   with MIT License 5 votes vote down vote up
package io.github.howardjohn.lambda.akka

import akka.actor.ActorSystem
import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller}
import akka.http.scaladsl.model.MediaTypes.`application/json`
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model.{HttpEntity, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller}
import akka.stream.ActorMaterializer
import io.circe.parser.decode
import io.circe.syntax._
import io.circe.{Decoder, Encoder}
import io.github.howardjohn.lambda.LambdaHandlerBehavior
import io.github.howardjohn.lambda.LambdaHandlerBehavior._
import org.scalatest.{BeforeAndAfterAll, FeatureSpec, GivenWhenThen}

import scala.concurrent.Future

class AkkaHttpLambdaHandlerSpec
    extends FeatureSpec
    with LambdaHandlerBehavior
    with GivenWhenThen
    with BeforeAndAfterAll {

  implicit val system: ActorSystem = ActorSystem("test")
  implicit val materializer: ActorMaterializer = ActorMaterializer()
  implicit val ec = scala.concurrent.ExecutionContext.Implicits.global

  val route: Route =
    path("hello") {
      (get & parameter("times".as[Int] ? 1)) { times =>
        complete {
          Seq
            .fill(times)("Hello World!")
            .mkString(" ")
        }
      }
    } ~ path("long") {
      get {
        Thread.sleep(1000)
        complete("")
      }
    } ~ path("post") {
      post {
        entity(as[String]) { body =>
          complete(body)
        }
      }
    } ~ path("json") {
      post {
        import CirceJsonMarshalling._
        import io.circe.generic.auto._
        entity(as[JsonBody]) { entity =>
          complete(LambdaHandlerBehavior.jsonReturn.asJson)
        }
      }
    } ~ path("exception") {
      get {
        throw RouteException()
      }
    } ~ path("error") {
      get {
        complete(StatusCodes.InternalServerError)
      }
    } ~ path("header") {
      get {
        headerValueByName(inputHeader) { header =>
          respondWithHeaders(RawHeader(outputHeader, outputHeaderValue)) {
            complete(header)
          }
        }
      }
    }

  val handler = new AkkaHttpLambdaHandler(route)

  scenariosFor(behavior(handler))

  override def afterAll(): Unit = {
    materializer.shutdown()
    system.terminate()
  }
}


object CirceJsonMarshalling {
  implicit final def unmarshaller[A: Decoder]: FromEntityUnmarshaller[A] =
    Unmarshaller.stringUnmarshaller
      .forContentTypes(`application/json`)
      .flatMap { ctx => mat => json =>
        decode[A](json).fold(Future.failed, Future.successful)
      }

  implicit final def marshaller[A: Encoder]: ToEntityMarshaller[A] =
    Marshaller.withFixedContentType(`application/json`) { a =>
      HttpEntity(`application/json`, a.asJson.noSpaces)
    }
} 
Example 174
Source File: KafkaJsonSerializer.scala    From ticket-booking-aecor   with Apache License 2.0 5 votes vote down vote up
package ru.pavkin.payment.kafka
import java.nio.charset.StandardCharsets
import java.util

import io.circe.parser._
import io.circe.Encoder
import org.apache.kafka.common.serialization.{ Deserializer, Serializer, StringSerializer }
import ru.pavkin.payment.event.PaymentReceived

class PaymentReceivedEventSerializer extends Serializer[PaymentReceived] {
  private val stringSerializer = new StringSerializer

  def configure(configs: util.Map[String, _], isKey: Boolean): Unit = ()

  def serialize(topic: String, data: PaymentReceived): Array[Byte] =
    stringSerializer.serialize(topic, Encoder[PaymentReceived].apply(data).noSpaces)

  def close(): Unit = ()
}

class PaymentReceivedEventDeserializer extends Deserializer[PaymentReceived] {
  def configure(configs: util.Map[String, _], isKey: Boolean): Unit = ()

  def close(): Unit = ()

  def deserialize(topic: String, data: Array[Byte]): PaymentReceived =
    if (data ne null)
      decode[PaymentReceived](new String(data, StandardCharsets.UTF_8)).fold(throw _, identity)
    else null

} 
Example 175
Source File: AnyValCoders.scala    From ticket-booking-aecor   with Apache License 2.0 5 votes vote down vote up
package ru.pavkin.booking.common.json

import io.circe.{Decoder, Encoder}
import shapeless.Unwrapped

trait AnyValCoders {
  implicit def anyValEncoder[V, U](
    implicit ev: V <:< AnyVal,
    V: Unwrapped.Aux[V, U],
    encoder: Encoder[U]): Encoder[V] = {
    val _ = ev
    encoder.contramap(V.unwrap)
  }

  implicit def anyValDecoder[V, U](
    implicit ev: V <:< AnyVal,
    V: Unwrapped.Aux[V, U],
    decoder: Decoder[U],
    lp: shapeless.LowPriority): Decoder[V] = {
    val _ = (ev, lp)
    decoder.map(V.wrap)
  }
}

object AnyValCoders extends AnyValCoders 
Example 176
Source File: Models.scala    From ticket-booking-aecor   with Apache License 2.0 5 votes vote down vote up
package ru.pavkin.booking.common.models

import cats.Order
import cats.implicits._
import cats.kernel.{ Eq, Monoid }
import enumeratum._
import io.circe.{ Decoder, Encoder }
import io.circe.generic.semiauto._
import ru.pavkin.booking.common.json.AnyValCoders._

import scala.collection.immutable

case class Money(amount: BigDecimal) extends AnyVal

object Money {
  implicit val monoid: Monoid[Money] = new Monoid[Money] {
    def empty: Money = Money(0)
    def combine(x: Money, y: Money): Money = Money(x.amount + y.amount)
  }
}

case class BookingKey(value: String) extends AnyVal

case class ClientId(value: String) extends AnyVal
object ClientId {
  implicit val eqInstance: Eq[ClientId] = Eq.fromUniversalEquals
}

case class ConcertId(value: String) extends AnyVal

case class Row(num: Int) extends AnyVal
case class SeatNumber(num: Int) extends AnyVal

case class Seat(row: Row, number: SeatNumber)

object Seat {
  def seat(row: Int, number: Int): Seat = Seat(Row(row), SeatNumber(number))

  implicit val order: Order[Seat] = Order.by(s => (s.row.num, s.number.num))
  implicit val decoder: Decoder[Seat] = deriveDecoder
  implicit val encoder: Encoder[Seat] = deriveEncoder
}

case class Ticket(seat: Seat, price: Money)
object Ticket {
  implicit val decoder: Decoder[Ticket] = deriveDecoder
  implicit val encoder: Encoder[Ticket] = deriveEncoder
}
case class PaymentId(value: String) extends AnyVal

sealed trait BookingStatus extends EnumEntry

object BookingStatus extends Enum[BookingStatus] with CirceEnum[BookingStatus] {
  case object AwaitingConfirmation extends BookingStatus
  case object Confirmed extends BookingStatus
  case object Denied extends BookingStatus
  case object Canceled extends BookingStatus
  case object Settled extends BookingStatus

  def values: immutable.IndexedSeq[BookingStatus] = findValues
} 
Example 177
Source File: PostgresBookingViewRepository.scala    From ticket-booking-aecor   with Apache License 2.0 5 votes vote down vote up
package ru.pavkin.booking.booking.view

import java.sql.Timestamp
import java.time.Instant

import cats.Monad
import cats.implicits._
import doobie._
import doobie.implicits._
import doobie.util.transactor.Transactor
import io.circe.{ Decoder, Encoder, Json }
import io.circe.parser._
import org.postgresql.util.PGobject
import ru.pavkin.booking.common.models._

class PostgresBookingViewRepository[F[_]: Monad](transactor: Transactor[F],
                                                 tableName: String = "bookings")
    extends BookingViewRepository[F] {

  implicit val jsonMeta: Meta[Json] =
    Meta.Advanced
      .other[PGobject]("json")
      .timap[Json](a => parse(a.getValue).leftMap[Json](e => throw e).merge)(a => {
        val o = new PGobject
        o.setType("json")
        o.setValue(a.noSpaces)
        o
      })

  implicit val seatsMeta: Meta[List[Seat]] = jsonMeta.timap(
    j => Decoder[List[Seat]].decodeJson(j).right.get
  )(s => Encoder[List[Seat]].apply(s))

  implicit val ticketsMeta: Meta[List[Ticket]] = jsonMeta.timap(
    j => Decoder[List[Ticket]].decodeJson(j).right.get
  )(s => Encoder[List[Ticket]].apply(s))

  implicit val instantMeta: Meta[Instant] =
    Meta[Timestamp].timap(_.toInstant)(Timestamp.from)

  implicit val bookingStatusMeta: Meta[BookingStatus] =
    Meta[String].timap(BookingStatus.withName)(_.entryName)

  def get(bookingId: BookingKey): F[Option[BookingView]] =
    queryView(bookingId).option.transact(transactor)

  def byClient(clientId: ClientId): F[List[BookingView]] =
    queryForClient(clientId).to[List].transact(transactor)

  def set(view: BookingView): F[Unit] =
    Update[BookingView](setViewQuery).run(view).transact(transactor).void

  def expired(now: Instant): fs2.Stream[F, BookingKey] =
    queryExpired(now).stream.transact(transactor)

  def createTable: F[Unit] = createTableQuery.transact(transactor).void

  private val setViewQuery =
    s"""INSERT INTO $tableName
    (booking_id, client_id, concert_id, seats, tickets, status, confirmed_at, expires_at, version)
    VALUES (?,?,?,?,?,?,?,?,?)
    ON CONFLICT (booking_id)
    DO UPDATE SET
     tickets = EXCLUDED.tickets,
     status = EXCLUDED.status,
     confirmed_at = EXCLUDED.confirmed_at,
     expires_at = EXCLUDED.expires_at,
     version = EXCLUDED.version;"""

  private def queryView(bookingId: BookingKey) =
    (fr"SELECT * FROM " ++ Fragment.const(tableName) ++
      fr"WHERE booking_id = $bookingId;")
      .query[BookingView]

  private def queryExpired(now: Instant) =
    (fr"SELECT booking_id FROM " ++ Fragment.const(tableName) ++
      fr"WHERE status = ${BookingStatus.Confirmed: BookingStatus} AND expires_at < $now;")
      .query[BookingKey]

  private def queryForClient(clientId: ClientId) =
    (fr"SELECT * FROM " ++ Fragment.const(tableName) ++
      fr"WHERE client_id = $clientId;")
      .query[BookingView]

  private val createTableQuery = (fr"""
    CREATE TABLE IF NOT EXISTS """ ++ Fragment.const(tableName) ++
    fr""" (
    booking_id    text      NOT NULL PRIMARY KEY,
    client_id     text      NOT NULL,
    concert_id    text      NOT NULL,
    seats         json      NOT NULL,
    tickets       json      NOT NULL,
    status        text      NOT NULL,
    confirmed_at  timestamptz,
    expires_at    timestamptz,
    version       bigint    NOT NULL
    );
  """).update.run

} 
Example 178
Source File: Formatter.scala    From odin   with Apache License 2.0 5 votes vote down vote up
package io.odin.json

import cats.syntax.show._
import io.circe.syntax._
import io.circe.Encoder
import io.odin.LoggerMessage
import io.odin.formatter.{Formatter => OFormatter}
import io.odin.formatter.Formatter._
import io.odin.formatter.options.{PositionFormat, ThrowableFormat}

object Formatter {

  val json: OFormatter = create(ThrowableFormat.Default, PositionFormat.Full)

  def create(throwableFormat: ThrowableFormat): OFormatter =
    create(throwableFormat, PositionFormat.Full)

  def create(throwableFormat: ThrowableFormat, positionFormat: PositionFormat): OFormatter = {
    implicit val encoder: Encoder[LoggerMessage] = loggerMessageEncoder(throwableFormat, positionFormat)
    (msg: LoggerMessage) => msg.asJson.noSpaces
  }

  def loggerMessageEncoder(throwableFormat: ThrowableFormat, positionFormat: PositionFormat): Encoder[LoggerMessage] =
    Encoder.forProduct7("level", "message", "context", "exception", "position", "thread_name", "timestamp")(m =>
      (
        m.level.show,
        m.message.value,
        m.context,
        m.exception.map(t => formatThrowable(t, throwableFormat)),
        formatPosition(m.position, positionFormat),
        m.threadName,
        formatTimestamp(m.timestamp)
      )
    )

} 
Example 179
Source File: ErrorInfo.scala    From shaclex   with MIT License 5 votes vote down vote up
package es.weso.schema
import cats.Show
import com.typesafe.scalalogging.LazyLogging
import io.circe.JsonObject._
import io.circe.{ Decoder, Encoder, Json }

case class ErrorInfo(msg: String) {
  def show: String = msg
}

object ErrorInfo extends LazyLogging {
  implicit val showErrorInfo = new Show[ErrorInfo] {
    override def show(e: ErrorInfo): String = e.show
  }

  implicit val encodeErrorInfo: Encoder[ErrorInfo] = new Encoder[ErrorInfo] {
    final def apply(e: ErrorInfo): Json = Json.fromJsonObject(
      singleton("type", Json.fromString("ErrorInfo")).
        add("error", Json.fromString(e.msg)))
  }

  implicit val decodeErrorInfo: Decoder[ErrorInfo] = Decoder.instance { c =>
    logger.debug(s"Decoding error info: $c")
    for {
      msg <- c.get[String]("error")
    } yield ErrorInfo(msg)
  }

} 
Example 180
Source File: Codecs.scala    From bay-scalajs.g8   with Apache License 2.0 5 votes vote down vote up
package shared.utils

import cats.syntax.either._
import io.circe.Decoder
import io.circe.Encoder
import java.time._
import java.time.format.DateTimeFormatter

trait Codecs extends UpickleCodecs with CirceCodecs

object Codecs extends Codecs

trait CirceCodecs {

  // use more stable encodings then standard
  private val fmt: DateTimeFormatter =
    DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSZZZZZ")
  private val fmtLocal: DateTimeFormatter =
    DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSS")
  private val fmtDate: DateTimeFormatter =
    DateTimeFormatter.ofPattern("uuuu-MM-dd")
  private val fmtTime: DateTimeFormatter =
    DateTimeFormatter.ofPattern("HH:mm:ss.SSS")

  def createCirceCodec[T](encode: T => String,
                          decode: String => T): (Encoder[T], Decoder[T]) =
    (Encoder.encodeString.contramap[T](encode),
     Decoder.decodeString.emap(str =>
       Either.catchNonFatal(decode(str)).leftMap(_.getMessage)))

  implicit val (encodeOffsetDateTimeCirce, decodeOffsetDateTimeCirce) =
    createCirceCodec[OffsetDateTime](fmt.format, OffsetDateTime.parse)
  implicit val (encodeLocalDateTimeCirce, decodeLocalDateTimeCirce) =
    createCirceCodec[LocalDateTime](fmtLocal.format, LocalDateTime.parse)
  implicit val (encodeLocalDateCirce, decodeLocalDateCirce) =
    createCirceCodec[LocalDate](fmtDate.format, LocalDate.parse)
  implicit val (encodeLocalTimeCirce, decodeLocalTimeCirce) =
    createCirceCodec[LocalTime](fmtTime.format, LocalTime.parse)
  implicit val (encodeDurationCirce, decodeDurationCirce) =
    createCirceCodec[Duration](_.toString(), Duration.parse)

}

object CirceCodecs extends CirceCodecs

trait UpickleCodecs {
  import upickle.default._

  def createUpickleCode[T](encode: T => String,
                           decode: String => T): (Writer[T], Reader[T]) =
    (Writer[T](e => upickle.Js.Str(encode(e))), Reader[T] {
      case upickle.Js.Str(jsStr) => decode(jsStr)
    })

  implicit val (encodeOffsetDateTimeUpickle, decodeOffsetDateTimeUpickle) =
    createUpickleCode[OffsetDateTime](_.toString(), OffsetDateTime.parse)
  implicit val (encodeLocalDateTimeUpickle, decodeLocalDateTimeUpickle) =
    createUpickleCode[LocalDateTime](_.toString(), LocalDateTime.parse)
  implicit val (encodeLocalDateUpickle, decodeLocalDateUpickle) =
    createUpickleCode[LocalDate](_.toString(), LocalDate.parse)
  implicit val (encodeLocalTimeUpickle, decodeLocalTimeUpickle) =
    createUpickleCode[LocalTime](_.toString(), LocalTime.parse)
  implicit val (encodeDurationUpickle, decodeDurationUpickle) =
    createUpickleCode[Duration](_.toString(), Duration.parse)
}

object UpickleCodecs extends UpickleCodecs 
Example 181
Source File: CirceSerialization.scala    From kafka-serialization   with Apache License 2.0 5 votes vote down vote up
package com.ovoenergy.kafka.serialization.circe

import java.nio.charset.StandardCharsets

import cats.syntax.either._
import com.ovoenergy.kafka.serialization.core._
import io.circe.parser._
import io.circe.syntax._
import io.circe.{Decoder, Encoder, Error, Json}
import org.apache.kafka.common.serialization.{Deserializer => KafkaDeserializer, Serializer => KafkaSerializer}

private[circe] trait CirceSerialization {

  def circeJsonSerializer[T: Encoder]: KafkaSerializer[T] = serializer { (_, data) =>
    data.asJson.noSpaces.getBytes(StandardCharsets.UTF_8)
  }

  def circeJsonDeserializer[T: Decoder]: KafkaDeserializer[T] = deserializer { (_, data) =>
    (for {
      json <- parse(new String(data, StandardCharsets.UTF_8)): Either[Error, Json]
      t <- json.as[T]: Either[Error, T]
    } yield
      t).fold(error => throw new RuntimeException(s"Deserialization failure: ${error.getMessage}", error), identity _)
  }

} 
Example 182
Source File: PermissionsEvent.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.permissions

import java.time.Instant

import ch.epfl.bluebrain.nexus.iam.config.AppConfig.HttpConfig
import ch.epfl.bluebrain.nexus.iam.config.Contexts._
import ch.epfl.bluebrain.nexus.iam.types.Identity.Subject
import ch.epfl.bluebrain.nexus.iam.types.{Identity, Permission}
import ch.epfl.bluebrain.nexus.rdf.implicits._
import com.github.ghik.silencer.silent
import io.circe.Encoder
import io.circe.generic.extras.Configuration


  final case class PermissionsDeleted(
      rev: Long,
      instant: Instant,
      subject: Subject
  ) extends PermissionsEvent

  object JsonLd {
    import io.circe.generic.extras.semiauto._

    @silent // defined implicits are not recognized as being used
    implicit def permissionsEventEncoder(implicit http: HttpConfig): Encoder[Event] = {
      implicit val config: Configuration = Configuration.default
        .withDiscriminator("@type")
        .copy(transformMemberNames = {
          case "rev"     => "_rev"
          case "instant" => "_instant"
          case "subject" => "_subject"
          case other     => other
        })
      implicit val subjectEncoder: Encoder[Subject] = Identity.subjectIdEncoder
      deriveConfiguredEncoder[Event]
        .mapJson { json =>
          json
            .addContext(iamCtxUri)
            .addContext(resourceCtxUri)
        }
    }
  }
} 
Example 183
Source File: AccessControlLists.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.acls

import ch.epfl.bluebrain.nexus.commons.circe.syntax._
import ch.epfl.bluebrain.nexus.iam.config.AppConfig.HttpConfig
import ch.epfl.bluebrain.nexus.iam.config.Contexts._
import ch.epfl.bluebrain.nexus.iam.config.Vocabulary.nxv
import ch.epfl.bluebrain.nexus.iam.types.Identity
import ch.epfl.bluebrain.nexus.rdf.Iri.Path
import ch.epfl.bluebrain.nexus.rdf.implicits._
import io.circe.syntax._
import io.circe.{Encoder, Json}

import scala.collection.immutable.ListMap


  final def apply(tuple: (Path, Resource)*): AccessControlLists = AccessControlLists(tuple.toMap)

  implicit def aclsEncoder(implicit http: HttpConfig): Encoder[AccessControlLists] = Encoder.encodeJson.contramap {
    case AccessControlLists(value) =>
      val arr = value.map {
        case (path, acl) =>
          Json.obj("_path" -> Json.fromString(path.asString)) deepMerge acl.asJson.removeKeys("@context")
      }
      Json
        .obj(nxv.total.prefix -> Json.fromInt(arr.size), nxv.results.prefix -> Json.arr(arr.toSeq: _*))
        .addContext(resourceCtxUri)
        .addContext(iamCtxUri)
        .addContext(searchCtxUri)
  }
} 
Example 184
Source File: AclRejection.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.acls

import akka.http.scaladsl.model.StatusCodes.{BadRequest, Conflict, NotFound}
import ch.epfl.bluebrain.nexus.commons.http.directives.StatusFrom
import ch.epfl.bluebrain.nexus.iam.config.Contexts.errorCtxUri
import ch.epfl.bluebrain.nexus.iam.types.{Permission, ResourceRejection}
import ch.epfl.bluebrain.nexus.rdf.Iri.Path
import ch.epfl.bluebrain.nexus.rdf.implicits._
import com.github.ghik.silencer.silent
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}

sealed abstract class AclRejection(val msg: String) extends ResourceRejection

object AclRejection {

  
  final case class UnknownPermissions(permissions: Set[Permission])
      extends AclRejection(
        s"Some of the permissions specified are not known: '${permissions.mkString("\"", ", ", "\"")}'"
      )

  @silent // rejectionConfig is not recognized as being used
  implicit val aclRejectionEncoder: Encoder[AclRejection] = {
    implicit val rejectionConfig: Configuration = Configuration.default.withDiscriminator("@type")
    val enc                                     = deriveConfiguredEncoder[AclRejection].mapJson(_ addContext errorCtxUri)
    Encoder.instance(r => enc(r) deepMerge Json.obj("reason" -> Json.fromString(r.msg)))
  }

  implicit val aclRejectionStatusFrom: StatusFrom[AclRejection] =
    StatusFrom {
      case _: NothingToBeUpdated                        => BadRequest
      case _: AclIsEmpty                                => BadRequest
      case _: AclCannotContainEmptyPermissionCollection => BadRequest
      case _: AclNotFound                               => NotFound
      case _: IncorrectRev                              => Conflict
      case _: UnknownPermissions                        => BadRequest
    }
} 
Example 185
Source File: AclEvent.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.acls

import java.time.Instant

import ch.epfl.bluebrain.nexus.iam.config.AppConfig.HttpConfig
import ch.epfl.bluebrain.nexus.iam.config.Contexts._
import ch.epfl.bluebrain.nexus.iam.types.Identity
import ch.epfl.bluebrain.nexus.iam.types.Identity.Subject
import ch.epfl.bluebrain.nexus.rdf.Iri.Path
import ch.epfl.bluebrain.nexus.rdf.implicits._
import com.github.ghik.silencer.silent
import io.circe.Encoder
import io.circe.generic.extras.Configuration


  final case class AclDeleted(
      path: Path,
      rev: Long,
      instant: Instant,
      subject: Subject
  ) extends AclEvent

  object JsonLd {
    import io.circe.generic.extras.semiauto._

    @silent // defined implicits are not recognized as being used
    implicit def aclEventEncoder(implicit httpConfig: HttpConfig): Encoder[AclEvent] = {
      implicit val config: Configuration = Configuration.default
        .withDiscriminator("@type")
        .copy(transformMemberNames = {
          case "rev"     => "_rev"
          case "instant" => "_instant"
          case "subject" => "_subject"
          case "path"    => "_path"
          case other     => other
        })
      implicit val arrayEncoder: Encoder[AccessControlList] = AccessControlList.aclArrayEncoder
      implicit val subjectEncoder: Encoder[Subject]         = Identity.subjectIdEncoder
      deriveConfiguredEncoder[AclEvent]
        .mapJson { json =>
          json
            .addContext(iamCtxUri)
            .addContext(resourceCtxUri)
        }
    }
  }
} 
Example 186
Source File: ActiveRealm.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.realms

import ch.epfl.bluebrain.nexus.iam.config.Vocabulary.nxv
import ch.epfl.bluebrain.nexus.iam.types.GrantType.Camel._
import ch.epfl.bluebrain.nexus.iam.types.{GrantType, Label}
import ch.epfl.bluebrain.nexus.rdf.Iri.Url
import ch.epfl.bluebrain.nexus.rdf.implicits._
import com.nimbusds.jose.jwk.{JWK, JWKSet}
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}

import scala.util.Try


final case class ActiveRealm(
    id: Label,
    name: String,
    openIdConfig: Url,
    issuer: String,
    grantTypes: Set[GrantType],
    logo: Option[Url],
    authorizationEndpoint: Url,
    tokenEndpoint: Url,
    userInfoEndpoint: Url,
    revocationEndpoint: Option[Url],
    endSessionEndpoint: Option[Url],
    keys: Set[Json]
) {

  private[realms] lazy val keySet: JWKSet = {
    val jwks = keys.foldLeft(Set.empty[JWK]) {
      case (acc, e) => Try(JWK.parse(e.noSpaces)).map(acc + _).getOrElse(acc)
    }
    import scala.jdk.CollectionConverters._
    new JWKSet(jwks.toList.asJava)
  }
}

object ActiveRealm {
  private[ActiveRealm] implicit val config: Configuration = Configuration.default.copy(transformMemberNames = {
    case "issuer"                => nxv.issuer.prefix
    case "grantTypes"            => nxv.grantTypes.prefix
    case "authorizationEndpoint" => nxv.authorizationEndpoint.prefix
    case "tokenEndpoint"         => nxv.tokenEndpoint.prefix
    case "userInfoEndpoint"      => nxv.userInfoEndpoint.prefix
    case "revocationEndpoint"    => nxv.revocationEndpoint.prefix
    case "endSessionEndpoint"    => nxv.endSessionEndpoint.prefix
    case other                   => other
  })
  implicit val activeEncoder: Encoder[ActiveRealm] = {
    val default = deriveConfiguredEncoder[ActiveRealm]
    Encoder
      .instance[ActiveRealm] { realm =>
        default(realm) deepMerge Json.obj(
          nxv.label.prefix      -> Json.fromString(realm.id.value),
          nxv.deprecated.prefix -> Json.fromBoolean(false)
        )
      }
      .mapJson(_.removeKeys("keys", "id"))
  }
} 
Example 187
Source File: ResourceF.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.types

import java.time.Instant

import ch.epfl.bluebrain.nexus.iam.config.AppConfig.HttpConfig
import ch.epfl.bluebrain.nexus.iam.config.Contexts._
import ch.epfl.bluebrain.nexus.iam.config.Vocabulary.nxv
import ch.epfl.bluebrain.nexus.iam.syntax._
import ch.epfl.bluebrain.nexus.iam.types.Identity.Subject
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import ch.epfl.bluebrain.nexus.rdf.implicits._
import io.circe.syntax._
import io.circe.{Encoder, Json}


  def unit(
      id: AbsoluteIri,
      rev: Long,
      types: Set[AbsoluteIri],
      createdAt: Instant,
      createdBy: Subject,
      updatedAt: Instant,
      updatedBy: Subject
  ): ResourceF[Unit] =
    ResourceF(id, rev, types, createdAt, createdBy, updatedAt, updatedBy, ())

  implicit val permsEncoder: Encoder[Set[Permission]] =
    Encoder.instance(perms => Json.obj("permissions" -> Json.fromValues(perms.toList.sortBy(_.value).map(_.asJson))))

  implicit def resourceFEncoder[A: Encoder](implicit http: HttpConfig): Encoder[ResourceF[A]] =
    Encoder.encodeJson.contramap { r =>
      resourceMetaEncoder.apply(r.discard) deepMerge r.value.asJson
    }

  implicit def resourceMetaEncoder(implicit http: HttpConfig): Encoder[ResourceMetadata] =
    Encoder.encodeJson.contramap {
      case ResourceF(id, rev, types, createdAt, createdBy, updatedAt, updatedBy, _: Unit) =>
        val jsonTypes = types.toList match {
          case Nil      => Json.Null
          case t :: Nil => Json.fromString(t.lastSegment.getOrElse(t.asString))
          case _        => Json.arr(types.map(t => Json.fromString(t.lastSegment.getOrElse(t.asString))).toSeq: _*)
        }
        Json
          .obj(
            "@id"                -> id.asJson,
            "@type"              -> jsonTypes,
            nxv.rev.prefix       -> Json.fromLong(rev),
            nxv.createdBy.prefix -> createdBy.id.asJson,
            nxv.updatedBy.prefix -> updatedBy.id.asJson,
            nxv.createdAt.prefix -> Json.fromString(createdAt.toString),
            nxv.updatedAt.prefix -> Json.fromString(updatedAt.toString)
          )
          .addContext(iamCtxUri)
          .addContext(resourceCtxUri)
    }
} 
Example 188
Source File: Caller.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.types

import ch.epfl.bluebrain.nexus.iam.config.AppConfig.HttpConfig
import ch.epfl.bluebrain.nexus.iam.config.Contexts._
import ch.epfl.bluebrain.nexus.iam.types.Identity.{Anonymous, Subject}
import ch.epfl.bluebrain.nexus.rdf.implicits._
import io.circe.{Encoder, Json}


  val anonymous: Caller = Caller(Anonymous: Subject, Set[Identity](Anonymous))

  object JsonLd {
    final implicit def callerEncoder(
        implicit
        I: Encoder[Identity],
        http: HttpConfig
    ): Encoder[Caller] =
      Encoder.instance[Caller] { caller =>
        Json
          .obj(
            "identities" -> Encoder.encodeList(I)(caller.identities.toList.sortBy(_.id.asUri))
          )
          .addContext(iamCtxUri)
          .addContext(resourceCtxUri)
      }
  }
} 
Example 189
Source File: TokenRejection.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.auth

import com.github.ghik.silencer.silent
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}


  final case object InvalidAccessToken
      extends TokenRejection(
        "The token is invalid; possible causes are: incorrect signature, the token is expired or the 'nbf' value was not met."
      )

  @silent // rejectionConfig is not recognized as being used
  implicit val tokenRejectionEncoder: Encoder[TokenRejection] = {
    implicit val rejectionConfig: Configuration = Configuration.default.withDiscriminator("@type")
    val enc                                     = deriveConfiguredEncoder[TokenRejection]
    Encoder.instance(r => enc(r) deepMerge Json.obj("reason" -> Json.fromString(r.msg)))
  }
} 
Example 190
Source File: EventSerializer.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.io

import java.nio.charset.Charset

import akka.actor.ExtendedActorSystem
import akka.serialization.SerializerWithStringManifest
import ch.epfl.bluebrain.nexus.iam.acls.AclEvent
import ch.epfl.bluebrain.nexus.iam.config.AppConfig.HttpConfig
import ch.epfl.bluebrain.nexus.iam.config.Settings
import ch.epfl.bluebrain.nexus.iam.permissions.PermissionsEvent
import ch.epfl.bluebrain.nexus.iam.realms.RealmEvent
import ch.epfl.bluebrain.nexus.iam.types.GrantType.Camel._
import ch.epfl.bluebrain.nexus.rdf.Iri.Url
import ch.epfl.bluebrain.nexus.rdf.implicits._
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto._
import io.circe.parser._
import io.circe.syntax._
import io.circe.{Decoder, Encoder, Printer}


class EventSerializer(system: ExtendedActorSystem) extends SerializerWithStringManifest {
  private val utf8 = Charset.forName("UTF-8")

  private val printer = Printer.noSpaces.copy(dropNullValues = true)

  private[io] implicit val http: HttpConfig = Settings(system).appConfig.http

  private[io] implicit val config: Configuration = Configuration.default.withDiscriminator("@type")

  private[io] implicit val urlEncoder: Encoder[Url] =
    Encoder.encodeString.contramap(_.asUri)
  private[io] implicit val urlDecoder: Decoder[Url] =
    Decoder.decodeString.emap(Url.apply)

  private[io] implicit val permissionEventEncoder: Encoder[PermissionsEvent] = deriveConfiguredEncoder[PermissionsEvent]
  private[io] implicit val permissionEventDecoder: Decoder[PermissionsEvent] = deriveConfiguredDecoder[PermissionsEvent]
  private[io] implicit val aclEventEncoder: Encoder[AclEvent]                = deriveConfiguredEncoder[AclEvent]
  private[io] implicit val aclEventDecoder: Decoder[AclEvent]                = deriveConfiguredDecoder[AclEvent]
  private[io] implicit val realmEventEncoder: Encoder[RealmEvent]            = deriveConfiguredEncoder[RealmEvent]
  private[io] implicit val realmEventDecoder: Decoder[RealmEvent]            = deriveConfiguredDecoder[RealmEvent]

  override val identifier: Int = 1225

  override def manifest(o: AnyRef): String = o match {
    case _: PermissionsEvent => "permissions-event"
    case _: AclEvent         => "acl-event"
    case _: RealmEvent       => "realm-event"
    case other =>
      throw new IllegalArgumentException(
        s"Cannot determine manifest for unknown type: '${other.getClass.getCanonicalName}'"
      )
  }
  override def toBinary(o: AnyRef): Array[Byte] = o match {
    case ev: PermissionsEvent => ev.asJson.printWith(printer).getBytes(utf8)
    case ev: AclEvent         => ev.asJson.printWith(printer).getBytes(utf8)
    case ev: RealmEvent       => ev.asJson.printWith(printer).getBytes(utf8)
    case other =>
      throw new IllegalArgumentException(s"Cannot serialize unknown type: '${other.getClass.getCanonicalName}'")
  }
  override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef = manifest match {
    case "permissions-event" =>
      val str = new String(bytes, utf8)
      decode[PermissionsEvent](str)
        .getOrElse(throw new IllegalArgumentException(s"Cannot deserialize value: '$str' to 'PermissionsEvent'"))
    case "acl-event" =>
      val str = new String(bytes, utf8)
      decode[AclEvent](str)
        .getOrElse(throw new IllegalArgumentException(s"Cannot deserialize value: '$str' to 'AclEvent'"))
    case "realm-event" =>
      val str = new String(bytes, utf8)
      decode[RealmEvent](str)
        .getOrElse(throw new IllegalArgumentException(s"Cannot deserialize value: '$str' to 'RealmEvent'"))
    case other =>
      throw new IllegalArgumentException(s"Cannot deserialize type with unknown manifest: '$other'")
  }
} 
Example 191
Source File: GrantTypeSpec.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.types

import ch.epfl.bluebrain.nexus.commons.test.EitherValues
import ch.epfl.bluebrain.nexus.iam.types.GrantType._
import io.circe.{Decoder, Encoder, Json}
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike
import org.scalatest.Inspectors

class GrantTypeSpec extends AnyWordSpecLike with Matchers with Inspectors with EitherValues {

  "A GrantType" when {
    "using Camel encoders" should {
      import GrantType.Camel._
      val map = Map(
        AuthorizationCode -> "authorizationCode",
        Implicit          -> "implicit",
        Password          -> "password",
        ClientCredentials -> "clientCredentials",
        DeviceCode        -> "deviceCode",
        RefreshToken      -> "refreshToken"
      )
      "be encoded properly" in {
        val encoder = implicitly[Encoder[GrantType]]
        forAll(map.toList) {
          case (gt, expected) =>
            encoder(gt) shouldEqual Json.fromString(expected)
        }
      }
      "be decoded properly" in {
        val decoder = implicitly[Decoder[GrantType]]
        forAll(map.toList) {
          case (expected, gt) =>
            decoder.decodeJson(Json.fromString(gt)).rightValue shouldEqual expected
        }
      }
      "fail to decode for unknown string" in {
        val decoder = implicitly[Decoder[GrantType]]
        decoder.decodeJson(Json.fromString("incorrect")).leftValue
      }
    }
    "using Snake encoders" should {
      import GrantType.Snake._
      val map = Map(
        AuthorizationCode -> "authorization_code",
        Implicit          -> "implicit",
        Password          -> "password",
        ClientCredentials -> "client_credentials",
        DeviceCode        -> "device_code",
        RefreshToken      -> "refresh_token"
      )
      "be encoded properly" in {
        val encoder = implicitly[Encoder[GrantType]]
        forAll(map.toList) {
          case (gt, expected) =>
            encoder(gt) shouldEqual Json.fromString(expected)
        }
      }
      "be decoded properly" in {
        val decoder = implicitly[Decoder[GrantType]]
        forAll(map.toList) {
          case (expected, gtString) =>
            decoder.decodeJson(Json.fromString(gtString)).rightValue shouldEqual expected
        }
      }
      "fail to decode for unknown string" in {
        val decoder = implicitly[Decoder[GrantType]]
        decoder.decodeJson(Json.fromString("incorrect")).leftValue
      }
    }
  }

} 
Example 192
Source File: EnumerationEncoder.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras.encoding

import io.circe.{ Encoder, Json }
import io.circe.generic.extras.Configuration
import scala.annotation.implicitNotFound
import shapeless.{ :+:, CNil, Coproduct, HNil, Inl, Inr, LabelledGeneric, Witness }
import shapeless.labelled.FieldType

@implicitNotFound(
  """Could not find EnumerationEncoder for type ${A}.
Some possible causes for this:
- ${A} isn't a case class or sealed trat
- some of ${A}'s members don't have codecs of their own
- missing implicit Configuration"""
)
abstract class EnumerationEncoder[A] extends Encoder[A]

object EnumerationEncoder {
  implicit val encodeEnumerationCNil: EnumerationEncoder[CNil] = new EnumerationEncoder[CNil] {
    def apply(a: CNil): Json = sys.error("Cannot encode CNil")
  }

  implicit def encodeEnumerationCCons[K <: Symbol, V, R <: Coproduct](implicit
    witK: Witness.Aux[K],
    gen: LabelledGeneric.Aux[V, HNil],
    encodeR: EnumerationEncoder[R],
    config: Configuration = Configuration.default
  ): EnumerationEncoder[FieldType[K, V] :+: R] = new EnumerationEncoder[FieldType[K, V] :+: R] {
    def apply(a: FieldType[K, V] :+: R): Json = a match {
      case Inl(l) => Json.fromString(config.transformConstructorNames(witK.value.name))
      case Inr(r) => encodeR(r)
    }
  }

  implicit def encodeEnumeration[A, Repr <: Coproduct](implicit
    gen: LabelledGeneric.Aux[A, Repr],
    encodeR: EnumerationEncoder[Repr]
  ): EnumerationEncoder[A] =
    new EnumerationEncoder[A] {
      def apply(a: A): Json = encodeR(gen.to(a))
    }
} 
Example 193
Source File: UnwrappedEncoder.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras.encoding

import io.circe.{ Encoder, Json }
import scala.annotation.implicitNotFound
import shapeless.{ ::, Generic, HNil, Lazy }

@implicitNotFound(
  """Could not find UnwrappedEncoder for type ${A}.
Some possible causes for this:
- ${A} isn't a case class or sealed trat
- some of ${A}'s members don't have codecs of their own
- missing implicit Configuration"""
)
abstract class UnwrappedEncoder[A] extends Encoder[A]

object UnwrappedEncoder {
  implicit def encodeUnwrapped[A, R](implicit
    gen: Lazy[Generic.Aux[A, R :: HNil]],
    encodeR: Encoder[R]
  ): UnwrappedEncoder[A] = new UnwrappedEncoder[A] {
    override def apply(a: A): Json =
      encodeR(gen.value.to(a).head)
  }
} 
Example 194
Source File: ReprAsObjectEncoder.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras.encoding
import io.circe.{ Encoder, Json, JsonObject }
import io.circe.generic.extras.ConfigurableDeriver
import scala.annotation.implicitNotFound
import scala.language.experimental.macros


@implicitNotFound(
  """Could not find ReprAsObjectEncoder for type ${A}.
Some possible causes for this:
- ${A} isn't a case class or sealed trat
- some of ${A}'s members don't have codecs of their own
- missing implicit Configuration"""
)
trait ReprAsObjectEncoder[A] extends Encoder.AsObject[A] {
  def configuredEncodeObject(a: A)(
    transformMemberNames: String => String,
    transformDiscriminator: String => String,
    discriminator: Option[String]
  ): JsonObject

  final protected[this] def addDiscriminator[B](
    encode: Encoder[B],
    value: B,
    name: String,
    discriminator: Option[String]
  ): JsonObject = discriminator match {
    case None => JsonObject.singleton(name, encode(value))
    case Some(disc) =>
      encode match {
        case oe: Encoder.AsObject[B] @unchecked => oe.encodeObject(value).add(disc, Json.fromString(name))
        case _                                  => JsonObject.singleton(name, encode(value))
      }
  }

  final def encodeObject(a: A): JsonObject = configuredEncodeObject(a)(Predef.identity, Predef.identity, None)
}

object ReprAsObjectEncoder {
  implicit def deriveReprAsObjectEncoder[R]: ReprAsObjectEncoder[R] =
    macro ConfigurableDeriver.deriveConfiguredEncoder[R]
} 
Example 195
Source File: ConfiguredAsObjectCodec.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras.codec

import io.circe.{ Decoder, Encoder, HCursor, JsonObject }
import io.circe.generic.codec.DerivedAsObjectCodec
import io.circe.generic.extras.{ Configuration, JsonKey }
import io.circe.generic.extras.decoding.ConfiguredDecoder
import io.circe.generic.extras.encoding.ConfiguredAsObjectEncoder
import io.circe.generic.extras.util.RecordToMap
import scala.annotation.implicitNotFound
import shapeless.{ Annotations, Coproduct, Default, HList, LabelledGeneric, Lazy }
import shapeless.ops.hlist.ToTraversable
import shapeless.ops.record.Keys

@implicitNotFound(
  """Could not find ConfiguredAsObjectCodec for type ${A}.
Some possible causes for this:
- ${A} isn't a case class or sealed trat
- some of ${A}'s members don't have codecs of their own
- missing implicit Configuration"""
)
abstract class ConfiguredAsObjectCodec[A] extends DerivedAsObjectCodec[A]

object ConfiguredAsObjectCodec {
  implicit def codecForCaseClass[A, R <: HList, D <: HList, F <: HList, K <: HList](implicit
    gen: LabelledGeneric.Aux[A, R],
    codec: Lazy[ReprAsObjectCodec[R]],
    defaults: Default.AsRecord.Aux[A, D],
    defaultMapper: RecordToMap[D],
    config: Configuration,
    fields: Keys.Aux[R, F],
    fieldsToList: ToTraversable.Aux[F, List, Symbol],
    keys: Annotations.Aux[JsonKey, A, K],
    keysToList: ToTraversable.Aux[K, List, Option[JsonKey]]
  ): ConfiguredAsObjectCodec[A] = new ConfiguredAsObjectCodec[A] {
    private[this] val decodeA: Decoder[A] =
      ConfiguredDecoder.decodeCaseClass[A, R, D, F, K](
        gen,
        codec,
        defaults,
        defaultMapper,
        config,
        fields,
        fieldsToList,
        keys,
        keysToList
      )

    private[this] val encodeA: Encoder.AsObject[A] =
      ConfiguredAsObjectEncoder.encodeCaseClass[A, R, F, K](gen, codec, config, fields, fieldsToList, keys, keysToList)

    final def apply(c: HCursor): Decoder.Result[A] = decodeA.apply(c)
    final override def decodeAccumulating(c: HCursor): Decoder.AccumulatingResult[A] = decodeA.decodeAccumulating(c)

    final def encodeObject(a: A): JsonObject = encodeA.encodeObject(a)
  }

  implicit def codecForAdt[A, R <: Coproduct](implicit
    gen: LabelledGeneric.Aux[A, R],
    codec: Lazy[ReprAsObjectCodec[R]],
    config: Configuration
  ): ConfiguredAsObjectCodec[A] = new ConfiguredAsObjectCodec[A] {
    private[this] val decodeA: Decoder[A] =
      ConfiguredDecoder.decodeAdt[A, R](gen, codec, config)

    private[this] val encodeA: Encoder.AsObject[A] =
      ConfiguredAsObjectEncoder.encodeAdt[A, R](gen, codec, config)

    final def apply(c: HCursor): Decoder.Result[A] = decodeA.apply(c)
    final override def decodeAccumulating(c: HCursor): Decoder.AccumulatingResult[A] = decodeA.decodeAccumulating(c)

    final def encodeObject(a: A): JsonObject = encodeA.encodeObject(a)
  }
} 
Example 196
Source File: UnwrappedCodec.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras.codec

import io.circe.{ Codec, Decoder, Encoder, HCursor, Json }
import scala.annotation.implicitNotFound
import shapeless.{ ::, Generic, HNil, Lazy }

@implicitNotFound(
  """Could not find UnwrappedCodec for type ${A}.
Some possible causes for this:
- ${A} isn't a case class or sealed trat
- some of ${A}'s members don't have codecs of their own
- missing implicit Configuration"""
)
abstract class UnwrappedCodec[A] extends Codec[A]

object UnwrappedCodec {
  implicit def codecForUnwrapped[A, R](implicit
    gen: Lazy[Generic.Aux[A, R :: HNil]],
    decodeR: Decoder[R],
    encodeR: Encoder[R]
  ): UnwrappedCodec[A] = new UnwrappedCodec[A] {

    override def apply(c: HCursor): Decoder.Result[A] =
      decodeR(c) match {
        case Right(unwrapped) => Right(gen.value.from(unwrapped :: HNil))
        case l @ Left(_)      => l.asInstanceOf[Decoder.Result[A]]
      }
    override def apply(a: A): Json =
      encodeR(gen.value.to(a).head)
  }
} 
Example 197
Source File: ConfiguredJsonCodecWithKeySuite.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras

import cats.kernel.Eq
import io.circe.{ Decoder, Encoder }
import io.circe.literal._
import io.circe.testing.CodecTests
import org.scalacheck.{ Arbitrary, Gen }
import org.scalacheck.Arbitrary.arbitrary

object ConfiguredJsonCodecWithKeySuite {
  implicit val customConfig: Configuration =
    Configuration.default.withSnakeCaseMemberNames.withDefaults.withDiscriminator("type").withSnakeCaseConstructorNames

  @ConfiguredJsonCodec
  sealed trait ConfigExampleBase
  case class ConfigExampleFoo(thisIsAField: String, a: Int = 0, @JsonKey("myField") b: Double) extends ConfigExampleBase

  object ConfigExampleFoo {
    implicit val eqConfigExampleFoo: Eq[ConfigExampleFoo] = Eq.fromUniversalEquals
    val genConfigExampleFoo: Gen[ConfigExampleFoo] = for {
      thisIsAField <- arbitrary[String]
      a <- arbitrary[Int]
      b <- arbitrary[Double]
    } yield ConfigExampleFoo(thisIsAField, a, b)
    implicit val arbitraryConfigExampleFoo: Arbitrary[ConfigExampleFoo] = Arbitrary(genConfigExampleFoo)
  }

  object ConfigExampleBase {
    implicit val eqConfigExampleBase: Eq[ConfigExampleBase] = Eq.fromUniversalEquals
    val genConfigExampleBase: Gen[ConfigExampleBase] =
      ConfigExampleFoo.genConfigExampleFoo
    implicit val arbitraryConfigExampleBase: Arbitrary[ConfigExampleBase] = Arbitrary(genConfigExampleBase)
  }
}

class ConfiguredJsonCodecWithKeySuite extends CirceSuite {
  import ConfiguredJsonCodecWithKeySuite._

  checkLaws("Codec[ConfigExampleBase]", CodecTests[ConfigExampleBase].codec)

  "ConfiguredJsonCodec" should "support key annotation and configuration" in forAll { (f: String, b: Double) =>
    val foo: ConfigExampleBase = ConfigExampleFoo(f, 0, b)
    val json = json"""{ "type": "config_example_foo", "this_is_a_field": $f, "myField": $b}"""
    val expected = json"""{ "type": "config_example_foo", "this_is_a_field": $f, "a": 0, "myField": $b}"""

    assert(Encoder[ConfigExampleBase].apply(foo) === expected)
    assert(Decoder[ConfigExampleBase].decodeJson(json) === Right(foo))
  }
} 
Example 198
Source File: EnumerationSemiautoDerivedSuite.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras

import io.circe.{ Codec, Decoder, Encoder }
import io.circe.generic.extras.semiauto._
import io.circe.literal._
import io.circe.testing.CodecTests
import shapeless.test.illTyped

import examples._

class EnumerationSemiautoDerivedSuite extends CirceSuite {
  implicit val decodeCardinalDirection: Decoder[CardinalDirection] = deriveEnumerationDecoder
  implicit val encodeCardinalDirection: Encoder[CardinalDirection] = deriveEnumerationEncoder
  val codecForCardinalDirection: Codec[CardinalDirection] = deriveEnumerationCodec

  checkLaws("Codec[CardinalDirection]", CodecTests[CardinalDirection].codec)
  checkLaws(
    "Codec[CardinalDirection] via Codec",
    CodecTests[CardinalDirection](codecForCardinalDirection, codecForCardinalDirection).codec
  )
  checkLaws(
    "Codec[CardinalDirection] via Decoder and Codec",
    CodecTests[CardinalDirection](implicitly, codecForCardinalDirection).codec
  )
  checkLaws(
    "Codec[CardinalDirection] via Encoder and Codec",
    CodecTests[CardinalDirection](codecForCardinalDirection, implicitly).codec
  )

  "deriveEnumerationDecoder" should "not compile on an ADT with case classes" in {
    implicit val config: Configuration = Configuration.default
    illTyped("deriveEnumerationDecoder[ExtendedCardinalDirection]")
  }

  it should "respect Configuration" in {
    implicit val config: Configuration = Configuration.default.withSnakeCaseConstructorNames
    val decodeMary = deriveEnumerationDecoder[Mary]
    val expected = json""""little_lamb""""
    assert(decodeMary.decodeJson(expected) === Right(LittleLamb))
  }

  "deriveEnumerationEncoder" should "not compile on an ADT with case classes" in {
    implicit val config: Configuration = Configuration.default
    illTyped("deriveEnumerationEncoder[ExtendedCardinalDirection]")
  }

  it should "respect Configuration" in {
    implicit val config: Configuration = Configuration.default.withSnakeCaseConstructorNames
    val encodeMary = deriveEnumerationEncoder[Mary]
    val expected = json""""little_lamb""""
    assert(encodeMary(LittleLamb) === expected)
  }
} 
Example 199
Source File: BuildEvent.scala    From seed   with Apache License 2.0 5 votes vote down vote up
package seed.model

import io.circe.{Encoder, Json}

sealed abstract class BuildEvent(val id: String)
object BuildEvent {
  case class Compiled(module: String, platform: Platform)
      extends BuildEvent("compiled")
  case class Compiling(module: String, platform: Platform)
      extends BuildEvent("compiling")
  case class Failed(module: String, platform: Platform)
      extends BuildEvent("failed")
  case class Linked(path: String) extends BuildEvent("linked")

  implicit val encodeBuildEvent: Encoder[BuildEvent] = be =>
    Json.fromFields(
      List("event" -> Json.fromString(be.id)) ++
        (be match {
          case Compiled(module, platform) =>
            List(
              "module"   -> Json.fromString(module),
              "platform" -> Json.fromString(platform.id)
            )
          case Compiling(module, platform) =>
            List(
              "module"   -> Json.fromString(module),
              "platform" -> Json.fromString(platform.id)
            )
          case Failed(module, platform) =>
            List(
              "module"   -> Json.fromString(module),
              "platform" -> Json.fromString(platform.id)
            )
          case Linked(path) =>
            List("path" -> Json.fromString(path))
        })
    )
} 
Example 200
Source File: persistentEncoderUtil.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.example

import java.nio.ByteBuffer
import java.nio.charset.StandardCharsets

import aecor.runtime.akkapersistence.serialization.{
  DecodingFailure,
  PersistentDecoder,
  PersistentEncoder,
  PersistentRepr
}
import io.circe.{ Decoder, Encoder, jawn }

object persistentEncoderUtil {
  def circePersistentEncoder[A](implicit encoder: Encoder[A]): PersistentEncoder[A] =
    PersistentEncoder.instance(
      e => PersistentRepr("", encoder(e).noSpaces.getBytes(StandardCharsets.UTF_8))
    )

  def circePersistentDecoder[A](implicit decoder: Decoder[A]): PersistentDecoder[A] =
    PersistentDecoder.instance(
      repr =>
        jawn
          .parseByteBuffer(ByteBuffer.wrap(repr.payload))
          .flatMap(decoder.decodeJson)
          .left
          .map(DecodingFailure.fromThrowable)
    )
}