io.circe.Decoder Scala Examples

The following examples show how to use io.circe.Decoder. 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: TopicConfigurationParser.scala    From kafka-configurator   with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
package com.sky.kafka.configurator

import java.io.{Reader => JReader}

import cats.instances.either._
import cats.instances.list._
import cats.syntax.either._
import cats.syntax.traverse._
import io.circe
import io.circe.generic.AutoDerivation
import io.circe.yaml.parser._
import io.circe.{Decoder, DecodingFailure, Json}

import scala.collection.immutable.ListMap

object TopicConfigurationParser extends AutoDerivation {

  def apply(topicConfigReader: JReader): Either[circe.Error, List[Topic]] =
    for {
      ymlAsJson <- parse(topicConfigReader)
      topicConfigs <- if (ymlAsJson.isBoolean) List.empty[Topic].asRight else ymlAsJson.as[List[Topic]]
    } yield topicConfigs

  case class TopicConfig(partitions: Int, replication: Int, config: Map[String, String])

  implicit val topicsDecoder: Decoder[List[Topic]] = Decoder.instance { cursor =>
    for {
      configMap <- cursor.as[ListMap[String, TopicConfig]]
      topics = configMap.map { case (name, conf) => Topic(name, conf.partitions, conf.replication, conf.config) }
    } yield topics.toList
  }

  implicit val stringMapDecoder: Decoder[Map[String, String]] = Decoder.instance { cursor =>
    def stringify(json: Json): Json =
      json.asNumber.fold(json)(num =>
        Json.fromString(num.toLong.fold(num.toDouble.toString)(_.toString)))

    def failWithMsg(msg: String) = DecodingFailure(msg, List.empty)

    for {
      jsonObj <- cursor.value.asObject.toRight(failWithMsg(s"${cursor.value} is not an object"))
      valuesAsJsonStrings = jsonObj.mapValues(stringify)
      stringMap <- valuesAsJsonStrings.toList.traverse[Decoder.Result, (String, String)] {
        case (key, json) => json.asString.toRight(failWithMsg(s"$json is not a string")).map(key -> _)
      }
    } yield stringMap.toMap
  }
} 
Example 3
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 4
Source File: JWT.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.network.http.server.authentication

import cats.effect.IO
import io.circe.generic.auto._
import io.circe.{Decoder, ObjectEncoder}
import tsec.authentication.{AugmentedJWT, JWTAuthenticator, SecuredRequestHandler}
import tsec.common.SecureRandomId
import tsec.jws.mac.JWTMac
import tsec.jwt.JWTClaims
import tsec.mac.jca.{HMACSHA256, MacSigningKey}

import scala.concurrent.duration._

object JWT {
  class Unbacked(key: MacSigningKey[HMACSHA256]) {
    private val userStore = DummyBackingStore.apply[Long, User](_.id)

    private val authenticator = JWTAuthenticator.unbacked.inBearerToken(
      expiryDuration = 10.minutes, //Absolute expiration time
      maxIdle = None,
      identityStore = userStore,
      signingKey = key
    )

    val Auth = SecuredRequestHandler(authenticator)
  }

  class Stateful(key: MacSigningKey[HMACSHA256]) {
    private val jwtStore =
      DummyBackingStore.apply[SecureRandomId, AugmentedJWT[HMACSHA256, Long]](s => SecureRandomId.coerce(s.id))
    private val userStore = DummyBackingStore.apply[Long, User](_.id)

    private val authenticator = JWTAuthenticator.backed.inBearerToken(
      expiryDuration = 10.minutes, //Absolute expiration time
      maxIdle = None,
      tokenStore = jwtStore,
      identityStore = userStore,
      signingKey = key
    )

    val Auth =
      SecuredRequestHandler(authenticator)
  }

  class Stateless(key: MacSigningKey[HMACSHA256]) {
    private val authenticator = JWTAuthenticator.pstateless.inBearerToken[IO, User, HMACSHA256](
      expiryDuration = 10.minutes,
      maxIdle = None,
      signingKey = key
    )

    val Auth =
      SecuredRequestHandler(authenticator)
  }

  final case class CustomClaim(suchChars: String, much32Bits: Int, so64Bits: Long)
  val claim = "JBOK"

  def withCustomClaims[A: ObjectEncoder: Decoder](
      key: String,
      value: A,
      duration: Option[FiniteDuration] = None
  ): IO[JWTClaims] =
    JWTClaims
      .withDuration[IO](expiration = duration).flatMap(_.withCustomFieldF[IO, A](key, value))

  def sign(claims: JWTClaims, key: MacSigningKey[HMACSHA256]): IO[JWTMac[HMACSHA256]] =
    for {
      jwt <- JWTMac.build[IO, HMACSHA256](claims, key) //You can sign and build a jwt object directly
    } yield jwt

  def signToString(claims: JWTClaims, key: MacSigningKey[HMACSHA256]): IO[String] =
    sign(claims, key).map(_.toEncodedString)

  def parseFromString(jwt: String, key: MacSigningKey[HMACSHA256]): IO[JWTMac[HMACSHA256]] =
    JWTMac.verifyAndParse[IO, HMACSHA256](jwt, key)

  def verifyFromString(jwt: String, key: MacSigningKey[HMACSHA256]): IO[Boolean] =
    JWTMac.verifyFromStringBool[IO, HMACSHA256](jwt, key)
} 
Example 5
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 6
Source File: APIWalTail.scala    From scarango   with MIT License 5 votes vote down vote up
package com.outr.arango.api

import io.circe.Decoder.Result
import io.youi.client.HttpClient
import io.youi.http.{HeaderKey, HttpMethod}
import io.youi.net._
import io.circe.{Decoder, DecodingFailure, HCursor}
import profig.JsonUtil

import scala.concurrent.{ExecutionContext, Future}
      
object APIWalTail {
  private implicit def operationTypeDecoder: Decoder[OperationType] = new Decoder[OperationType] {
    override def apply(c: HCursor): Result[OperationType] = c.value.asNumber match {
      case Some(n) => Right(OperationType(n.toInt.get))
      case None => Left(DecodingFailure(s"OperationType not a number: ${c.value}", Nil))
    }
  }

  def get(client: HttpClient,
          global: Option[Boolean] = None,
          from: Option[Long] = None,
          to: Option[Long] = None,
          lastScanned: Long = 0L,
          chunkSize: Option[Long] = None,
          syncerId: Option[Long] = None,
          serverId: Option[Long] = None,
          clientId: Option[String] = None)(implicit ec: ExecutionContext): Future[WALOperations] = {
    client
      .method(HttpMethod.Get)
      .path(path"/_api/wal/tail", append = true)
      .param[Option[Long]]("from", from, None)
      .param[Option[Long]]("to", to, None)
      .param[Long]("lastScanned", lastScanned, 0L)
      .param[Option[Boolean]]("global", global, None)
      .param[Option[Long]]("chunkSize", chunkSize, None)
      .param[Option[Long]]("syncerId", syncerId, None)
      .param[Option[Long]]("serverId", serverId, None)
      .param[Option[String]]("clientId", clientId, None)
      .send()
      .map { response =>
        val lines = response.content.map(_.asString).getOrElse("").split('\n').toList
        val operations = lines.map(_.trim).collect {
          case line if line.nonEmpty => JsonUtil.fromJsonString[WALOperation](line)
        }
        val headers = response.headers
        WALOperations(
          client = client,
          global = global,
          chunkSize = chunkSize,
          syncerId = syncerId,
          serverId = serverId,
          clientId = clientId,
          checkMore = headers.first(HeaderKey("X-Arango-Replication-Checkmore")).exists(_.toBoolean),
          fromPresent = headers.first(HeaderKey("X-Arango-Replication-Frompresent")).exists(_.toBoolean),
          lastIncluded = headers.first(HeaderKey("X-Arango-Replication-Lastincluded")).map(_.toLong).getOrElse(-1L),
          lastScanned = headers.first(HeaderKey("X-Arango-Replication-Lastscanned")).map(_.toLong).getOrElse(-1L),
          lastTick = headers.first(HeaderKey("X-Arango-Replication-Lasttick")).map(_.toLong).getOrElse(-1L),
          operations = operations
        )
      }
  }
} 
Example 7
Source File: TransactionStatus.scala    From scarango   with MIT License 5 votes vote down vote up
package com.outr.arango.transaction

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

sealed trait TransactionStatus

object TransactionStatus {
  case object Running extends TransactionStatus
  case object Committed extends TransactionStatus
  case object Aborted extends TransactionStatus

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

  def apply(value: String): TransactionStatus = value match {
    case "running" => Running
    case "committed" => Committed
    case "aborted" => Aborted
  }
} 
Example 8
Source File: Transaction.scala    From scarango   with MIT License 5 votes vote down vote up
package com.outr.arango.transaction

import com.outr.arango.Graph
import io.circe.Decoder.Result
import io.circe.{Decoder, DecodingFailure, HCursor}

import scala.concurrent.{ExecutionContext, Future}

case class Transaction(id: String, status: TransactionStatus) {
  private[arango] var graph: Option[Graph] = None

  def withGraph(option: Option[Graph]): Transaction = {
    graph = option
    this
  }

  def checkStatus()(implicit ec: ExecutionContext): Future[Transaction] = {
    val g = graph.getOrElse(throw new RuntimeException("Graph not included!"))
    g.arangoDatabase.transactionStatus(id).map(_.withGraph(graph))
  }

  def commit()(implicit ec: ExecutionContext): Future[Unit] = {
    val g = graph.getOrElse(throw new RuntimeException("Graph not included!"))
    g.arangoDatabase.transactionCommit(id).map { t =>
      t.status match {
        case TransactionStatus.Running => throw new RuntimeException("Commit failed, transaction still running!")
        case TransactionStatus.Committed => ()
        case TransactionStatus.Aborted => throw new RuntimeException("Commit failed, transaction aborted!")
      }
    }
  }

  def abort()(implicit ec: ExecutionContext): Future[Unit] = {
    val g = graph.getOrElse(throw new RuntimeException("Graph not included!"))
    g.arangoDatabase.transactionAbort(id).map { t =>
      t.status match {
        case TransactionStatus.Running => throw new RuntimeException("Abort failed, transaction still running!")
        case TransactionStatus.Committed => throw new RuntimeException("Abort failed, transaction committed!")
        case TransactionStatus.Aborted => ()
      }
    }
  }
} 
Example 9
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 10
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 11
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 12
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 13
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 14
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 15
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 16
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 17
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 18
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 19
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 20
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 21
Source File: ExtractorSpec.scala    From seals   with Apache License 2.0 5 votes vote down vote up
package dev.tauri.seals
package checker

import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

import io.circe.Decoder

import circe.Codecs._

class ExtractorSpec extends AnyFlatSpec with Matchers {

  val decoder = Decoder[Model]
  val pack = this.getClass.getPackage.getName

  val fooName = s"$pack.Foo"
  val ccName = s"$pack.CC"
  val wfooName = s"$pack.Wrap.WFoo"
  val wccName = s"$pack.Wrap.WCC"

  // force WFoo subclasses (SI-7046 workaround):
  def dummy1: Wrap.Bar = sys.error("dummy1")
  def dummy2: Wrap.Baz.type = sys.error("dummy2")

  val extractor = Extractor(
    this.getClass.getClassLoader,
    new java.io.File(this.getClass.getProtectionDomain.getCodeSource.getLocation.toURI)
  )

  "Extractor#allClasses" should "find every class" in {
    extractor.allClasses(pack) should contain allOf (
      "Foo",
      "Foo$",
      "CC",
      "CC$",
      "Wrap$"
    )
  }

  "Extractor#extractAll" should "find all marked classes in a package" in {
    val models: Map[String, Model] = extractor.extractAll(pack)
    val expected = Map(
      fooName -> Foo.reifiedFoo.model,
      ccName -> CC.reifiedCC.model,
      wfooName -> Wrap.WFoo.reifiedWFoo.model,
      wccName -> Wrap.WCC.reifiedWCC.model
    )
    models should === (expected)
  }

  "Extractor#allSchemas" should "collect all annotated classes" in {
    extractor.allSchemasOfPackage(pack).map(_.fullName).toSet should === (Set(
      fooName,
      ccName,
      wfooName,
      wccName
    ))
  }
} 
Example 22
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 23
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 24
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 25
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 26
Source File: Error.scala    From akka-http-oauth2-client   with Apache License 2.0 5 votes vote down vote up
package com.github.dakatsuka.akka.http.oauth2.client

import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.Materializer
import com.github.dakatsuka.akka.http.oauth2.client.utils.JsonUnmarshaller
import io.circe.Decoder

import scala.concurrent.{ ExecutionContext, Future }

object Error {
  sealed abstract class Code(val value: String)
  case object InvalidRequest       extends Code("invalid_request")
  case object InvalidClient        extends Code("invalid_client")
  case object InvalidToken         extends Code("invalid_token")
  case object InvalidGrant         extends Code("invalid_grant")
  case object InvalidScope         extends Code("invalid_scope")
  case object UnsupportedGrantType extends Code("unsupported_grant_type")
  case object Unknown              extends Code("unknown")

  object Code {
    def fromString(code: String): Code = code match {
      case "invalid_request"        => InvalidRequest
      case "invalid_client"         => InvalidClient
      case "invalid_token"          => InvalidToken
      case "invalid_grant"          => InvalidGrant
      case "invalid_scope"          => InvalidScope
      case "unsupported_grant_type" => UnsupportedGrantType
      case _                        => Unknown
    }
  }

  class UnauthorizedException(val code: Code, val description: String, val response: HttpResponse)
      extends RuntimeException(s"$code: $description")

  object UnauthorizedException extends JsonUnmarshaller {
    case class UnauthorizedResponse(error: String, errorDescription: String)

    implicit def decoder: Decoder[UnauthorizedResponse] = Decoder.instance { c =>
      for {
        error       <- c.downField("error").as[String].right
        description <- c.downField("error_description").as[String].right
      } yield UnauthorizedResponse(error, description)
    }

    def fromHttpResponse(response: HttpResponse)(implicit ec: ExecutionContext, mat: Materializer): Future[UnauthorizedException] = {
      Unmarshal(response).to[UnauthorizedResponse].map { r =>
        new UnauthorizedException(Code.fromString(r.error), r.errorDescription, response)
      }
    }
  }
} 
Example 27
Source File: JsonUnmarshaller.scala    From akka-http-oauth2-client   with Apache License 2.0 5 votes vote down vote up
package com.github.dakatsuka.akka.http.oauth2.client.utils

import akka.http.scaladsl.model.ContentTypeRange
import akka.http.scaladsl.model.MediaTypes.`application/json`
import akka.http.scaladsl.unmarshalling.{ FromEntityUnmarshaller, Unmarshaller }
import akka.util.ByteString
import io.circe.{ jawn, Decoder, Json }

trait JsonUnmarshaller {
  def unmarshallerContentTypes: Seq[ContentTypeRange] =
    List(`application/json`)

  implicit def jsonUnmarshaller: FromEntityUnmarshaller[Json] =
    Unmarshaller.byteStringUnmarshaller
      .forContentTypes(unmarshallerContentTypes: _*)
      .map {
        case ByteString.empty => throw Unmarshaller.NoContentException
        case data             => jawn.parseByteBuffer(data.asByteBuffer).fold(throw _, identity)
      }

  implicit def unmarshaller[A: Decoder]: FromEntityUnmarshaller[A] = {
    def decode(json: Json) = implicitly[Decoder[A]].decodeJson(json).fold(throw _, identity)
    jsonUnmarshaller.map(decode)
  }
} 
Example 28
Source File: AccessToken.scala    From akka-http-oauth2-client   with Apache License 2.0 5 votes vote down vote up
package com.github.dakatsuka.akka.http.oauth2.client

import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.Materializer
import com.github.dakatsuka.akka.http.oauth2.client.utils.JsonUnmarshaller
import io.circe.Decoder

import scala.concurrent.Future

case class AccessToken(
    accessToken: String,
    tokenType: String,
    expiresIn: Int,
    refreshToken: Option[String]
)

object AccessToken extends JsonUnmarshaller {
  implicit def decoder: Decoder[AccessToken] = Decoder.instance { c =>
    for {
      accessToken  <- c.downField("access_token").as[String].right
      tokenType    <- c.downField("token_type").as[String].right
      expiresIn    <- c.downField("expires_in").as[Int].right
      refreshToken <- c.downField("refresh_token").as[Option[String]].right
    } yield AccessToken(accessToken, tokenType, expiresIn, refreshToken)
  }

  def apply(response: HttpResponse)(implicit mat: Materializer): Future[AccessToken] = {
    Unmarshal(response).to[AccessToken]
  }
} 
Example 29
Source File: TestSuiteTests.scala    From circe-json-schema   with Apache License 2.0 5 votes vote down vote up
package io.circe.schema

import cats.data.Validated
import io.circe.{ Decoder, Json }
import java.io.File
import org.scalatest.flatspec.AnyFlatSpec

case class SchemaTestCase(description: String, data: Json, valid: Boolean)
case class SchemaTest(description: String, schema: Json, tests: List[SchemaTestCase])

object SchemaTestCase {
  implicit val decodeSchemaTestCase: Decoder[SchemaTestCase] = io.circe.generic.semiauto.deriveDecoder
}

object SchemaTest {
  implicit val decodeSchemaTest: Decoder[SchemaTest] = io.circe.generic.semiauto.deriveDecoder
}

class TestSuiteTests(path: String) extends AnyFlatSpec {
  val tests: List[SchemaTest] = io.circe.jawn
    .decodeFile[List[SchemaTest]](new File(path))
    .getOrElse(
      throw new Exception(s"Unable to load test file: $path")
    )

  tests.foreach {
    case SchemaTest(description, schema, tests) =>
      tests.foreach {
        case SchemaTestCase(caseDescription, data, valid) =>
          val expected = if (valid) "validate successfully" else "fail to validate"
          s"$description: $caseDescription" should expected in {
            val errors = Schema.load(schema).validate(data)

            if (valid) {
              assert(errors == Validated.valid(()))
            } else {
              assert(errors.isInvalid)
            }
          }

          it should s"$expected when schema is loaded from a string" in {
            val errors = Schema.loadFromString(schema.noSpaces).get.validate(data)

            if (valid) {
              assert(errors == Validated.valid(()))
            } else {
              assert(errors.isInvalid)
            }
          }
      }
  }
}

class AdditionalItemsTestSuiteTests extends TestSuiteTests("tests/tests/draft7/additionalItems.json")
class AdditionalPropertiesTestSuiteTests extends TestSuiteTests("tests/tests/draft7/additionalProperties.json")
class AllOfTestSuiteTests extends TestSuiteTests("tests/tests/draft7/allOf.json")
class AnyOfTestSuiteTests extends TestSuiteTests("tests/tests/draft7/anyOf.json")
class BooleanSchemaTestSuiteTests extends TestSuiteTests("tests/tests/draft7/boolean_schema.json")
class ConstTestSuiteTests extends TestSuiteTests("tests/tests/draft7/const.json")
class ContainsTestSuiteTests extends TestSuiteTests("tests/tests/draft7/contains.json")
class DefaultTestSuiteTests extends TestSuiteTests("tests/tests/draft7/default.json")
//class DefinitionsTestSuiteTests extends TestSuiteTests("tests/tests/draft7/definitions.json")
class EnumTestSuiteTests extends TestSuiteTests("tests/tests/draft7/enum.json")
class ExclusiveMaximumTestSuiteTests extends TestSuiteTests("tests/tests/draft7/exclusiveMaximum.json")
class ExclusiveMinimumTestSuiteTests extends TestSuiteTests("tests/tests/draft7/exclusiveMinimum.json")
class FormatTestSuiteTests extends TestSuiteTests("tests/tests/draft7/format.json")
class IfThenElseTestSuiteTests extends TestSuiteTests("tests/tests/draft7/if-then-else.json")
class ItemsTestSuiteTests extends TestSuiteTests("tests/tests/draft7/items.json")
class MaximumTestSuiteTests extends TestSuiteTests("tests/tests/draft7/maximum.json")
class MaxItemsTestSuiteTests extends TestSuiteTests("tests/tests/draft7/maxItems.json")
class MaxLengthTestSuiteTests extends TestSuiteTests("tests/tests/draft7/maxLength.json")
class MaxPropertiesTestSuiteTests extends TestSuiteTests("tests/tests/draft7/maxProperties.json")
class MinimumTestSuiteTests extends TestSuiteTests("tests/tests/draft7/minimum.json")
class MinItemsTestSuiteTests extends TestSuiteTests("tests/tests/draft7/minItems.json")
class MinLengthTestSuiteTests extends TestSuiteTests("tests/tests/draft7/minLength.json")
class MinPropertiesTestSuiteTests extends TestSuiteTests("tests/tests/draft7/minProperties.json")
class MultipleOfTestSuiteTests extends TestSuiteTests("tests/tests/draft7/multipleOf.json")
class NotTestSuiteTests extends TestSuiteTests("tests/tests/draft7/not.json")
class OneOfTestSuiteTests extends TestSuiteTests("tests/tests/draft7/oneOf.json")
class PatternTestSuiteTests extends TestSuiteTests("tests/tests/draft7/pattern.json")
class PatternPropertiesTestSuiteTests extends TestSuiteTests("tests/tests/draft7/patternProperties.json")
class PropertyNamesTestSuiteTests extends TestSuiteTests("tests/tests/draft7/propertyNames.json")
// Not currently running remote tests.
//class RefTestSuiteTests extends TestSuiteTests("tests/tests/draft7/ref.json")
//class RefRemoteTestSuiteTests extends TestSuiteTests("tests/tests/draft7/refRemote.json")
class RequiredTestSuiteTests extends TestSuiteTests("tests/tests/draft7/required.json")
class TypeTestSuiteTests extends TestSuiteTests("tests/tests/draft7/type.json")
class UniqueItemsTestSuiteTests extends TestSuiteTests("tests/tests/draft7/uniqueItems.json") 
Example 30
Source File: ParseOpenApi.scala    From skeuomorph   with Apache License 2.0 5 votes vote down vote up
package higherkindness.skeuomorph.openapi

import java.io.File

import higherkindness.droste._
import higherkindness.skeuomorph.Parser
import schema.OpenApi
import cats.effect.Sync
import cats.syntax.flatMap._
import cats.syntax.functor._
import cats.syntax.either._

object ParseOpenApi {
  import JsonDecoders._

  case class YamlSource(file: File)
  case class JsonSource(file: File)

  implicit def parseYamlOpenApi[F[_], T](implicit T: Embed[JsonSchemaF, T]): Parser[F, YamlSource, OpenApi[T]] =
    new Parser[F, YamlSource, OpenApi[T]] {
      import yaml.{Decoder => _, _}
      override def parse(input: YamlSource)(implicit S: Sync[F]): F[OpenApi[T]] =
        readContent(input.file).flatMap(x =>
          S.fromEither(
            yaml
              .Decoder[OpenApi[T]]
              .apply(x)
              .left
              .map(_.valueOr(identity))
          )
        )
    }

  implicit def parseJsonOpenApi[F[_], T](implicit T: Embed[JsonSchemaF, T]): Parser[F, JsonSource, OpenApi[T]] =
    new Parser[F, JsonSource, OpenApi[T]] {
      import io.circe.Decoder
      import io.circe.parser

      override def parse(input: JsonSource)(implicit S: Sync[F]): F[OpenApi[T]] =
        for {
          content <- readContent(input.file)
          json    <- S.fromEither(parser.parse(content))
          openApi <- S.fromEither(Decoder[OpenApi[T]].decodeJson(json))
        } yield openApi
    }

  private def readContent[F[_]: Sync](file: File): F[String] =
    Sync[F].delay {
      scala.io.Source
        .fromFile(file)
        .getLines()
        .toList
        .mkString("\n")
    }

} 
Example 31
Source File: CodacyConfigurationFile.scala    From codacy-analysis-cli   with GNU Affero General Public License v3.0 5 votes vote down vote up
package com.codacy.analysis.core.configuration

import better.files.File
import cats.syntax.show._
import com.codacy.analysis.core.files.Glob
import com.codacy.plugins.api.languages.{Language, Languages}
import io.circe.generic.auto._
import io.circe.yaml.parser
import io.circe.{Decoder, Json, _}
import play.api.libs.json.JsValue

import scala.util.{Properties, Try}

final case class LanguageConfiguration(extensions: Option[Set[String]])

final case class EngineConfiguration(excludePaths: Option[Set[Glob]],
                                     baseSubDir: Option[String],
                                     extraValues: Option[Map[String, JsValue]])

final case class CodacyConfigurationFile(engines: Option[Map[String, EngineConfiguration]],
                                         excludePaths: Option[Set[Glob]],
                                         languages: Option[Map[Language, LanguageConfiguration]]) {

  lazy val languageCustomExtensions: Map[Language, Set[String]] =
    languages.fold(Map.empty[Language, Set[String]])(_.map {
      case (lang, config) => (lang, config.extensions.getOrElse(Set.empty[String]))
    })
}

class CodacyConfigurationFileLoader {

  val filenames: Set[String] = Set(".codacy.yaml", ".codacy.yml")

  def load(directory: File): Either[String, CodacyConfigurationFile] = {
    search(directory).flatMap(configDir => parse(configDir.contentAsString))
  }

  def search(root: File): Either[String, File] = {
    filenames
      .map(root / _)
      .find(f => f.exists && f.isRegularFile)
      .fold[Either[String, File]](
        Left(s"Could not find Codacy configuration file. Make sure you have a file named like one of ${filenames
          .mkString(", ")}."))(Right(_))
  }

  def parse(yamlString: String): Either[String, CodacyConfigurationFile] = {
    for {
      json <- parser.parse(yamlString).left.map(_.show)
      cursor = HCursor.fromJson(json)
      configurationEither = Decoder[CodacyConfigurationFile].decodeAccumulating(cursor).toEither
      configuration <- configurationEither.left.map(_.toList.map(_.show).mkString(Properties.lineSeparator))
    } yield configuration
  }

}

object CodacyConfigurationFile {

  implicit val globDecoder: Decoder[Glob] = (c: HCursor) => c.as[String].map(Glob)

  implicit val languageKeyDecoder: KeyDecoder[Language] = (languageStr: String) => Languages.fromName(languageStr)

  implicit val decodeEngineConfiguration: Decoder[EngineConfiguration] =
    new Decoder[EngineConfiguration] {
      val engineConfigurationKeys = Set("enabled", "exclude_paths", "base_sub_dir")

      def apply(c: HCursor): Decoder.Result[EngineConfiguration] = {
        val extraKeys =
          c.keys.fold(List.empty[String])(_.to[List]).filter(key => !engineConfigurationKeys.contains(key))
        for {
          excludePaths <- c.downField("exclude_paths").as[Option[Set[Glob]]]
          baseSubDir <- c.downField("base_sub_dir").as[Option[String]]
        } yield {
          val extraToolConfigurations: Map[String, JsValue] = extraKeys.flatMap { extraKey =>
            c.downField(extraKey)
              .as[Json]
              .fold[Option[JsValue]](
                { _ =>
                  Option.empty
                },
                { json =>
                  Try(play.api.libs.json.Json.parse(json.noSpaces)).toOption
                })
              .map(value => (extraKey, value))
          }(collection.breakOut)

          EngineConfiguration(excludePaths, baseSubDir, Option(extraToolConfigurations).filter(_.nonEmpty))
        }
      }
    }

  implicit val decodeCodacyConfigurationFile: Decoder[CodacyConfigurationFile] =
    Decoder.forProduct3("engines", "exclude_paths", "languages")(CodacyConfigurationFile.apply)

} 
Example 32
Source File: TestUtils.scala    From codacy-analysis-cli   with GNU Affero General Public License v3.0 5 votes vote down vote up
package com.codacy.analysis.core.utils

import java.nio.file.attribute.PosixFilePermission
import java.nio.file.{Path, Paths}

import better.files.File
import com.codacy.plugins.api.results
import io.circe.Decoder
import org.specs2.concurrent.ExecutionEnv
import org.specs2.matcher.MatchResult

import scala.sys.process.Process

object TestUtils {

  implicit val categoryDecoder: Decoder[results.Pattern.Category.Value] =
    Decoder.decodeEnumeration(results.Pattern.Category)

  implicit val levelDecoder: Decoder[results.Result.Level.Value] =
    Decoder.decodeEnumeration(results.Result.Level)
  implicit val fileDecoder: Decoder[Path] = Decoder[String].map(Paths.get(_))
  implicit val executionEnv: ExecutionEnv = ExecutionEnv.fromGlobalExecutionContext

  def withClonedRepo[T](gitUrl: String, commitUUid: String)(block: (File, File) => MatchResult[T]): MatchResult[T] =
    (for {
      directory <- File.temporaryDirectory()
      file <- File.temporaryFile()
    } yield {
      directory
        .addPermission(PosixFilePermission.OWNER_READ)
        .addPermission(PosixFilePermission.GROUP_READ)
        .addPermission(PosixFilePermission.OTHERS_READ)
        .addPermission(PosixFilePermission.OWNER_EXECUTE)
        .addPermission(PosixFilePermission.GROUP_EXECUTE)
        .addPermission(PosixFilePermission.OTHERS_EXECUTE)
      Process(Seq("git", "clone", gitUrl, directory.pathAsString)).!
      Process(Seq("git", "reset", "--hard", commitUUid), directory.toJava).!
      block(file, directory)
    }).get()

  def withTemporaryGitRepo[T](fn: File => MatchResult[T]): MatchResult[T] = {
    (for {
      temporaryDirectory <- File.temporaryDirectory()
    } yield {
      Process(Seq("git", "init"), temporaryDirectory.toJava).!
      Process(Seq("git", "commit", "--allow-empty", "-m", "initial commit"), temporaryDirectory.toJava).!
      fn(temporaryDirectory)
    }).get

  }
} 
Example 33
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 34
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 35
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 36
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 37
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 38
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 39
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 40
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 41
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 42
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 43
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 44
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 45
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 46
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 47
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 48
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 49
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 50
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 51
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 52
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 53
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 54
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 55
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 56
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 57
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 58
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 59
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 60
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 61
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 62
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 63
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 64
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 65
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 66
Source File: Chat.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.models

import canoe.models.ChatType.ChatType
import io.circe.Decoder
import io.circe.generic.auto._
import io.circe.generic.semiauto.deriveDecoder

sealed trait Chat {
  def id: Long
}

object Chat {

  
  implicit val chatDecoder: Decoder[Chat] = Decoder.instance[Chat] { cursor =>
    cursor
      .get[ChatType]("type")
      .map {
        case ChatType.Private    => deriveDecoder[PrivateChat]
        case ChatType.Group      => deriveDecoder[Group]
        case ChatType.Supergroup => deriveDecoder[Supergroup]
        case ChatType.Channel    => deriveDecoder[Channel]
      }
      .flatMap(_.tryDecode(cursor))
  }
}

final case class PrivateChat(id: Long, username: Option[String], firstName: Option[String], lastName: Option[String])
    extends Chat

final case class Group(id: Long, title: Option[String]) extends Chat

final case class Supergroup(id: Long, title: Option[String], username: Option[String]) extends Chat

final case class Channel(id: Long, title: Option[String], username: Option[String]) extends Chat 
Example 67
Source File: ChatMember.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.models

import canoe.models.MemberStatus.MemberStatus
import io.circe.Decoder
import io.circe.generic.auto._
import io.circe.generic.semiauto.deriveDecoder

sealed trait ChatMember {
  def user: User
}

object ChatMember {

  implicit val chatMemberDecoder: Decoder[ChatMember] = Decoder.instance[ChatMember] { cursor =>
    cursor
      .get[MemberStatus]("status")
      .map {
        case MemberStatus.Creator       => deriveDecoder[ChatCreator]
        case MemberStatus.Administrator => deriveDecoder[ChatAdministrator]
        case MemberStatus.Member        => deriveDecoder[OrdinaryMember]
        case MemberStatus.Restricted    => deriveDecoder[RestrictedMember]
        case MemberStatus.Left          => deriveDecoder[LeftMember]
        case MemberStatus.Kicked        => deriveDecoder[KickedMember]
      }
      .flatMap(_.tryDecode(cursor))
  }
}

final case class ChatCreator(user: User) extends ChatMember

final case class OrdinaryMember(user: User) extends ChatMember

final case class LeftMember(user: User) extends ChatMember

final case class KickedMember(user: User, untilDate: Option[Int]) extends ChatMember

final case class ChatAdministrator(user: User,
                                   customTitle: Option[String],
                                   canBeEdited: Option[Boolean],
                                   canChangeInfo: Option[Boolean],
                                   canPostMessages: Option[Boolean],
                                   canEditMessages: Option[Boolean],
                                   canDeleteMessages: Option[Boolean],
                                   canRestrictMembers: Option[Boolean],
                                   canPromoteMembers: Option[Boolean],
                                   canInviteUsers: Option[Boolean],
                                   canPinMessages: Option[Boolean])
    extends ChatMember

final case class RestrictedMember(user: User,
                                  untilDate: Option[Int],
                                  isMember: Option[Boolean],
                                  canChangeInfo: Option[Boolean],
                                  canInviteUsers: Option[Boolean],
                                  canPinMessages: Option[Boolean],
                                  canSendMessages: Option[Boolean],
                                  canSendMediaMessages: Option[Boolean],
                                  canSendOtherMessages: Option[Boolean],
                                  canAddWebPagePreviews: Option[Boolean])
    extends ChatMember 
Example 68
Source File: UserMessage.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.models.messages

import canoe.models.{Chat, User}
import cats.syntax.functor._
import io.circe.Decoder
import io.circe.generic.auto._
import io.circe.generic.semiauto.deriveDecoder

trait UserMessage extends TelegramMessage {

  def from: Option[User]

  def forwardFrom: Option[User]

  def forwardFromChat: Option[Chat]

  def forwardFromMessageId: Option[Int]

  def forwardSignature: Option[String]

  def forwardSenderName: Option[String]

  def forwardDate: Option[Int]

  def replyToMessage: Option[TelegramMessage]

  def editDate: Option[Int]

  def authorSignature: Option[String]
}

object UserMessage {

  implicit val userMessageDecoder: Decoder[UserMessage] =
    List[Decoder[UserMessage]](
      deriveDecoder[AnimationMessage].widen,
      deriveDecoder[AudioMessage].widen,
      deriveDecoder[ContactMessage].widen,
      deriveDecoder[DocumentMessage].widen,
      deriveDecoder[GameMessage].widen,
      deriveDecoder[InvoiceMessage].widen,
      deriveDecoder[LocationMessage].widen,
      deriveDecoder[PhotoMessage].widen,
      deriveDecoder[PollMessage].widen,
      deriveDecoder[StickerMessage].widen,
      deriveDecoder[TextMessage].widen,
      deriveDecoder[VenueMessage].widen,
      deriveDecoder[VideoMessage].widen,
      deriveDecoder[VideoNoteMessage].widen,
      deriveDecoder[VoiceMessage].widen
    ).reduceLeft(_.or(_))
} 
Example 69
Source File: TelegramMessage.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.models.messages

import canoe.models.Chat
import cats.syntax.functor._
import io.circe.Decoder

trait TelegramMessage {
  def messageId: Int
  def chat: Chat
  def date: Int
}

object TelegramMessage {

  implicit val telegramMessageDecoder: Decoder[TelegramMessage] =
    List[Decoder[TelegramMessage]](
      UserMessage.userMessageDecoder.widen,
      SystemMessage.systemMessageDecoder.widen
    ).reduceLeft(_.or(_))
} 
Example 70
Source File: SystemMessage.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.models.messages

import canoe.models.{Chat, DiceResult, PhotoSize, SuccessfulPayment, User}
import cats.syntax.functor._
import io.circe.Decoder
import io.circe.generic.auto._
import io.circe.generic.semiauto.deriveDecoder

sealed trait SystemMessage extends TelegramMessage with Product

object SystemMessage {

  implicit val systemMessageDecoder: Decoder[SystemMessage] =
    List[Decoder[SystemMessage]](
      deriveDecoder[MessagePinned].widen,
      deriveDecoder[ChatMemberAdded].widen,
      deriveDecoder[ChannelCreated].widen,
      deriveDecoder[ChatMemberLeft].widen,
      deriveDecoder[ChatPhotoChanged].widen,
      deriveDecoder[ChatPhotoDeleted].widen,
      deriveDecoder[ChatTitleChanged].widen,
      deriveDecoder[MigratedFromGroup].widen,
      deriveDecoder[MigratedToSupergroup].widen,
      deriveDecoder[SuccessfulPaymentMessage].widen,
      deriveDecoder[GroupChatCreated].widen,
      deriveDecoder[SupergroupCreated].widen,
      deriveDecoder[WebsiteConnected].widen,
      deriveDecoder[DiceThrownMessage].widen
    ).reduceLeft(_.or(_))
}

final case class MessagePinned(messageId: Int, chat: Chat, date: Int, pinnedMessage: TelegramMessage) extends SystemMessage

final case class ChannelCreated(messageId: Int, chat: Chat, date: Int, channelChatCreated: Boolean)
    extends SystemMessage

final case class ChatMemberAdded(messageId: Int, chat: Chat, date: Int, newChatMembers: Seq[User]) extends SystemMessage

final case class ChatMemberLeft(messageId: Int, chat: Chat, date: Int, leftChatMember: User) extends SystemMessage

final case class ChatPhotoChanged(messageId: Int, chat: Chat, date: Int, newChatPhoto: Seq[PhotoSize])
    extends SystemMessage

final case class ChatPhotoDeleted(messageId: Int, chat: Chat, date: Int, deleteChatPhoto: Boolean) extends SystemMessage

final case class ChatTitleChanged(messageId: Int, chat: Chat, date: Int, newChatTitle: String) extends SystemMessage

final case class MigratedFromGroup(messageId: Int, chat: Chat, date: Int, migrateFromChatId: Long) extends SystemMessage

final case class MigratedToSupergroup(messageId: Int, chat: Chat, date: Int, migrateToChatId: Long)
    extends SystemMessage

final case class GroupChatCreated(messageId: Int, chat: Chat, date: Int, groupChatCreated: Boolean)
    extends SystemMessage

final case class SupergroupCreated(messageId: Int, chat: Chat, date: Int, supergroupChatCreated: Boolean)
    extends SystemMessage

final case class SuccessfulPaymentMessage(messageId: Int, chat: Chat, date: Int, successfulPayment: SuccessfulPayment)
    extends SystemMessage

final case class WebsiteConnected(messageId: Int, chat: Chat, date: Int, connectedWebsite: String) extends SystemMessage

final case class DiceThrownMessage(messageId: Int, chat: Chat, date: Int, dice: DiceResult) extends SystemMessage 
Example 71
Source File: Update.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.models

import canoe.marshalling.codecs._
import canoe.models.messages.TelegramMessage
import cats.syntax.functor._
import io.circe.Decoder
import io.circe.generic.auto._
import io.circe.generic.semiauto.deriveDecoder

sealed trait Update {
  def updateId: Long
}

object Update {

  final case class Unknown(updateId: Long) extends Update

  implicit val updateDecoder: Decoder[Update] =
    List[Decoder[Update]](
      deriveDecoder[MessageReceived].widen,
      deriveDecoder[MessageEdited].widen,
      deriveDecoder[ChannelPost].widen,
      deriveDecoder[ChannelPostEdited].widen,
      deriveDecoder[PollUpdated].widen,
      deriveDecoder[InlineQueryReceived].widen,
      deriveDecoder[InlineResultSelected].widen,
      deriveDecoder[CallbackButtonSelected].widen,
      deriveDecoder[ShippingQueryReceived].widen,
      deriveDecoder[PreCheckoutQueryReceived].widen,
      deriveDecoder[PollAnswerReceived].widen,
      deriveDecoder[Unknown].widen
    ).reduceLeft(_.or(_)).camelCase
}


final case class PollUpdated(updateId: Long, poll: Poll) extends Update 
Example 72
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 73
Source File: AjaxClient.scala    From canoe   with MIT License 5 votes vote down vote up
package canoe.api.clients

import canoe.api.{FailedMethod, ResponseDecodingError, TelegramClient}
import canoe.methods.Method
import canoe.models.Response
import cats.effect.{Async, ContextShift}
import cats.syntax.all._
import io.circe.Decoder
import io.circe.parser.decode
import org.scalajs.dom.console
import org.scalajs.dom.ext.Ajax

private[api] class AjaxClient[F[_]: Async: ContextShift](token: String) extends TelegramClient[F] {

  private val botApiUri: String = s"https://api.telegram.org/bot$token"

  
  def execute[Req, Res](request: Req)(implicit M: Method[Req, Res]): F[Res] = {
    implicit val responseDecoder: Decoder[Response[Res]] = Response.decoder[Res](M.decoder)

    sendJsonRequest(request, M).map(decode[Response[Res]]).flatMap {
      case Left(error)     => handleUnknownEntity(M.name, request, error.getMessage)
      case Right(response) => handleTelegramResponse(M, request)(response)
    }
  }

  private def handleUnknownEntity[I, A](method: String, input: I, error: String): F[A] = {
    console.error(
      s"Received unknown Telegram entity during execution of '$method' method. \nInput data: $input. \n${error}"
    )
    ResponseDecodingError(error.toString).raiseError[F, A]
  }

  private def handleTelegramResponse[A, I, C](m: Method[I, A], input: I)(response: Response[A]): F[A] =
    response match {
      case Response(true, Some(result), _, _, _) => result.pure[F]

      case failed =>
        console.error(s"Received failed response from Telegram: $failed. Method name: ${m.name}, input data: $input")
        FailedMethod(m, input, failed).raiseError[F, A]
    }

  private def sendJsonRequest[Req, Res](request: Req, method: Method[Req, Res]): F[String] = {
    val url = s"$botApiUri/${method.name}"
    val json = method.encoder.apply(request).toString

    Async
      .fromFuture(F.delay(Ajax.post(url, json, headers = Map("Content-Type" -> "application/json"))))
      .map(_.responseText)
  }
} 
Example 74
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 75
Source File: JsonToCsv.scala    From temperature-machine   with Apache License 2.0 5 votes vote down vote up
package bad.robot.temperature

import java.lang.Math.abs
import java.time.Instant
import java.time.ZoneId._
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle._
import java.util.Locale

import io.circe.Decoder

import scalaz.\/

object JsonToCsv {

  type Row = (String, Instant, Double)
 
  val DefaultTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(SHORT).withLocale(Locale.getDefault).withZone(systemDefault())
  
  def convert(json: => Error \/ String, formatter: DateTimeFormatter): Error \/ String = {
    for {
      string <- json
      series <- decodeAsDisjunction[List[Series]](string)
    } yield {
      toCsv(series, formatter)
    }
  }
  
  private def toCsv(series: List[Series], formatter: DateTimeFormatter) = {
    val quote = "\""
    
    def toRows: List[Row] = for {
      reading     <- series
      measurement <- reading.data 
    } yield {
      (reading.label, measurement.time, measurement.temperature.celsius)
    }

    def toCsv(rows: List[Row]): List[String] = {
      val enquote: String => String = value => s"$quote$value$quote"
      val heading = List(
        enquote("Sensor"), 
        enquote("Time"), 
        enquote("Temperature"),
        enquote("Difference")
      ).mkString(",")
      
      if (rows.isEmpty)
        return Nil
      
      val tuples = rows.map(x => (x._1, x._2, x._3, "0"))
      val rowsWithPercentageDifference = tuples.drop(1).scan(tuples.head) {
        case (previous, current) => (current._1, current._2, current._3, f"${abs(current._3 - previous._3)}%.2f")
      }
      
      heading :: rowsWithPercentageDifference.map(row => List(
        enquote(row._1),
        enquote(formatter.format(row._2)),
        enquote(row._3.toString),
        enquote(row._4.toString)
      ).mkString(","))
    }
    
    toCsv(toRows).mkString(sys.props("line.separator"))
  }
}

object Series {
  import io.circe.generic.semiauto._

  implicit val dataCodec: Decoder[Series] = deriveDecoder[Series]
}
case class Series(label: String, data: List[Data])

object Data {
  import io.circe.generic.semiauto._

  implicit val seriesCodec: Decoder[Data] = deriveDecoder[Data]
}
case class Data(x: Long, y: String) {
  def time: Instant = Instant.ofEpochMilli(x)
  def temperature: Temperature = Temperature(y.toDouble)
} 
Example 76
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 77
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 78
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 79
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 80
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 81
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 82
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 83
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 84
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 85
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 86
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 87
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 88
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 89
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 90
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 91
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 92
Source File: GroupMigrations.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.update

import cats.implicits._
import io.circe.Decoder
import io.circe.config.parser
import io.circe.generic.extras.{semiauto, Configuration}
import org.scalasteward.core.application.Config
import org.scalasteward.core.data._
import org.scalasteward.core.io.FileAlg
import org.scalasteward.core.util.{MonadThrowable, Nel}

trait GroupMigrations {
  def findUpdateWithNewerGroupId(dependency: Dependency): Option[Update.Single]
}

object GroupMigrations {
  def create[F[_]: MonadThrowable](implicit
      fileAlg: FileAlg[F],
      config: Config
  ): F[GroupMigrations] = {
    val migrationSources = {

      val fromParameters: F[Option[String]] =
        config.groupMigrations.traverse(fileAlg.readFile(_)).flatMap {
          case None => none[String].pure[F]
          case Some(None) =>
            new Throwable("Couldn't read the file with custom group migrations")
              .raiseError[F, Option[String]]
          case Some(Some(text)) => text.some.pure[F]
        }

      List(
        fileAlg.readResource("group-migrations.conf").map(List(_)),
        fromParameters.map(_.toList)
      ).flatSequence
    }

    val decodeFile: String => F[GroupIdChanges] = parser
      .decode[GroupIdChanges](_)
      .leftMap(e => new Throwable("Couldn't decode migrations file", e))
      .liftTo[F]

    migrationSources
      .flatMap(_.traverse(decodeFile))
      .map(_.flatMap(_.changes))
      .map(migrations => dependency => migrateGroupId(dependency, migrations))
  }

  def migrateGroupId(
      dependency: Dependency,
      migrations: List[GroupIdChange]
  ): Option[Update.Single] =
    migrations.view
      .filter(_.before === dependency.groupId)
      .find(_.artifactId === dependency.artifactId.name)
      .map { migration =>
        Update.Single(
          CrossDependency(dependency),
          Nel.one(migration.initialVersion),
          Some(migration.after)
        )
      }

  implicit val customConfig: Configuration =
    Configuration.default.withDefaults

  final case class GroupIdChanges(changes: List[GroupIdChange])
  object GroupIdChanges {
    implicit val decoder: Decoder[GroupIdChanges] =
      semiauto.deriveConfiguredDecoder
  }

  final case class GroupIdChange(
      before: GroupId,
      after: GroupId,
      artifactId: String,
      initialVersion: String
  )

  object GroupIdChange {

    implicit val decoder: Decoder[GroupIdChange] =
      semiauto.deriveConfiguredDecoder
  }
} 
Example 93
Source File: PullRequestOut.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.vcs.data

import cats.implicits._
import io.circe.Decoder
import io.circe.generic.semiauto._
import org.http4s.Uri
import org.scalasteward.core.util.uri.uriDecoder
import org.scalasteward.core.vcs.data.PullRequestState.Closed

final case class PullRequestOut(
    html_url: Uri,
    state: PullRequestState,
    title: String
) {
  def isClosed: Boolean =
    state === Closed
}

object PullRequestOut {
  implicit val pullRequestOutDecoder: Decoder[PullRequestOut] =
    deriveDecoder

  // prevent IntelliJ from removing the import of uriDecoder
  locally(uriDecoder)
} 
Example 94
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 95
Source File: RepoOut.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.vcs.data

import io.circe.Decoder
import io.circe.generic.semiauto._
import org.http4s.Uri
import org.scalasteward.core.git.Branch
import org.scalasteward.core.util.ApplicativeThrowable
import org.scalasteward.core.util.uri.uriDecoder

final case class RepoOut(
    name: String,
    owner: UserOut,
    parent: Option[RepoOut],
    clone_url: Uri,
    default_branch: Branch
) {
  def parentOrRaise[F[_]](implicit F: ApplicativeThrowable[F]): F[RepoOut] =
    parent.fold(F.raiseError[RepoOut](new Throwable(s"repo $name has no parent")))(F.pure)

  def repo: Repo =
    Repo(owner.login, name)
}

object RepoOut {
  implicit val repoOutDecoder: Decoder[RepoOut] =
    deriveDecoder

  // prevent IntelliJ from removing the import of uriDecoder
  locally(uriDecoder)
} 
Example 96
Source File: RepositoryResponse.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.bitbucket.http4s

import cats.implicits._
import io.circe.{ACursor, Decoder, DecodingFailure, Json}
import org.http4s.Uri
import org.scalasteward.core.git.Branch
import org.scalasteward.core.util.uri._
import org.scalasteward.core.vcs.data.{Repo, UserOut}
import scala.annotation.tailrec

final private[http4s] case class RepositoryResponse(
    name: String,
    mainBranch: Branch,
    owner: UserOut,
    httpsCloneUrl: Uri,
    parent: Option[Repo]
)

private[http4s] object RepositoryResponse {
  implicit private val repoDecoder: Decoder[Repo] = Decoder.instance { c =>
    c.as[String].map(_.split('/')).flatMap { parts =>
      parts match {
        case Array(owner, name) => Repo(owner, name).asRight
        case _                  => DecodingFailure("Repo", c.history).asLeft
      }
    }
  }

  implicit val decoder: Decoder[RepositoryResponse] = Decoder.instance { c =>
    for {
      name <- c.downField("name").as[String]
      owner <-
        c.downField("owner")
          .downField("username")
          .as[String]
          .orElse(c.downField("owner").downField("nickname").as[String])
      cloneUrl <-
        c.downField("links")
          .downField("clone")
          .downAt { p =>
            p.asObject
              .flatMap(o => o("name"))
              .flatMap(_.asString)
              .contains("https")
          }
          .downField("href")
          .as[Uri]
      defaultBranch <- c.downField("mainbranch").downField("name").as[Branch]
      maybeParent <- c.downField("parent").downField("full_name").as[Option[Repo]]
    } yield RepositoryResponse(name, defaultBranch, UserOut(owner), cloneUrl, maybeParent)
  }

  
    def downAt(p: Json => Boolean): ACursor = {
      @tailrec
      def find(c: ACursor): ACursor =
        if (c.succeeded)
          if (c.focus.exists(p)) c else find(c.right)
        else c

      find(cursor.downArray)
    }
  }
} 
Example 97
Source File: json.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.bitbucket.http4s

import io.circe.Decoder
import org.http4s.Uri
import org.scalasteward.core.git.{Branch, Sha1}
import org.scalasteward.core.util.uri.uriDecoder
import org.scalasteward.core.vcs.data.{BranchOut, CommitOut, PullRequestOut, PullRequestState}

private[http4s] object json {
  implicit val branchOutDecoder: Decoder[BranchOut] = Decoder.instance { c =>
    for {
      branch <- c.downField("name").as[Branch]
      commitHash <- c.downField("target").downField("hash").as[Sha1]
    } yield BranchOut(branch, CommitOut(commitHash))
  }

  implicit val pullRequestStateDecoder: Decoder[PullRequestState] =
    Decoder[String].emap {
      case "OPEN"                               => Right(PullRequestState.Open)
      case "MERGED" | "SUPERSEDED" | "DECLINED" => Right(PullRequestState.Closed)
      case unknown                              => Left(s"Unexpected string '$unknown'")
    }

  implicit val pullRequestOutDecoder: Decoder[PullRequestOut] = Decoder.instance { c =>
    for {
      title <- c.downField("title").as[String]
      state <- c.downField("state").as[PullRequestState]
      html_url <- c.downField("links").downField("self").downField("href").as[Uri]
    } yield (PullRequestOut(html_url, state, title))
  }
} 
Example 98
Source File: uri.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.util

import cats.implicits._
import io.circe.{Decoder, KeyDecoder, KeyEncoder}
import monocle.Optional
import org.http4s.Uri
import org.http4s.Uri.{Authority, UserInfo}

object uri {
  implicit val uriDecoder: Decoder[Uri] =
    Decoder[String].emap(s => Uri.fromString(s).leftMap(_.getMessage))

  implicit val uriKeyDecoder: KeyDecoder[Uri] =
    KeyDecoder.instance(Uri.fromString(_).toOption)

  implicit val uriKeyEncoder: KeyEncoder[Uri] =
    KeyEncoder.instance(_.renderString)

  val withAuthority: Optional[Uri, Authority] =
    Optional[Uri, Authority](_.authority)(authority => _.copy(authority = Some(authority)))

  val authorityWithUserInfo: Optional[Authority, UserInfo] =
    Optional[Authority, UserInfo](_.userInfo)(userInfo => _.copy(userInfo = Some(userInfo)))

  val withUserInfo: Optional[Uri, UserInfo] =
    authorityWithUserInfo.compose(withAuthority)
} 
Example 99
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 100
Source File: parser.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.buildtool.sbt

import cats.implicits._
import io.circe.Decoder
import io.circe.parser._
import org.scalasteward.core.buildtool.sbt.data.SbtVersion
import org.scalasteward.core.data._

object parser {
  def parseBuildProperties(s: String): Option[SbtVersion] =
    """sbt.version\s*=\s*(.+)""".r.findFirstMatchIn(s).map(_.group(1)).map(SbtVersion.apply)

  
  def parseDependencies(lines: List[String]): List[Scope.Dependencies] = {
    val chunks = fs2.Stream.emits(lines).map(removeSbtNoise).split(_ === "--- snip ---")
    val decoder = Decoder[Dependency].either(Decoder[Resolver])
    chunks.mapFilter { chunk =>
      val (dependencies, resolvers) = chunk.toList.flatMap(decode(_)(decoder).toList).separate
      if (dependencies.isEmpty || resolvers.isEmpty) None
      else Some(Scope(dependencies, resolvers.sorted))
    }.toList
  }

  private def removeSbtNoise(s: String): String =
    s.replace("[info]", "").trim
} 
Example 101
Source File: parser.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.buildtool.mill

import cats.implicits._
import io.circe.{Decoder, DecodingFailure}
import org.scalasteward.core.data.{ArtifactId, Dependency, GroupId, Resolver}

object parser {
  sealed trait ParseError extends RuntimeException {
    def message: String

    final override def getMessage: String = message
  }
  case class CirceParseError(message: String, cause: io.circe.Error) extends ParseError {
    final override def getCause: Throwable = cause
  }

  def parseModules[F[_]](
      input: String
  ): Either[ParseError, List[MillModule]] =
    for {
      json <-
        io.circe.parser
          .decode[Modules](input)
          .leftMap(CirceParseError("Failed to decode Modules", _): ParseError)
    } yield json.modules

}

case class Modules(modules: List[MillModule])
object Modules {
  implicit val decoder: Decoder[Modules] = Decoder.forProduct1("modules")(apply)
}

case class MillModule(name: String, repositories: List[Resolver], dependencies: List[Dependency])

object MillModule {
  val resolverDecoder: Decoder[Resolver] = Decoder.instance { c =>
    c.downField("type").as[String].flatMap {
      case "maven" =>
        for {
          url <- c.downField("url").as[String]
          creds <- c.downField("auth").as[Option[Resolver.Credentials]]
        } yield Resolver.MavenRepository(url, url, creds)
      case "ivy" =>
        for {
          url <- c.downField("pattern").as[String]
          creds <- c.downField("auth").as[Option[Resolver.Credentials]]
        } yield Resolver.IvyRepository(url, url, creds)
      case typ => Left(DecodingFailure(s"Not a matching resolver type, $typ", c.history))
    }
  }

  val dependencyDecoder: Decoder[Dependency] = Decoder.instance { c =>
    for {
      groupId <- c.downField("groupId").as[GroupId]
      artifactId <- c.downField("artifactId").as[String].map(aid => ArtifactId(aid, None))
      version <- c.downField("version").as[String]
    } yield Dependency(groupId, artifactId, version)
  }

  implicit val decoder: Decoder[MillModule] = Decoder.instance(c =>
    for {
      name <- c.downField("name").as[String]
      resolvers <- c.downField("repositories").as(Decoder.decodeList(resolverDecoder))
      dependencies <- c.downField("dependencies").as(Decoder.decodeList(dependencyDecoder))
    } yield MillModule(name, resolvers, dependencies)
  )
} 
Example 102
Source File: Migration.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.scalafix

import io.circe.Decoder
import io.circe.generic.semiauto._
import org.scalasteward.core.data.{GroupId, Version}
import org.scalasteward.core.util.Nel

final case class Migration(
    groupId: GroupId,
    artifactIds: Nel[String],
    newVersion: Version,
    rewriteRules: Nel[String],
    doc: Option[String]
)

object Migration {
  implicit val migrationDecoder: Decoder[Migration] =
    deriveDecoder[Migration]
} 
Example 103
Source File: ScalafixMigrations.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.scalafix

import io.circe.Decoder
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto._

final case class ScalafixMigrations(
    disableDefaults: Boolean = false,
    migrations: List[Migration] = List.empty
)

object ScalafixMigrations {
  implicit val configuration: Configuration =
    Configuration.default.withDefaults

  implicit val scalafixMigrationsDecoder: Decoder[ScalafixMigrations] =
    deriveConfiguredDecoder
} 
Example 104
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 105
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 106
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 107
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 108
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 109
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 110
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 111
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 112
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 113
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 114
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 115
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 116
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 117
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 118
Source File: JobTask.scala    From docspell   with GNU General Public License v3.0 5 votes vote down vote up
package docspell.joex.scheduler

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

import docspell.common.Ident
import docspell.common.syntax.all._

import io.circe.Decoder


case class JobTask[F[_]](
    name: Ident,
    task: Task[F, String, Unit],
    onCancel: Task[F, String, Unit]
)

object JobTask {

  def json[F[_]: Sync, A](
      name: Ident,
      task: Task[F, A, Unit],
      onCancel: Task[F, A, Unit]
  )(implicit
      D: Decoder[A]
  ): JobTask[F] = {
    val convert: String => F[A] =
      str =>
        str.parseJsonAs[A] match {
          case Right(a) => a.pure[F]
          case Left(ex) =>
            Sync[F].raiseError(new Exception(s"Cannot parse task arguments: $str", ex))
        }

    JobTask(name, task.contramap(convert), onCancel.contramap(convert))
  }
} 
Example 119
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 120
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 121
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 122
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 123
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 124
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 125
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 126
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 127
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 128
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 129
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 130
Source File: SearchFilters.scala    From franklin   with Apache License 2.0 5 votes vote down vote up
package com.azavea.franklin.database

import cats.implicits._
import com.azavea.franklin.api.schemas.bboxToString
import com.azavea.franklin.datamodel.{PaginationToken, Query}
import com.azavea.stac4s.{Bbox, TemporalExtent}
import eu.timepit.refined.types.numeric.NonNegInt
import geotrellis.vector.Geometry
import geotrellis.vector.{io => _, _}
import io.circe.generic.semiauto._
import io.circe.refined._
import io.circe.{Decoder, HCursor}

import java.net.URLEncoder
import java.nio.charset.StandardCharsets

final case class SearchFilters(
    bbox: Option[Bbox],
    datetime: Option[TemporalExtent],
    intersects: Option[Geometry],
    collections: List[String],
    items: List[String],
    limit: Option[NonNegInt],
    query: Map[String, List[Query]],
    next: Option[PaginationToken]
) {

  def asQueryParameters: String = {

    val bboxQP =
      bbox map { box => s"bbox=${bboxToString(box)}" }
    val datetimeQP =
      datetime map { tempExtent =>
        s"datetime=${SearchFilters.encodeString(temporalExtentToString(tempExtent))}"
      }
    val collectionsQP = collections.toNel map { _ =>
      s"""collections=${SearchFilters.encodeString(collections.mkString(","))}"""
    }
    val itemsQP = items.toNel map { _ =>
      s"""ids=${SearchFilters.encodeString(items.mkString(","))}"""
    }

    List(bboxQP, datetimeQP, collectionsQP, itemsQP).flatten.mkString("&")
  }

}

object SearchFilters {

  def encodeString(s: String): String = URLEncoder.encode(s, StandardCharsets.UTF_8.toString)

  implicit val searchFilterDecoder = new Decoder[SearchFilters] {

    final def apply(c: HCursor): Decoder.Result[SearchFilters] =
      for {
        bbox              <- c.downField("bbox").as[Option[Bbox]]
        datetime          <- c.downField("datetime").as[Option[TemporalExtent]]
        intersects        <- c.downField("intersects").as[Option[Geometry]]
        collectionsOption <- c.downField("collections").as[Option[List[String]]]
        itemsOption       <- c.downField("items").as[Option[List[String]]]
        limit             <- c.downField("limit").as[Option[NonNegInt]]
        query             <- c.get[Option[Map[String, List[Query]]]]("query")
        paginationToken   <- c.get[Option[PaginationToken]]("next")
      } yield {
        SearchFilters(
          bbox,
          datetime,
          intersects,
          collectionsOption.getOrElse(List.empty),
          itemsOption.getOrElse(List.empty),
          limit,
          query getOrElse Map.empty,
          paginationToken
        )
      }
  }
  implicit val searchFilterEncoder = deriveEncoder[SearchFilters]
} 
Example 131
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 132
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 133
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 134
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 135
Source File: CirceYaml.scala    From bazel-deps   with MIT License 5 votes vote down vote up
package com.github.johnynek.bazel_deps

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import io.circe.jackson.CirceJsonModule
import io.circe.{Decoder, Json, ParsingFailure, Parser}
import scala.util.control.NonFatal


object Yaml extends Parser {
  private[this] val mapper = new ObjectMapper(new YAMLFactory()).registerModule(CirceJsonModule)
  private[this] val factory = mapper.getFactory
  override def parse(input: String): Either[ParsingFailure, Json] =
    try {
      Right(mapper.readValue(factory.createParser(input), classOf[Json]))
    } catch {
      case NonFatal(error) => Left(ParsingFailure(error.getMessage, error))
    }
} 
Example 136
Source File: StringUnmarshaller.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.admin.directives

import akka.http.scaladsl.unmarshalling.{FromStringUnmarshaller, Unmarshaller}
import ch.epfl.bluebrain.nexus.admin.exceptions.AdminError.InvalidFormat
import com.typesafe.scalalogging.Logger
import io.circe.parser._
import io.circe.{Decoder, Json}

object StringUnmarshaller {

  private val logger = Logger[this.type]

  
  def unmarshallJson[A: Decoder]: FromStringUnmarshaller[A] =
    unmarshaller { value =>
      parse(value).left.map { err =>
        logger.warn(s"Failed to convert string '$value' to Json", err)
        InvalidFormat
      }
    }

  private def unmarshaller[A](
      f: String => Either[Throwable, Json]
  )(implicit dec: Decoder[A]): FromStringUnmarshaller[A] =
    Unmarshaller.strict[String, A] {
      case ""     => throw Unmarshaller.NoContentException
      case string =>
        f(string).flatMap(_.as[A]) match {
          case Right(value) => value
          case Left(err)    => throw new IllegalArgumentException(err)
        }
    }

} 
Example 137
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 138
Source File: ProjectDescription.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.admin.projects

import ch.epfl.bluebrain.nexus.rdf.Iri
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import io.circe.{Decoder, DecodingFailure}


  def vocabOrGenerated(organization: String, label: String)(implicit http: HttpConfig): Option[AbsoluteIri] =
    vocab orElse Iri.absolute(s"${http.prefixIri.asString}/vocabs/$organization/$label/").toOption
}

object ProjectDescription {

  final case class Mapping(prefix: String, namespace: AbsoluteIri)

  implicit val mappingDecoder: Decoder[Mapping] = Decoder.instance { hc =>
    for {
      prefix    <- hc.downField("prefix").as[String]
      namespace <- hc.downField("namespace").as[String]
      iri       <- Iri.absolute(namespace).left.map(err => DecodingFailure(err, hc.history))
    } yield Mapping(prefix, iri)
  }

  implicit val descriptionDecoder: Decoder[ProjectDescription] = Decoder.instance { hc =>
    for {
      desc <- hc.downField("description").as[Option[String]]
      lam   = hc.downField("apiMappings").as[List[Mapping]].getOrElse(List.empty)
      map   = lam.map(am => am.prefix -> am.namespace).toMap
      base <- hc.downField("base").as[Option[AbsoluteIri]]
      voc  <- hc.downField("vocab").as[Option[AbsoluteIri]]
    } yield ProjectDescription(desc, map, base, voc)
  }
} 
Example 139
Source File: ElasticSearchDecoder.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.commons.es.client

import cats.implicits._
import ch.epfl.bluebrain.nexus.commons.search.QueryResult.{ScoredQueryResult, UnscoredQueryResult}
import ch.epfl.bluebrain.nexus.commons.search.{QueryResult, QueryResults}
import ch.epfl.bluebrain.nexus.commons.search.QueryResults.{ScoredQueryResults, UnscoredQueryResults}
import io.circe.{Decoder, Json}

class ElasticSearchDecoder[A](implicit D: Decoder[A]) {

  private type ErrorOrResults = Either[Json, List[QueryResult[A]]]

  private def queryResults(json: Json, scored: Boolean): ErrorOrResults = {
    def queryResult(result: Json): Option[QueryResult[A]] = {
      result.hcursor.get[A]("_source") match {
        case Right(s) if scored => Some(ScoredQueryResult(result.hcursor.get[Float]("_score").getOrElse(0f), s))
        case Right(s)           => Some(UnscoredQueryResult(s))
        case _                  => None
      }
    }
    val hitsList = json.hcursor.downField("hits").downField("hits").focus.flatMap(_.asArray).getOrElse(Vector.empty)
    hitsList
      .foldM(List.empty[QueryResult[A]])((acc, json) => queryResult(json).map(_ :: acc).toRight(json))
      .map(_.reverse)
  }

  private def token(json: Json): Option[String] = {
    val hits   = json.hcursor.downField("hits").downField("hits")
    val length = hits.values.fold(1)(_.size)
    hits.downN(length - 1).downField("sort").focus.map(_.noSpaces)
  }

  private def decodeScoredQueryResults(maxScore: Float): Decoder[QueryResults[A]] =
    Decoder.decodeJson.emap { json =>
      queryResults(json, scored = true) match {
        case Right(list)   => Right(ScoredQueryResults(fetchTotal(json), maxScore, list, token(json)))
        // $COVERAGE-OFF$
        case Left(errJson) => Left(s"Could not decode source from value '$errJson'")
        // $COVERAGE-ON$
      }
    }

  private val decodeUnscoredResults: Decoder[QueryResults[A]] =
    Decoder.decodeJson.emap { json =>
      queryResults(json, scored = false) match {
        case Right(list)   => Right(UnscoredQueryResults(fetchTotal(json), list, token(json)))
        // $COVERAGE-OFF$
        case Left(errJson) => Left(s"Could not decode source from value '$errJson'")
        // $COVERAGE-ON$
      }
    }

  private def fetchTotal(json: Json): Long =
    json.hcursor.downField("hits").downField("total").get[Long]("value").getOrElse(0L)

  val decodeQueryResults: Decoder[QueryResults[A]] =
    Decoder.decodeJson.flatMap(
      _.hcursor.downField("hits").get[Float]("max_score").toOption.filterNot(f => f.isInfinite || f.isNaN) match {
        case Some(maxScore) => decodeScoredQueryResults(maxScore)
        case None           => decodeUnscoredResults
      }
    )
}

object ElasticSearchDecoder {

  
  final def apply[A](implicit D: Decoder[A]): Decoder[QueryResults[A]] =
    new ElasticSearchDecoder[A].decodeQueryResults
} 
Example 140
Source File: EventSource.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.client

import java.util.UUID

import akka.NotUsed
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.headers.OAuth2BearerToken
import akka.http.scaladsl.model.{HttpRequest, HttpResponse}
import akka.persistence.query.{NoOffset, Offset, Sequence, TimeBasedUUID}
import akka.stream.Materializer
import akka.stream.alpakka.sse.scaladsl.{EventSource => SSESource}
import akka.stream.scaladsl.Source
import ch.epfl.bluebrain.nexus.iam.auth.AccessToken
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import com.typesafe.scalalogging.Logger
import io.circe.Decoder
import io.circe.parser.decode

import scala.concurrent.{ExecutionContext, Future}
import scala.util.Try

trait EventSource[A] {

  
  def apply[A: Decoder](
      config: KgClientConfig
  )(implicit as: ActorSystem, mt: Materializer, ec: ExecutionContext): EventSource[A] =
    new EventSource[A] {
      private val logger = Logger[this.type]
      private val http   = Http()

      private def addCredentials(request: HttpRequest)(implicit cred: Option[AccessToken]): HttpRequest =
        cred.map(token => request.addCredentials(OAuth2BearerToken(token.value))).getOrElse(request)

      private def send(request: HttpRequest)(implicit cred: Option[AccessToken]): Future[HttpResponse] =
        http.singleRequest(addCredentials(request)).map { resp =>
          if (!resp.status.isSuccess())
            logger.warn(s"HTTP response when performing SSE request: status = '${resp.status}'")
          resp
        }

      private def toOffset(id: String): Offset =
        Try(TimeBasedUUID(UUID.fromString(id))).orElse(Try(Sequence(id.toLong))).getOrElse(NoOffset)

      override def apply(iri: AbsoluteIri, offset: Option[String])(implicit
          cred: Option[AccessToken]
      ): Source[(Offset, A), NotUsed] =
        SSESource(iri.asAkka, send, offset, config.sseRetryDelay).flatMapConcat { sse =>
          val offset = sse.id.map(toOffset).getOrElse(NoOffset)
          decode[A](sse.data) match {
            case Right(ev) => Source.single(offset -> ev)
            case Left(err) =>
              logger.error(s"Failed to decode admin event '$sse'", err)
              Source.empty
          }
        }
    }
} 
Example 141
Source File: PermissionsRoutes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.routes

import akka.http.javadsl.server.Rejections._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.permissions.Permissions
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions
import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions.{Append, Replace, Subtract}
import ch.epfl.bluebrain.nexus.iam.types.Permission
import ch.epfl.bluebrain.nexus.iam.types.ResourceF._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives
import ch.epfl.bluebrain.nexus.service.marshallers.instances._
import io.circe.{Decoder, DecodingFailure}
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global


class PermissionsRoutes(permissions: Permissions[Task], acls: Acls[Task], realms: Realms[Task])(implicit
    http: HttpConfig
) extends AuthDirectives(acls, realms) {

  def routes: Route =
    (pathPrefix("permissions") & pathEndOrSingleSlash) {
      operationName(s"/${http.prefix}/permissions") {
        extractCaller { implicit caller =>
          concat(
            get {
              parameter("rev".as[Long].?) {
                case Some(rev) => complete(permissions.fetchAt(rev).runNotFound)
                case None      => complete(permissions.fetch.runToFuture)
              }
            },
            (put & parameter("rev" ? 0L)) { rev =>
              entity(as[PatchPermissions]) {
                case Replace(set) =>
                  complete(permissions.replace(set, rev).runToFuture)
                case _            => reject(validationRejection("Only @type 'Replace' is permitted when using 'put'."))
              }
            },
            delete {
              parameter("rev".as[Long]) { rev => complete(permissions.delete(rev).runToFuture) }
            },
            (patch & parameter("rev" ? 0L)) { rev =>
              entity(as[PatchPermissions]) {
                case Append(set)   =>
                  complete(permissions.append(set, rev).runToFuture)
                case Subtract(set) =>
                  complete(permissions.subtract(set, rev).runToFuture)
                case _             =>
                  reject(validationRejection("Only @type 'Append' or 'Subtract' is permitted when using 'patch'."))
              }
            }
          )
        }
      }
    }
}

object PermissionsRoutes {

  sealed private[routes] trait PatchPermissions extends Product with Serializable

  private[routes] object PatchPermissions {

    final case class Append(permissions: Set[Permission])   extends PatchPermissions
    final case class Subtract(permissions: Set[Permission]) extends PatchPermissions
    final case class Replace(permissions: Set[Permission])  extends PatchPermissions

    implicit val patchPermissionsDecoder: Decoder[PatchPermissions] =
      Decoder.instance { hc =>
        for {
          permissions <- hc.get[Set[Permission]]("permissions")
          tpe          = hc.get[String]("@type").getOrElse("Replace")
          patch       <- tpe match {
                           case "Replace"  => Right(Replace(permissions))
                           case "Append"   => Right(Append(permissions))
                           case "Subtract" => Right(Subtract(permissions))
                           case _          => Left(DecodingFailure("@type field must have Append or Subtract value", hc.history))
                         }
        } yield patch
      }
  }

} 
Example 142
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 143
Source File: ElasticSearchDecoderSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.commons.es.client

import ch.epfl.bluebrain.nexus.commons.search.QueryResults
import ch.epfl.bluebrain.nexus.commons.search.QueryResult.ScoredQueryResult
import ch.epfl.bluebrain.nexus.commons.search.QueryResults.{ScoredQueryResults, UnscoredQueryResults}
import ch.epfl.bluebrain.nexus.util.Resources
import io.circe.{Decoder, Json}
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

class ElasticSearchDecoderSpec extends AnyWordSpecLike with Matchers with Resources {

  "A ElasticSearchDecoder" should {
    implicit val D: Decoder[QueryResults[Json]] = ElasticSearchDecoder[Json]

    "decode ElasticSearch response " in {
      val response = jsonContentOf("/commons/es/elastic_response.json")
      val json1    = Json.obj("key" -> Json.fromString("a"), "key2" -> Json.fromString("b"))
      val json2    = Json.obj("key" -> Json.fromString("c"), "key2" -> Json.fromString("d"))

      response.as[QueryResults[Json]].toOption.get shouldEqual ScoredQueryResults(
        2L,
        1f,
        List(ScoredQueryResult(0.5f, json1), ScoredQueryResult(0.8f, json2))
      )
    }

    "decode ElasticSearch empty response" in {
      val response = jsonContentOf("/commons/es/elastic_response_0.json")
      response.as[QueryResults[Json]].toOption.get shouldEqual UnscoredQueryResults(0L, List.empty)
    }
  }
} 
Example 144
Source File: ResourceDecoderSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.serializers

import java.time.Instant

import akka.http.scaladsl.testkit.ScalatestRouteTest
import ch.epfl.bluebrain.nexus.commons.test.{EitherValues, Resources}
import ch.epfl.bluebrain.nexus.iam.types.Identity.User
import ch.epfl.bluebrain.nexus.kg.TestHelper
import ch.epfl.bluebrain.nexus.kg.config.Schemas
import ch.epfl.bluebrain.nexus.kg.resources.ProjectIdentifier.ProjectRef
import ch.epfl.bluebrain.nexus.kg.resources.{Id, ResourceF, ResourceGraph}
import ch.epfl.bluebrain.nexus.rdf.implicits._
import io.circe.Decoder
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike
import org.scalatest.{Inspectors, OptionValues}

class ResourceDecoderSpec
    extends AnyWordSpecLike
    with Matchers
    with Inspectors
    with EitherValues
    with ScalatestRouteTest
    with OptionValues
    with Resources
    with TestHelper {

  private val json                                     = jsonContentOf("/serialization/resource.json")
  private val projectRef                               = ProjectRef(genUUID)
  private val id                                       = url"http://example.com/prefix/myId"
  private val graph                                    = json.toGraph(id).rightValue
  implicit private val decoder: Decoder[ResourceGraph] = ResourceF.resourceGraphDecoder(projectRef)

  private val model = ResourceF(
    Id(projectRef, url"http://example.com/prefix/myId"),
    1L,
    Set(url"https://example.com/vocab/A", url"https://example.com/vocab/B"),
    deprecated = false,
    Map.empty,
    None,
    Instant.parse("2020-01-17T12:45:01.479676Z"),
    Instant.parse("2020-01-17T13:45:01.479676Z"),
    User("john", "bbp"),
    User("brenda", "bbp"),
    Schemas.unconstrainedRef,
    graph
  )

  "A resource" should {
    "be decoded" in {
      json.as[ResourceGraph].rightValue shouldEqual model
    }
  }

} 
Example 145
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 146
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 147
Source File: AbstractHttpClient.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli.clients

import cats.effect.{Sync, Timer}
import cats.implicits._
import ch.epfl.bluebrain.nexus.cli.CliError.ClientError
import ch.epfl.bluebrain.nexus.cli.CliError.ClientError.{SerializationError, Unexpected}
import ch.epfl.bluebrain.nexus.cli.config.EnvConfig
import ch.epfl.bluebrain.nexus.cli.{logRetryErrors, ClientErrOr, Console}
import io.circe.Decoder
import org.http4s.circe.CirceEntityDecoder._
import org.http4s.client.Client
import org.http4s.{Request, Response}
import retry.CatsEffect._
import retry.RetryPolicy
import retry.syntax.all._

import scala.reflect.ClassTag
import scala.util.control.NonFatal

class AbstractHttpClient[F[_]: Timer](client: Client[F], env: EnvConfig)(implicit
    protected val F: Sync[F],
    protected val console: Console[F]
) {

  protected val retry                                = env.httpClient.retry
  protected def successCondition[A]                  = retry.condition.notRetryFromEither[A] _
  implicit protected val retryPolicy: RetryPolicy[F] = retry.retryPolicy
  implicit protected def logOnError[A]               = logRetryErrors[F, A]("interacting with an HTTP API")

  protected def executeDiscard[A](req: Request[F], returnValue: => A): F[ClientErrOr[A]] =
    execute(req, _.body.compile.drain.as(Right(returnValue)))

  protected def executeParse[A: Decoder](req: Request[F])(implicit A: ClassTag[A]): F[ClientErrOr[A]] =
    execute(
      req,
      _.attemptAs[A].value.map(
        _.leftMap(err =>
          SerializationError(err.message, s"The response payload was not of type '${A.runtimeClass.getSimpleName}'")
        )
      )
    )

  private def execute[A](req: Request[F], f: Response[F] => F[ClientErrOr[A]]): F[ClientErrOr[A]] =
    client
      .fetch(req)(ClientError.errorOr[F, A](r => f(r)))
      .recoverWith {
        case NonFatal(err) => F.delay(Left(Unexpected(Option(err.getMessage).getOrElse("").take(30))))
      }
      .retryingM(successCondition[A])
} 
Example 148
Source File: ProjectClient.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli.clients

import cats.effect.concurrent.Ref
import cats.effect.{Sync, Timer}
import cats.implicits._
import ch.epfl.bluebrain.nexus.cli.config.EnvConfig
import ch.epfl.bluebrain.nexus.cli.sse.{OrgLabel, OrgUuid, ProjectLabel, ProjectUuid}
import ch.epfl.bluebrain.nexus.cli.{ClientErrOr, Console}
import io.circe.Decoder
import io.circe.generic.semiauto.deriveDecoder
import org.http4s.client.Client
import org.http4s.{Headers, Request}

trait ProjectClient[F[_]] {

  
  final def apply[F[_]: Sync: Timer](
      client: Client[F],
      env: EnvConfig,
      cache: Ref[F, Map[(OrgUuid, ProjectUuid), (OrgLabel, ProjectLabel)]],
      console: Console[F]
  ): ProjectClient[F] = {
    implicit val c: Console[F] = console
    new LiveProjectClient[F](client, env, cache)
  }

  private class LiveProjectClient[F[_]: Timer: Console: Sync](
      client: Client[F],
      env: EnvConfig,
      cache: Ref[F, Map[(OrgUuid, ProjectUuid), (OrgLabel, ProjectLabel)]]
  ) extends AbstractHttpClient[F](client, env)
      with ProjectClient[F] {

    override def labels(org: OrgUuid, proj: ProjectUuid): F[ClientErrOr[(OrgLabel, ProjectLabel)]] =
      cache.get.flatMap { map =>
        map.get((org, proj)) match {
          // value in cache, return
          case Some(value) => F.pure(Right(value))
          // value not in cache, fetch, update and return
          case None        =>
            get(org, proj).flatMap {
              // propagate error
              case l @ Left(_)      => F.pure(l)
              // success, update cache and return
              case r @ Right(value) =>
                cache.modify(m => (m.updated((org, proj), value), value)) *> F.pure(r)
            }
        }
      }

    private def get(org: OrgUuid, proj: ProjectUuid): F[ClientErrOr[(OrgLabel, ProjectLabel)]] = {
      val uri = env.project(org, proj)
      val req = Request[F](uri = uri, headers = Headers(env.authorizationHeader.toList))
      executeParse[NexusAPIProject](req).map {
        case Right(NexusAPIProject(orgLabel, projectLabel)) => Right((orgLabel, projectLabel))
        case Left(err)                                      => Left(err)
      }
    }
  }

  final private[ProjectClient] case class NexusAPIProject(`_organizationLabel`: OrgLabel, `_label`: ProjectLabel)
  private[ProjectClient] object NexusAPIProject {
    implicit val nexusAPIProjectDecoder: Decoder[NexusAPIProject] = deriveDecoder[NexusAPIProject]
  }
} 
Example 149
Source File: Event.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli.sse

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

import ch.epfl.bluebrain.nexus.cli.utils.Codecs
import io.circe.generic.semiauto.deriveDecoder
import io.circe.{Decoder, Json}
import org.http4s.Uri


final case class Event(
    eventType: EventType,
    resourceId: Uri,
    rev: Long,
    organization: OrgUuid,
    project: ProjectUuid,
    resourceTypes: Set[Uri],
    instant: Instant,
    raw: Json
)

object Event extends Codecs {

  final private[Event] case class APIEvent(
      `_organizationUuid`: UUID,
      `_projectUuid`: UUID,
      `@type`: EventType,
      `_types`: Option[Set[Uri]],
      `_resourceId`: Uri,
      `_rev`: Option[Long],
      `_instant`: Instant
  ) {
    def asEvent(raw: Json): Event =
      Event(
        `@type`,
        `_resourceId`,
        `_rev`.getOrElse(1L),
        OrgUuid(`_organizationUuid`),
        ProjectUuid(`_projectUuid`),
        `_types`.getOrElse(Set.empty[Uri]),
        `_instant`,
        raw
      )
  }

  private[Event] object APIEvent {
    implicit val apiEventDecoder: Decoder[APIEvent] = deriveDecoder[APIEvent]
  }

  implicit final val eventDecoder: Decoder[Event] =
    Decoder.instance { cursor => cursor.as[APIEvent].map(_.asEvent(cursor.value)) }

} 
Example 150
Source File: EventType.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.cli.sse

import io.circe.Decoder


  final def apply(string: String): Either[String, EventType] =
    string match {
      case "Created"               => Right(Created)
      case "Updated"               => Right(Updated)
      case "Deprecated"            => Right(Deprecated)
      case "FileCreated"           => Right(FileCreated)
      case "FileUpdated"           => Right(FileUpdated)
      case "FileDigestUpdated"     => Right(FileDigestUpdated)
      case "FileAttributesUpdated" => Right(FileAttributesUpdated)
      case "TagAdded"              => Right(TagAdded)
      case other                   => Left(s"'$other' does not match a known event type")
    }

  implicit final val eventTypeDecoder: Decoder[EventType] =
    Decoder.decodeString.emap(apply)
} 
Example 151
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 152
Source File: IamIdentitiesClient.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.storage

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.client.RequestBuilding.Get
import akka.http.scaladsl.model.HttpRequest
import akka.http.scaladsl.model.headers.OAuth2BearerToken
import akka.http.scaladsl.unmarshalling.FromEntityUnmarshaller
import akka.util.ByteString
import cats.effect.{ContextShift, Effect, IO}
import cats.implicits._
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClient.Identity._
import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClient._
import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClientError.IdentitiesSerializationError
import ch.epfl.bluebrain.nexus.storage.config.IamClientConfig
import de.heikoseeberger.akkahttpcirce.ErrorAccumulatingCirceSupport.{DecodingFailures => AccDecodingFailures}
import io.circe.Decoder.Result
import io.circe.{Decoder, DecodingFailure, HCursor}

import scala.concurrent.ExecutionContext

class IamIdentitiesClient[F[_]](config: IamClientConfig)(implicit F: Effect[F], as: ActorSystem)
    extends JsonLdCirceSupport {

  private val um: FromEntityUnmarshaller[Caller]      = unmarshaller[Caller]
  implicit private val ec: ExecutionContext           = as.dispatcher
  implicit private val contextShift: ContextShift[IO] = IO.contextShift(ec)

  def apply()(implicit credentials: Option[AccessToken]): F[Caller] =
    credentials match {
      case Some(token) => execute(Get(config.identitiesIri.asAkka).addCredentials(OAuth2BearerToken(token.value)))
      case None        => F.pure(Caller.anonymous)
    }

  private def execute(req: HttpRequest): F[Caller] = {
    IO.fromFuture(IO(Http().singleRequest(req))).to[F].flatMap { resp =>
      if (resp.status.isSuccess())
        IO.fromFuture(IO(um(resp.entity))).to[F].recoverWith {
          case err: AccDecodingFailures => F.raiseError(IdentitiesSerializationError(err.getMessage))
          case err: Error               => F.raiseError(IdentitiesSerializationError(err.getMessage))
        }
      else
        IO.fromFuture(IO(resp.entity.dataBytes.runFold(ByteString(""))(_ ++ _).map(_.utf8String)))
          .to[F]
          .flatMap { err => F.raiseError(IamIdentitiesClientError.unsafe(resp.status, err)) }
    }
  }

}

object IamIdentitiesClient {

  
    final case class Authenticated(realm: String) extends Identity

    private def decodeAnonymous(hc: HCursor): Result[Subject] =
      hc.get[String]("@type").flatMap {
        case "Anonymous" => Right(Anonymous)
        case _           => Left(DecodingFailure("Cannot decode Anonymous Identity", hc.history))
      }

    private def decodeUser(hc: HCursor): Result[Subject] =
      (hc.get[String]("subject"), hc.get[String]("realm")).mapN {
        case (subject, realm) => User(subject, realm)
      }

    private def decodeGroup(hc: HCursor): Result[Identity] =
      (hc.get[String]("group"), hc.get[String]("realm")).mapN {
        case (group, realm) => Group(group, realm)
      }

    private def decodeAuthenticated(hc: HCursor): Result[Identity] =
      hc.get[String]("realm").map(Authenticated)

    private val attempts =
      List[HCursor => Result[Identity]](decodeAnonymous, decodeUser, decodeGroup, decodeAuthenticated)

    implicit val identityDecoder: Decoder[Identity] =
      Decoder.instance { hc =>
        attempts.foldLeft(Left(DecodingFailure("Unexpected", hc.history)): Result[Identity]) {
          case (acc @ Right(_), _) => acc
          case (_, f)              => f(hc)
        }
      }
  }

} 
Example 153
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 154
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 155
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 156
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 157
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 158
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 159
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 160
Source File: MLFlowModelSpec.scala    From ForestFlow   with Apache License 2.0 5 votes vote down vote up
package ai.forestflow.serving.MLFlow

import ai.forestflow.serving.impl.{LocalFileArtifactReader, MLFlowH2OLoader, UnsupportedServableFlavor}
import ai.forestflow.serving.interfaces.{ArtifactReader, Loader}
import cats.syntax.either._
import ai.forestflow.serving.impl.{LocalFileArtifactReader, MLFlowH2OLoader, UnsupportedServableFlavor}
import ai.forestflow.serving.interfaces.ArtifactReader
import ai.forestflow.utils.SourceStorageProtocols
import io.circe.generic.extras._
import io.circe.generic.extras.semiauto.deriveDecoder
import io.circe.{CursorOp, Decoder, DecodingFailure}
import ai.forestflow.serving.interfaces.Loader
import ai.forestflow.utils.ThrowableImplicits._
import org.joda.time.{DateTimeZone, LocalDateTime}


case class MLFlowModelSpec(
  artifactReader: ArtifactReader,

  runId: Option[String],

  timeCreated: Long,

  flavors: Map[String, Loader]
) {
  def getServableFlavor: Option[(String, Loader)] = flavors.collectFirst { case (flavor, loader) if !loader.isInstanceOf[UnsupportedServableFlavor] => (flavor, loader) }
}

object MLFlowModelSpec {

  implicit val config: Configuration = {
    val baseConfig = Configuration.default.withSnakeCaseMemberNames
    baseConfig.copy(transformMemberNames = baseConfig.transformMemberNames andThen {
      // from snake_case in class to snake_case file
      case "artifact_reader" => "artifact_path"
      case "time_created" => "utc_time_created" // utc_time_created is a string!
      case other => other
    })
  }

  implicit val decodeTimeCreated: Decoder[Long] = Decoder.decodeString.emap{ tm: String =>
    Either.catchNonFatal[Long]({
      var ts = tm.replace(" ", "T")
      if (ts.takeRight(1) != "Z")
        ts = ts + "Z"
      val ll = LocalDateTime.parse(tm.replace(" ", "T")).toDateTime(DateTimeZone.UTC)
      ll.getMillis
    }
    ).leftMap(t => s"timeCreated Decoder Failed: ${t.printableStackTrace}")
  }.handleErrorWith(_ => Decoder.decodeLong)

  implicit val decodeMLFlowModel: Decoder[MLFlowModelSpec] = deriveDecoder[MLFlowModelSpec]

  implicit val decodeArtifactReaderString: Decoder[ArtifactReader] = Decoder.decodeOption[String].emap { artifactPath: Option[String] =>
    Either.catchNonFatal[ArtifactReader]({
      artifactPath match {
        case Some(path) => ArtifactReader.getArtifactReader(path)
        case _ => LocalFileArtifactReader("")
      }
    }
    ).leftMap(t => s"Artifact Reader Decoder Failed: ${t.printableStackTrace}")
  }

  implicit val decodeServableFlavor: Decoder[Map[String, Loader]] = Decoder.decodeMap[String, Map[String, String]].emap { flavors =>
    Either.catchNonFatal[Map[String, Loader]](
      flavors
        .map { case (flavor, props) => (flavor.toLowerCase, props) }
        .map {
          case (f@"h2o_mojo", props) => f -> MLFlowH2OLoader(dataPath = props.getOrElse("data", ""), version = props.get("h2o_version"))
          
          case (f, props) => f -> UnsupportedServableFlavor(props)
          case (f, props) => throw DecodingFailure(s"Unexpected or unsupported flavor type [$f] with props $props", List[CursorOp]())
          // TODO: Support POJO?
          // case (f, _) => p -> BasicSourceProvider()
        }
    ).leftMap(t => t.printableStackTrace)

  }

} 
Example 161
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 162
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 163
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 164
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 165
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 166
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 167
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 168
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 169
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 170
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 171
Source File: Parsers.scala    From get-programming-with-scala   with MIT License 5 votes vote down vote up
package org.example.movies.entities

import java.time.LocalDate

import io.circe.Decoder
import io.circe.parser.decode
import io.circe.generic.auto._
import scala.util.Try

object Parsers {

  def parseInt(row: Map[String, String], key: String): Option[Int] =
    parseAs(row, key, _.toInt)

  def parseDouble(row: Map[String, String], key: String): Option[Double] =
    parseAs(row, key, _.toDouble)

  def parseString(row: Map[String, String], key: String): Option[String] =
    parseAs(row, key, identity)

  def parseFloat(row: Map[String, String], key: String): Option[Float] =
    parseAs(row, key, _.toFloat)

  def parseLocalDate(row: Map[String, String], key: String): Option[LocalDate] =
    parseAs(row, key, LocalDate.parse)

  def parseGenres(row: Map[String, String], key: String): Option[List[Genre]] =
    parseJsonAs[List[Genre]](row, key)

  private def parseJsonAs[T: Decoder](row: Map[String, String], key: String): Option[T] =
    for {
      rawJson <- parseString(row, key)
      // for some reason the CSV is using ' rather than " for JSON,
      // so we need to clean the data before decoding
      cleanJson = rawJson.replace("'", "\"")
      // rather than returning an error for invalid JSON, we return no value
      decodedValue <- decode[T](cleanJson).toOption
    } yield decodedValue

  private def parseAs[T](row: Map[String, String], key: String, f: String => T): Option[T] =
    row.get(key).flatMap { value =>
      // if we cannot parse a value, we return no value
      Try(f(value)).toOption
    }
} 
Example 172
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 173
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 174
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 175
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 176
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 177
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 178
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 179
Source File: GrantType.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.client.types

import io.circe.Decoder


  final case object RefreshToken extends GrantType

  final implicit val grantTypeDecoder: Decoder[GrantType] = Decoder.decodeString.emap {
    case "authorizationCode" => Right(AuthorizationCode)
    case "implicit"          => Right(Implicit)
    case "password"          => Right(Password)
    case "clientCredentials" => Right(ClientCredentials)
    case "deviceCode"        => Right(DeviceCode)
    case "refreshToken"      => Right(RefreshToken)
    case other               => Left(s"Unknown grant type '$other'")
  }
} 
Example 180
Source File: Caller.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.client.types

import ch.epfl.bluebrain.nexus.iam.client.types.Identity._
import io.circe.{Decoder, DecodingFailure}


  val anonymous: Caller = Caller(Anonymous: Subject, Set[Identity](Anonymous))

  final implicit val callerDecoder: Decoder[Caller] =
    Decoder.instance { cursor =>
      cursor
        .get[Set[Identity]]("identities")
        .flatMap { identities =>
          identities.collectFirst { case u: User => u } orElse identities.collectFirst { case Anonymous => Anonymous } match {
            case Some(subject: Subject) => Right(Caller(subject, identities))
            case _ =>
              val pos = cursor.downField("identities").history
              Left(DecodingFailure("Unable to find a subject in the collection of identities", pos))
          }
        }
    }
} 
Example 181
Source File: EventSource.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.client

import akka.NotUsed
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.headers.OAuth2BearerToken
import akka.http.scaladsl.model.{HttpRequest, HttpResponse}
import akka.stream.Materializer
import akka.stream.alpakka.sse.scaladsl.{EventSource => SSESource}
import akka.stream.scaladsl.Source
import ch.epfl.bluebrain.nexus.iam.client.config.IamClientConfig
import ch.epfl.bluebrain.nexus.iam.client.types.AuthToken
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import ch.epfl.bluebrain.nexus.rdf.implicits._
import com.typesafe.scalalogging.Logger
import io.circe.Decoder
import io.circe.parser.decode

import scala.concurrent.{ExecutionContext, Future}

trait EventSource[A] {

  
  def apply[A: Decoder](
      config: IamClientConfig
  )(implicit as: ActorSystem, mt: Materializer, ec: ExecutionContext): EventSource[A] =
    new EventSource[A] {
      private val logger = Logger[this.type]
      private val http   = Http()

      private def addCredentials(request: HttpRequest)(implicit cred: Option[AuthToken]): HttpRequest =
        cred.map(token => request.addCredentials(OAuth2BearerToken(token.value))).getOrElse(request)

      private def send(request: HttpRequest)(implicit cred: Option[AuthToken]): Future[HttpResponse] =
        http.singleRequest(addCredentials(request)).map { resp =>
          if (!resp.status.isSuccess())
            logger.warn(s"HTTP response when performing SSE request: status = '${resp.status}'")
          resp
        }

      override def apply(iri: AbsoluteIri, offset: Option[String])(
          implicit cred: Option[AuthToken]
      ): Source[A, NotUsed] =
        SSESource(iri.asAkka, send, offset, config.sseRetryDelay).flatMapConcat { sse =>
          decode[A](sse.data) match {
            case Right(ev) => Source.single(ev)
            case Left(err) =>
              logger.error(s"Failed to decode admin event '$sse'", err)
              Source.empty
          }
        }
    }
} 
Example 182
Source File: PermissionsRoutes.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.routes

import akka.http.javadsl.server.Rejections._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.iam.config.AppConfig.HttpConfig
import ch.epfl.bluebrain.nexus.iam.directives.AuthDirectives.authenticator
import ch.epfl.bluebrain.nexus.iam.marshallers.instances._
import ch.epfl.bluebrain.nexus.iam.permissions.Permissions
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions
import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions.{Append, Replace, Subtract}
import ch.epfl.bluebrain.nexus.iam.types.ResourceF._
import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission}
import io.circe.{Decoder, DecodingFailure}
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global


class PermissionsRoutes(permissions: Permissions[Task], realms: Realms[Task])(implicit http: HttpConfig) {

  def routes: Route =
    (pathPrefix("permissions") & pathEndOrSingleSlash) {
      operationName(s"/${http.prefix}/permissions") {
        authenticateOAuth2Async("*", authenticator(realms)).withAnonymousUser(Caller.anonymous) { implicit caller =>
          concat(
            get {
              parameter("rev".as[Long].?) {
                case Some(rev) => complete(permissions.fetchAt(rev).runNotFound)
                case None      => complete(permissions.fetch.runToFuture)
              }
            },
            (put & parameter("rev" ? 0L)) { rev =>
              entity(as[PatchPermissions]) {
                case Replace(set) =>
                  complete(permissions.replace(set, rev).runToFuture)
                case _ => reject(validationRejection("Only @type 'Replace' is permitted when using 'put'."))
              }
            },
            delete {
              parameter("rev".as[Long]) { rev =>
                complete(permissions.delete(rev).runToFuture)
              }
            },
            (patch & parameter("rev" ? 0L)) { rev =>
              entity(as[PatchPermissions]) {
                case Append(set) =>
                  complete(permissions.append(set, rev).runToFuture)
                case Subtract(set) =>
                  complete(permissions.subtract(set, rev).runToFuture)
                case _ =>
                  reject(validationRejection("Only @type 'Append' or 'Subtract' is permitted when using 'patch'."))
              }
            }
          )
        }
      }
    }
}

object PermissionsRoutes {

  private[routes] sealed trait PatchPermissions extends Product with Serializable

  private[routes] object PatchPermissions {

    final case class Append(permissions: Set[Permission])   extends PatchPermissions
    final case class Subtract(permissions: Set[Permission]) extends PatchPermissions
    final case class Replace(permissions: Set[Permission])  extends PatchPermissions

    implicit val patchPermissionsDecoder: Decoder[PatchPermissions] =
      Decoder.instance { hc =>
        for {
          permissions <- hc.get[Set[Permission]]("permissions")
          tpe = hc.get[String]("@type").getOrElse("Replace")
          patch <- tpe match {
            case "Replace"  => Right(Replace(permissions))
            case "Append"   => Right(Append(permissions))
            case "Subtract" => Right(Subtract(permissions))
            case _          => Left(DecodingFailure("@type field must have Append or Subtract value", hc.history))
          }
        } yield patch
      }
  }

} 
Example 183
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 184
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 185
Source File: CirceConfigLaws.scala    From circe-config   with Apache License 2.0 5 votes vote down vote up
package io.circe.config

import cats.instances.either._
import cats.laws._
import cats.laws.discipline._
import io.circe.{Decoder, Json, Parser, ParsingFailure}
import io.circe.testing.ParserTests
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatestplus.scalacheck.Checkers
import org.scalacheck.{Arbitrary, Prop}
import org.typelevel.discipline.Laws
import com.typesafe.config.{parser => _, _}

class CirceConfigLaws extends AnyFlatSpec {

  implicit val arbitraryConfigJson: Arbitrary[Json] = Arbitrary {
    def normalize(json: Json): Json =
      json.mapObject(_.filterKeys(_.nonEmpty).mapValues(normalize)).mapArray(_.map(normalize)).mapNumber { number =>
        // Lower the precision to the types used internally by
        // Lightbend Config to ensure that numbers are representable.
        val double: java.lang.Double = number.toDouble
        val long: java.lang.Long = double.toLong

        val json =
          if (double.isInfinite)
            // While +/+Infinity can be represented, it cannot be round-tripped.
            Json.fromInt(42)
          else if (long == double)
            // Emulate Lightbend Config's internal cast:
            // https://github.com/lightbend/config/blob/v1.3.4/config/src/main/java/com/typesafe/config/impl/ConfigNumber.java#L96-L104
            Json.fromLong(long)
          else
            Json.fromDouble(double).get

        json.asNumber.get
      }

    for (jsonObject <- io.circe.testing.instances.arbitraryJsonObject.arbitrary)
      yield normalize(Json.fromJsonObject(jsonObject))
  }

  def checkLaws(name: String, ruleSet: Laws#RuleSet): Unit = ruleSet.all.properties.zipWithIndex.foreach {
    case ((id, prop), 0) => name should s"obey $id" in Checkers.check(prop)
    case ((id, prop), _) => it should s"obey $id" in Checkers.check(prop)
  }

  checkLaws("Parser", ParserTests(parser).fromString)
  checkLaws(
    "Parser",
    ParserTests(parser).fromFunction[Config]("fromConfig")(
      ConfigFactory.parseString,
      _.parse,
      _.decode[Json],
      _.decodeAccumulating[Json]
    )
  )
  checkLaws("Printer", PrinterTests(parser).fromJson)
  checkLaws("Codec", CodecTests[Config](syntax.configDecoder, parser.parse).fromFunction("fromConfig"))
}

case class PrinterTests(parser: Parser) extends Laws {
  def fromJson(implicit A: Arbitrary[Json]): RuleSet =
    new DefaultRuleSet(
      name = "printer",
      parent = None,
      "roundTrip" -> Prop.forAll { (json: Json) =>
        parser.parse(printer.print(json)) <-> Right(json)
      }
    )
}

case class CodecTests[A](decoder: Decoder[A], parse: A => Either[ParsingFailure, Json]) extends Laws {
  def fromFunction(name: String)(implicit arbitraryJson: Arbitrary[Json]): RuleSet =
    new DefaultRuleSet(
      name = s"codec[$name]",
      parent = None,
      "decodingRoundTrip" -> Prop.forAll { (json: Json) =>
        decoder.decodeJson(json).flatMap(parse) <-> Right(json)
      }
    )
} 
Example 186
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 187
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 188
Source File: EnumerationCodec.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, DecodingFailure, HCursor, Json }
import io.circe.generic.extras.Configuration
import scala.annotation.implicitNotFound
import shapeless.{ :+:, CNil, Coproduct, HNil, Inl, Inr, LabelledGeneric, Witness }
import shapeless.labelled.{ FieldType, field }

@implicitNotFound(
  """Could not find EnumerationCodec 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 EnumerationCodec[A] extends Codec[A]

object EnumerationCodec {
  implicit val codecForEnumerationCNil: EnumerationCodec[CNil] = new EnumerationCodec[CNil] {
    def apply(c: HCursor): Decoder.Result[CNil] = Left(DecodingFailure("Enumeration", c.history))
    def apply(a: CNil): Json = sys.error("Cannot encode CNil")
  }

  implicit def codecForEnumerationCCons[K <: Symbol, V, R <: Coproduct](implicit
    witK: Witness.Aux[K],
    gen: LabelledGeneric.Aux[V, HNil],
    codecForR: EnumerationCodec[R],
    config: Configuration = Configuration.default
  ): EnumerationCodec[FieldType[K, V] :+: R] = new EnumerationCodec[FieldType[K, V] :+: R] {
    def apply(c: HCursor): Decoder.Result[FieldType[K, V] :+: R] =
      c.as[String] match {
        case Right(s) if s == config.transformConstructorNames(witK.value.name) =>
          Right(Inl(field[K](gen.from(HNil))))
        case Right(_) =>
          codecForR.apply(c) match {
            case Right(v)  => Right(Inr(v))
            case Left(err) => Left(err)
          }
        case Left(err) => Left(DecodingFailure("Enumeration", c.history))
      }
    def apply(a: FieldType[K, V] :+: R): Json = a match {
      case Inl(l) => Json.fromString(config.transformConstructorNames(witK.value.name))
      case Inr(r) => codecForR(r)
    }
  }

  implicit def codecForEnumeration[A, R <: Coproduct](implicit
    gen: LabelledGeneric.Aux[A, R],
    codecForR: EnumerationCodec[R]
  ): EnumerationCodec[A] =
    new EnumerationCodec[A] {
      def apply(c: HCursor): Decoder.Result[A] = codecForR(c) match {
        case Right(v)  => Right(gen.from(v))
        case Left(err) => Left(err)
      }
      def apply(a: A): Json = codecForR(gen.to(a))
    }
} 
Example 189
Source File: ReprAsObjectCodec.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras.codec

import cats.data.Validated
import io.circe.{ Decoder, DecodingFailure, HCursor, JsonObject }
import io.circe.generic.extras.ConfigurableDeriver
import io.circe.generic.extras.decoding.ReprDecoder
import io.circe.generic.extras.encoding.ReprAsObjectEncoder
import scala.annotation.implicitNotFound
import scala.collection.immutable.Map
import scala.language.experimental.macros
import shapeless.HNil


@implicitNotFound(
  """Could not find ReprAsObjectCodec 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 ReprAsObjectCodec[A] extends ReprDecoder[A] with ReprAsObjectEncoder[A]

object ReprAsObjectCodec {
  implicit def deriveReprAsObjectCodec[R]: ReprAsObjectCodec[R] = macro ConfigurableDeriver.deriveConfiguredCodec[R]

  val hnilReprCodec: ReprAsObjectCodec[HNil] = new ReprAsObjectCodec[HNil] {
    def configuredDecode(c: HCursor)(
      transformMemberNames: String => String,
      transformConstructorNames: String => String,
      defaults: Map[String, Any],
      discriminator: Option[String]
    ): Decoder.Result[HNil] =
      if (c.value.isObject) Right(HNil) else Left(DecodingFailure("HNil", c.history))

    def configuredDecodeAccumulating(c: HCursor)(
      transformMemberNames: String => String,
      transformConstructorNames: String => String,
      defaults: Map[String, Any],
      discriminator: Option[String]
    ): Decoder.AccumulatingResult[HNil] =
      if (c.value.isObject) Validated.valid(HNil) else Validated.invalidNel(DecodingFailure("HNil", c.history))

    def configuredEncodeObject(a: HNil)(
      transformMemberNames: String => String,
      transformDiscriminator: String => String,
      discriminator: Option[String]
    ): JsonObject = JsonObject.empty
  }
} 
Example 190
Source File: IncompleteConfiguredDecoders.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras.decoding

import io.circe.{ Decoder, HCursor }
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.util.RecordToMap
import io.circe.generic.util.PatchWithOptions
import scala.collection.immutable.Map
import shapeless.{ Default, HList, LabelledGeneric }
import shapeless.ops.function.FnFromProduct
import shapeless.ops.record.RemoveAll

private[circe] trait IncompleteConfiguredDecoders {
  implicit final def decodeIncompleteCaseClass[F, P <: HList, A, D <: HList, T <: HList, R <: HList](implicit
    ffp: FnFromProduct.Aux[P => A, F],
    gen: LabelledGeneric.Aux[A, T],
    removeAll: RemoveAll.Aux[T, P, (P, R)],
    decode: ReprDecoder[R],
    defaults: Default.AsRecord.Aux[A, D],
    defaultMapper: RecordToMap[D],
    config: Configuration
  ): ConfiguredDecoder[F] = new ConfiguredDecoder[F](config) {
    private[this] val defaultMap: Map[String, Any] = if (config.useDefaults) defaultMapper(defaults()) else Map.empty

    final def apply(c: HCursor): Decoder.Result[F] = decode.configuredDecode(c)(
      config.transformMemberNames,
      constructorNameTransformer,
      defaultMap,
      None
    ) match {
      case Right(r)    => Right(ffp(p => gen.from(removeAll.reinsert((p, r)))))
      case l @ Left(_) => l.asInstanceOf[Decoder.Result[F]]
    }

    override final def decodeAccumulating(c: HCursor): Decoder.AccumulatingResult[F] =
      decode
        .configuredDecodeAccumulating(c)(
          config.transformMemberNames,
          constructorNameTransformer,
          defaultMap,
          None
        )
        .map(r => ffp(p => gen.from(removeAll.reinsert((p, r)))))
  }

  implicit final def decodeCaseClassPatch[A, D <: HList, R <: HList, O <: HList](implicit
    gen: LabelledGeneric.Aux[A, R],
    patch: PatchWithOptions.Aux[R, O],
    decode: ReprDecoder[O],
    defaults: Default.AsRecord.Aux[A, D],
    defaultMapper: RecordToMap[D],
    config: Configuration
  ): ConfiguredDecoder[A => A] = new ConfiguredDecoder[A => A](config) {
    private[this] val defaultMap: Map[String, Any] = if (config.useDefaults) defaultMapper(defaults()) else Map.empty

    final def apply(c: HCursor): Decoder.Result[A => A] = decode.configuredDecode(c)(
      config.transformMemberNames,
      constructorNameTransformer,
      defaultMap,
      None
    ) match {
      case Right(o)    => Right(a => gen.from(patch(gen.to(a), o)))
      case l @ Left(_) => l.asInstanceOf[Decoder.Result[A => A]]
    }

    override final def decodeAccumulating(c: HCursor): Decoder.AccumulatingResult[A => A] =
      decode
        .configuredDecodeAccumulating(c)(
          config.transformMemberNames,
          constructorNameTransformer,
          defaultMap,
          None
        )
        .map(o => a => gen.from(patch(gen.to(a), o)))
  }
} 
Example 191
Source File: UnwrappedDecoder.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras.decoding

import io.circe.{ Decoder, HCursor }
import scala.annotation.implicitNotFound
import shapeless.{ ::, Generic, HNil, Lazy }

@implicitNotFound(
  """Could not find UnwrappedDecoder 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 UnwrappedDecoder[A] extends Decoder[A]

object UnwrappedDecoder {
  implicit def decodeUnwrapped[A, R](implicit
    gen: Lazy[Generic.Aux[A, R :: HNil]],
    decodeR: Decoder[R]
  ): UnwrappedDecoder[A] = new UnwrappedDecoder[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]]
      }
  }
} 
Example 192
Source File: EnumerationDecoder.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras.decoding

import io.circe.{ Decoder, DecodingFailure, HCursor }
import io.circe.generic.extras.Configuration
import scala.annotation.implicitNotFound
import shapeless.{ :+:, CNil, Coproduct, HNil, Inl, Inr, LabelledGeneric, Witness }
import shapeless.labelled.{ FieldType, field }

@implicitNotFound(
  """Could not find EnumerationDecoder 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 EnumerationDecoder[A] extends Decoder[A]

object EnumerationDecoder {
  implicit val decodeEnumerationCNil: EnumerationDecoder[CNil] = new EnumerationDecoder[CNil] {
    def apply(c: HCursor): Decoder.Result[CNil] = Left(DecodingFailure("Enumeration", c.history))
  }

  implicit def decodeEnumerationCCons[K <: Symbol, V, R <: Coproduct](implicit
    witK: Witness.Aux[K],
    gen: LabelledGeneric.Aux[V, HNil],
    decodeR: EnumerationDecoder[R],
    config: Configuration = Configuration.default
  ): EnumerationDecoder[FieldType[K, V] :+: R] = new EnumerationDecoder[FieldType[K, V] :+: R] {
    def apply(c: HCursor): Decoder.Result[FieldType[K, V] :+: R] =
      c.as[String] match {
        case Right(s) if s == config.transformConstructorNames(witK.value.name) =>
          Right(Inl(field[K](gen.from(HNil))))
        case Right(_) =>
          decodeR.apply(c) match {
            case Right(v)  => Right(Inr(v))
            case Left(err) => Left(err)
          }
        case Left(err) => Left(DecodingFailure("Enumeration", c.history))
      }
  }

  implicit def decodeEnumeration[A, Repr <: Coproduct](implicit
    gen: LabelledGeneric.Aux[A, Repr],
    decodeR: EnumerationDecoder[Repr]
  ): EnumerationDecoder[A] =
    new EnumerationDecoder[A] {
      def apply(c: HCursor): Decoder.Result[A] = decodeR(c) match {
        case Right(v)  => Right(gen.from(v))
        case Left(err) => Left(err)
      }
    }
} 
Example 193
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 194
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 195
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)
    )
} 
Example 196
Source File: AnyValCirceEncoding.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.example

import io.circe.{ Decoder, Encoder }
import shapeless.Unwrapped

trait AnyValCirceEncoding {
  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]): Decoder[V] = {
    val _ = ev
    decoder.map(V.wrap)
  }
}

object AnyValCirceEncoding extends AnyValCirceEncoding 
Example 197
Source File: Algebra.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.example.account

import aecor.encoding.WireProtocol
import aecor.example.AnyValCirceEncoding
import aecor.example.common.Amount
import aecor.example.transaction.TransactionId
import aecor.macros.boopickle.BoopickleWireProtocol
import cats.tagless.{ Derive, FunctorK }
import io.circe.{ Decoder, Encoder }

final case class AccountTransactionId(baseTransactionId: TransactionId,
                                      kind: AccountTransactionKind)

object AccountTransactionId extends AnyValCirceEncoding {
  implicit def decoder: Decoder[AccountTransactionId] = io.circe.generic.semiauto.deriveDecoder
  implicit def encoder: Encoder[AccountTransactionId] = io.circe.generic.semiauto.deriveEncoder
}

sealed abstract class AccountTransactionKind extends Product with Serializable
object AccountTransactionKind {
  case object Normal extends AccountTransactionKind
  case object Revert extends AccountTransactionKind
  implicit val decoder: Decoder[AccountTransactionKind] = Decoder[String].emap {
    case "Normal" => Right(Normal)
    case "Revert" => Right(Revert)
    case _        => Left("Unknown AccountTransactionKind")
  }
  implicit val encoder: Encoder[AccountTransactionKind] = Encoder[String].contramap(_.toString)
}

trait Algebra[F[_]] {
  def open(checkBalance: Boolean): F[Unit]
  def credit(transactionId: AccountTransactionId, amount: Amount): F[Unit]
  def debit(transactionId: AccountTransactionId, amount: Amount): F[Unit]
}

object Algebra {
  import boopickle.Default._
  implicit def functorK: FunctorK[Algebra] = Derive.functorK
  implicit def wireProtocol: WireProtocol[Algebra] = BoopickleWireProtocol.derive
} 
Example 198
Source File: PersistentEncoderCirce.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.tests

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 PersistentEncoderCirce {
  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)
    )
} 
Example 199
Source File: SourceSettings.scala    From scylla-migrator   with Apache License 2.0 5 votes vote down vote up
package com.scylladb.migrator.config

import cats.implicits._
import io.circe.syntax._
import io.circe.{ Decoder, DecodingFailure, Encoder, Json, ObjectEncoder }

sealed trait SourceSettings
object SourceSettings {
  case class Cassandra(host: String,
                       port: Int,
                       credentials: Option[Credentials],
                       keyspace: String,
                       table: String,
                       splitCount: Option[Int],
                       connections: Option[Int],
                       fetchSize: Int,
                       preserveTimestamps: Boolean)
      extends SourceSettings
  case class Parquet(path: String, credentials: Option[AWSCredentials]) extends SourceSettings

  implicit val decoder: Decoder[SourceSettings] = Decoder.instance { cursor =>
    cursor.get[String]("type").flatMap {
      case "cassandra" | "scylla" =>
        Decoder
          .forProduct9(
            "host",
            "port",
            "credentials",
            "keyspace",
            "table",
            "splitCount",
            "connections",
            "fetchSize",
            "preserveTimestamps")(Cassandra.apply)
          .apply(cursor)
      case "parquet" =>
        Decoder
          .forProduct2("path", "credentials")(Parquet.apply)
          .apply(cursor)
      case otherwise =>
        Left(DecodingFailure(s"Unknown source type: ${otherwise}", cursor.history))
    }
  }

  implicit val encoder: Encoder[SourceSettings] = Encoder.instance {
    case s: Cassandra =>
      Encoder
        .forProduct9(
          "host",
          "port",
          "credentials",
          "keyspace",
          "table",
          "splitCount",
          "connections",
          "fetchSize",
          "preserveTimestamps")(Cassandra.unapply(_: Cassandra).get)
        .encodeObject(s)
        .add("type", Json.fromString("cassandra"))
        .asJson
    case s: Parquet =>
      Encoder
        .forProduct2("path", "credentials")(Parquet.unapply(_: Parquet).get)
        .encodeObject(s)
        .add("type", Json.fromString("parquet"))
        .asJson
  }
} 
Example 200
Source File: MigratorConfig.scala    From scylla-migrator   with Apache License 2.0 5 votes vote down vote up
package com.scylladb.migrator.config

import cats.implicits._
import com.datastax.spark.connector.rdd.partitioner.dht.{ BigIntToken, LongToken, Token }
import io.circe.generic.semiauto.{ deriveDecoder, deriveEncoder }
import io.circe.syntax._
import io.circe.yaml.parser
import io.circe.yaml.syntax._
import io.circe.{ Decoder, DecodingFailure, Encoder, Error, Json }

case class MigratorConfig(source: SourceSettings,
                          target: TargetSettings,
                          renames: List[Rename],
                          savepoints: Savepoints,
                          skipTokenRanges: Set[(Token[_], Token[_])],
                          validation: Validation) {
  def render: String = this.asJson.asYaml.spaces2
}
object MigratorConfig {
  implicit val tokenEncoder: Encoder[Token[_]] = Encoder.instance {
    case LongToken(value)   => Json.obj("type" := "long", "value"   := value)
    case BigIntToken(value) => Json.obj("type" := "bigint", "value" := value)
  }

  implicit val tokenDecoder: Decoder[Token[_]] = Decoder.instance { cursor =>
    for {
      tpe <- cursor.get[String]("type").right
      result <- tpe match {
                 case "long"    => cursor.get[Long]("value").right.map(LongToken(_))
                 case "bigint"  => cursor.get[BigInt]("value").right.map(BigIntToken(_))
                 case otherwise => Left(DecodingFailure(s"Unknown token type '$otherwise'", Nil))
               }
    } yield result
  }

  implicit val migratorConfigDecoder: Decoder[MigratorConfig] = deriveDecoder[MigratorConfig]
  implicit val migratorConfigEncoder: Encoder[MigratorConfig] = deriveEncoder[MigratorConfig]

  def loadFrom(path: String): MigratorConfig = {
    val configData = scala.io.Source.fromFile(path).mkString

    parser
      .parse(configData)
      .leftWiden[Error]
      .flatMap(_.as[MigratorConfig])
      .valueOr(throw _)
  }
}