Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,112 +3,77 @@ package pl.iterators.kebs.baklava.params.enums
import pl.iterators.baklava.{ToHeader, ToPathParam, ToQueryParam}
import pl.iterators.kebs.core.enums.{EnumLike, ValueEnumLike, ValueEnumLikeEntry}

import scala.annotation.unused

trait KebsBaklavaEnumsParams {
implicit def toQueryParamEnum[T](implicit _enum: EnumLike[T]): ToQueryParam[T] = new ToQueryParam[T] {
override def apply(t: T): Seq[String] = {
val _ = _enum // fix warning
Seq(t.toString) // todo use getName with kebs 2.1.0
}
override def apply(t: T): Seq[String] = Seq(_enum.getName(t))
}

implicit def toPathParamEnum[T](implicit _enum: EnumLike[T]): ToPathParam[T] = new ToPathParam[T] {
override def apply(t: T): String = {
val _ = _enum // fix warning
t.toString // todo use getName with kebs 2.1.0
}
override def apply(t: T): String = _enum.getName(t)
}

implicit def toHeaderEnum[T](implicit _enum: EnumLike[T]): ToHeader[T] = new ToHeader[T] {
override def apply(value: T): Option[String] = {
val _ = _enum // fix warning
Some(value.toString) // todo use getName with kebs 2.1.0
}
override def apply(value: T): Option[String] = Some(_enum.getName(value))

override def unapply(value: String): Option[T] = {
val _ = _enum // fix warning
_enum.values.find(_.toString == value)
}
override def unapply(value: String): Option[T] = _enum.withNameOption(value)
}

trait KebsBaklavaEnumsUppercaseParams {
implicit def toQueryParamEnum[T](implicit _enum: EnumLike[T]): ToQueryParam[T] = new ToQueryParam[T] {
override def apply(t: T): Seq[String] = {
val _ = _enum // fix warning
Seq(t.toString.toUpperCase)
}
override def apply(t: T): Seq[String] = Seq(_enum.getName(t).toUpperCase)
}

implicit def toPathParamEnum[T](implicit _enum: EnumLike[T]): ToPathParam[T] = new ToPathParam[T] {
override def apply(t: T): String = {
val _ = _enum // fix warning
t.toString.toUpperCase
}
override def apply(t: T): String = _enum.getName(t).toUpperCase
}

implicit def toHeaderEnum[T](implicit _enum: EnumLike[T]): ToHeader[T] = new ToHeader[T] {
override def apply(value: T): Option[String] = {
val _ = _enum // fix warning
Some(value.toString.toUpperCase)
}

override def unapply(value: String): Option[T] = {
val _ = _enum // fix warning
_enum.values.find(_.toString.toUpperCase == value)
}
override def apply(value: T): Option[String] = Some(_enum.getName(value).toUpperCase)

override def unapply(value: String): Option[T] = _enum.withNameUppercaseOnlyOption(value)
}
}

trait KebsBaklavaEnumsLowercaseParams {
implicit def toQueryParamEnum[T](implicit _enum: EnumLike[T]): ToQueryParam[T] = new ToQueryParam[T] {
override def apply(t: T): Seq[String] = {
val _ = _enum // fix warning
Seq(t.toString.toLowerCase)
}
override def apply(t: T): Seq[String] = Seq(_enum.getName(t).toLowerCase)
}

implicit def toPathParamEnum[T](implicit _enum: EnumLike[T]): ToPathParam[T] = new ToPathParam[T] {
override def apply(t: T): String = {
val _ = _enum // fix warning
t.toString.toLowerCase
}
override def apply(t: T): String = _enum.getName(t).toLowerCase
}

implicit def toHeaderEnum[T](implicit _enum: EnumLike[T]): ToHeader[T] = new ToHeader[T] {
override def apply(value: T): Option[String] = {
val _ = _enum // fix warning
Some(value.toString.toLowerCase)
}

override def unapply(value: String): Option[T] = {
val _ = _enum // fix warning
_enum.values.find(_.toString.toLowerCase == value)
}
override def apply(value: T): Option[String] = Some(_enum.getName(value).toLowerCase)

override def unapply(value: String): Option[T] = _enum.withNameLowercaseOnlyOption(value)
}
}
}

trait KebsBaklavaValueEnumsParams {
implicit def toQueryParamValueEnum[T, V <: ValueEnumLikeEntry[T]](implicit
valueEnumLike: ValueEnumLike[T, V],
implicit def toQueryParamValueEnum[V, E <: ValueEnumLikeEntry[V]](implicit
@unused valueEnumLike: ValueEnumLike[V, E],
tsm: ToQueryParam[V]
): ToQueryParam[T] = new ToQueryParam[T] {
override def apply(t: T): Seq[String] = tsm(valueEnumLike.valueOf(t))
): ToQueryParam[E] = new ToQueryParam[E] {
override def apply(e: E): Seq[String] = tsm(e.value)
}

implicit def toPathParamValueEnum[T, V <: ValueEnumLikeEntry[T]](implicit
valueEnumLike: ValueEnumLike[T, V],
implicit def toPathParamValueEnum[V, E <: ValueEnumLikeEntry[V]](implicit
@unused valueEnumLike: ValueEnumLike[V, E],
tsm: ToPathParam[V]
): ToPathParam[T] = new ToPathParam[T] {
override def apply(t: T): String = tsm(valueEnumLike.valueOf(t))
): ToPathParam[E] = new ToPathParam[E] {
override def apply(e: E): String = tsm(e.value)
}

implicit def toHeaderValueEnum[T, V <: ValueEnumLikeEntry[T]](implicit
valueEnumLike: ValueEnumLike[T, V],
implicit def toHeaderValueEnum[V, E <: ValueEnumLikeEntry[V]](implicit
valueEnumLike: ValueEnumLike[V, E],
tsm: ToHeader[V]
): ToHeader[T] = new ToHeader[T] {
override def apply(value: T): Option[String] = tsm(valueEnumLike.valueOf(value))
): ToHeader[E] = new ToHeader[E] {
override def apply(e: E): Option[String] = tsm(e.value)

override def unapply(value: String): Option[T] =
tsm.unapply(value).flatMap(v => valueEnumLike.getValuesToEntriesMap.toList.find(_._2 == v).map(_._1))
override def unapply(value: String): Option[E] = tsm.unapply(value).flatMap(valueEnumLike.withValueOption)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@ trait KebsBaklavaSchema {
cls: ClassTag[T]
): Schema[T] = {
new Schema[T] {
val className: String = cls.runtimeClass.getName // TODO: this won't capture opaque type's name.
val `type`: SchemaType = schema.`type`
val format: Option[String] = schema.format
val properties: Map[String, Schema[?]] = schema.properties
val items: Option[Schema[?]] = schema.items
val `enum`: Option[Set[String]] = schema.`enum`
val required: Boolean = schema.required
val additionalProperties: Boolean = schema.additionalProperties
val default: Option[T] = schema.default.map(valueClassLike.apply)
val description: Option[String] = schema.description
val className: String = cls.runtimeClass.getName // TODO: this won't capture opaque type's name.
val `type`: SchemaType = schema.`type`
val format: Option[String] = schema.format
val properties: Map[String, Schema[?]] = schema.properties
val items: Option[Schema[?]] = schema.items
val `enum`: Option[Set[String]] = schema.`enum`
val required: Boolean = schema.required
val additionalProperties: Boolean = schema.additionalProperties
override val additionalPropertiesSchema: Option[Schema[?]] = schema.additionalPropertiesSchema
val default: Option[T] = schema.default.map(valueClassLike.apply)
val description: Option[String] = schema.description
}
}

Expand All @@ -42,13 +43,14 @@ trait KebsBaklavaSchema {
case "java.util.UUID" => Some("uuid")
case _ => schema.format
}
val properties: Map[String, Schema[?]] = schema.properties
val items: Option[Schema[?]] = schema.items
val `enum`: Option[Set[String]] = schema.`enum`
val required: Boolean = schema.required
val additionalProperties: Boolean = schema.additionalProperties
val default: Option[T] = schema.default.map(instanceConverter.decode)
val description: Option[String] = schema.description
val properties: Map[String, Schema[?]] = schema.properties
val items: Option[Schema[?]] = schema.items
val `enum`: Option[Set[String]] = schema.`enum`
val required: Boolean = schema.required
val additionalProperties: Boolean = schema.additionalProperties
override val additionalPropertiesSchema: Option[Schema[?]] = schema.additionalPropertiesSchema
val default: Option[T] = schema.default.map(instanceConverter.decode)
val description: Option[String] = schema.description
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ trait KebsBaklavaEnumsSchema {
val format: Option[String] = None
val properties: Map[String, Schema[?]] = Map.empty
val items: Option[Schema[?]] = None
val `enum`: Option[Set[String]] = Some(enumLike.values.map(_.toString).toSet)
val `enum`: Option[Set[String]] = Some(enumLike.names.toSet)
val required: Boolean = true
val additionalProperties: Boolean = false
val default: Option[T] = None
Expand All @@ -28,7 +28,7 @@ trait KebsBaklavaEnumsSchema {
val format: Option[String] = None
val properties: Map[String, Schema[?]] = Map.empty
val items: Option[Schema[?]] = None
val `enum`: Option[Set[String]] = Some(enumLike.values.map(_.toString.toUpperCase).toSet)
val `enum`: Option[Set[String]] = Some(enumLike.names.map(_.toUpperCase).toSet)
val required: Boolean = true
val additionalProperties: Boolean = false
val default: Option[T] = None
Expand All @@ -44,7 +44,7 @@ trait KebsBaklavaEnumsSchema {
val format: Option[String] = None
val properties: Map[String, Schema[?]] = Map.empty
val items: Option[Schema[?]] = None
val `enum`: Option[Set[String]] = Some(enumLike.values.map(_.toString.toLowerCase).toSet)
val `enum`: Option[Set[String]] = Some(enumLike.names.map(_.toLowerCase).toSet)
val required: Boolean = true
val additionalProperties: Boolean = false
val default: Option[T] = None
Expand All @@ -54,21 +54,21 @@ trait KebsBaklavaEnumsSchema {
}

trait KebsBaklavaValueEnumsSchema {
implicit def valueEnumLikeSchema[T, V <: ValueEnumLikeEntry[T]](implicit
valueEnumLike: ValueEnumLike[T, V],
implicit def valueEnumLikeSchema[V, E <: ValueEnumLikeEntry[V]](implicit
valueEnumLike: ValueEnumLike[V, E],
schema: Schema[V],
cls: ClassTag[T]
): Schema[T] = {
new Schema[T] {
cls: ClassTag[E]
): Schema[E] = {
new Schema[E] {
val className: String = cls.runtimeClass.getName
val `type`: SchemaType = schema.`type`
val format: Option[String] = schema.format
val properties: Map[String, Schema[?]] = schema.properties
val items: Option[Schema[?]] = schema.items
val `enum`: Option[Set[String]] = Some(valueEnumLike.values.map(_.toString).toSet)
val `enum`: Option[Set[String]] = Some(valueEnumLike.values.map(_.value.toString).toSet)
val required: Boolean = schema.required
val additionalProperties: Boolean = schema.additionalProperties
val default: Option[T] = None
val default: Option[E] = None
val description: Option[String] = schema.description
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package pl.iterators.kebs.baklava

import enumeratum.values.{IntEnum, IntEnumEntry}
import enumeratum.{Enum, EnumEntry}
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers
import pl.iterators.baklava._
import pl.iterators.kebs.core.enums.ValueEnumLikeEntry
import pl.iterators.kebs.enumeratum.{KebsEnumeratum, KebsValueEnumeratum}

object BaklavaEnumsTests {
sealed trait Status extends EnumEntry
object Status extends Enum[Status] {
case object Active extends Status { override val entryName = "is-active" }
case object Inactive extends Status
val values = findValues
}

sealed abstract class Level(val value: Int) extends IntEnumEntry with ValueEnumLikeEntry[Int]
object Level extends IntEnum[Level] {
case object Low extends Level(1)
case object High extends Level(10)
val values = findValues
}

object BaklavaInstances extends BaklavaQueryParams with BaklavaPathParams with BaklavaHeaders
}

class BaklavaEnumsTests extends AnyFunSuite with Matchers with KebsEnumeratum with KebsValueEnumeratum {
import BaklavaEnumsTests._
import BaklavaInstances._

test("enum schema and params use entryName") {
import pl.iterators.kebs.baklava.params.enums._
import pl.iterators.kebs.baklava.schema.enums._

val schema = implicitly[Schema[Status]]
schema.className shouldBe classOf[Status].getName
schema.`type` shouldBe SchemaType.StringType
schema.format shouldBe None
schema.`enum` shouldBe Some(Set("is-active", "Inactive"))
schema.required shouldBe true
schema.default shouldBe None
implicitly[ToHeader[Status]].unapply("Active") shouldBe None
implicitly[ToQueryParam[Status]].apply(Status.Active) shouldBe Seq("is-active")
implicitly[ToPathParam[Status]].apply(Status.Active) shouldBe "is-active"
implicitly[ToHeader[Status]].apply(Status.Active) shouldBe Some("is-active")
implicitly[ToHeader[Status]].unapply("is-active") shouldBe Some(Status.Active)
}

test("enum schema and params use entryName - uppercase") {
import pl.iterators.kebs.baklava.params.enums.uppercase._
import pl.iterators.kebs.baklava.schema.enums.uppercase._

implicitly[Schema[Status]].`enum` shouldBe Some(Set("IS-ACTIVE", "INACTIVE"))
implicitly[ToQueryParam[Status]].apply(Status.Active) shouldBe Seq("IS-ACTIVE")
implicitly[ToPathParam[Status]].apply(Status.Active) shouldBe "IS-ACTIVE"
implicitly[ToHeader[Status]].apply(Status.Active) shouldBe Some("IS-ACTIVE")
implicitly[ToHeader[Status]].unapply("IS-ACTIVE") shouldBe Some(Status.Active)
}

test("enum schema and params use entryName - lowercase") {
import pl.iterators.kebs.baklava.params.enums.lowercase._
import pl.iterators.kebs.baklava.schema.enums.lowercase._

implicitly[Schema[Status]].`enum` shouldBe Some(Set("is-active", "inactive"))
implicitly[ToQueryParam[Status]].apply(Status.Inactive) shouldBe Seq("inactive")
implicitly[ToPathParam[Status]].apply(Status.Inactive) shouldBe "inactive"
implicitly[ToHeader[Status]].apply(Status.Inactive) shouldBe Some("inactive")
implicitly[ToHeader[Status]].unapply("inactive") shouldBe Some(Status.Inactive)
}

test("value enum schema uses the value type and values") {
import pl.iterators.kebs.baklava.schema.enums._

val schema = implicitly[Schema[Level]]
schema.className shouldBe classOf[Level].getName
schema.`type` shouldBe SchemaType.IntegerType
schema.format shouldBe Some("int32")
schema.`enum` shouldBe Some(Set("1", "10"))
schema.default shouldBe None
}

test("value enum schema keeps the value type description") {
import pl.iterators.kebs.baklava.schema.enums._

val schema = valueEnumLikeSchema[Int, Level](implicitly, Schema.intSchema.withDescription("a level"), implicitly)
schema.description shouldBe Some("a level")
}

test("value enum params use values") {
import pl.iterators.kebs.baklava.params.enums._

implicitly[ToQueryParam[Level]].apply(Level.High) shouldBe Seq("10")
implicitly[ToPathParam[Level]].apply(Level.Low) shouldBe "1"
implicitly[ToHeader[Level]].apply(Level.High) shouldBe Some("10")
implicitly[ToHeader[Level]].unapply("10") shouldBe Some(Level.High)
implicitly[ToHeader[Level]].unapply("5") shouldBe None
}

test("value enum instances don't apply to the value type") {
import pl.iterators.kebs.baklava.schema.enums._

implicitly[Schema[Int]].`enum` shouldBe None
}
}
Loading
Loading