spray.json.DeserializationException Scala Examples

The following examples show how to use spray.json.DeserializationException. 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: VolumeRoute.scala    From ohara   with Apache License 2.0 5 votes vote down vote up
package oharastream.ohara.configurator.route

import akka.http.scaladsl.server
import oharastream.ohara.client.configurator.VolumeApi
import oharastream.ohara.client.configurator.VolumeApi.{Creation, Updating, Volume}
import oharastream.ohara.common.util.CommonUtils
import oharastream.ohara.configurator.store.DataStore
import spray.json.DeserializationException

import scala.concurrent.{ExecutionContext, Future}

private[configurator] object VolumeRoute {
  private[this] def toVolume(creation: Creation): Future[Volume] =
    Future.successful(
      Volume(
        group = creation.group,
        name = creation.name,
        nodeNames = creation.nodeNames,
        path = creation.path,
        state = None,
        error = None,
        tags = creation.tags,
        lastModified = CommonUtils.current()
      )
    )

  def apply(implicit store: DataStore, executionContext: ExecutionContext): server.Route =
    RouteBuilder[Creation, Updating, Volume]()
      .prefixOfPlural("volumes")
      .prefixOfSingular(VolumeApi.KIND)
      .hookOfCreation(toVolume)
      .hookOfUpdating(
        (key, updating, previousOption) =>
          toVolume(previousOption match {
            case None =>
              if (updating.nodeNames.isEmpty)
                throw DeserializationException("nodeNames is required", fieldNames = List("nodeNames"))
              if (updating.path.isEmpty) throw DeserializationException("path is required", fieldNames = List("path"))
              Creation(
                group = key.group(),
                name = key.name(),
                nodeNames = updating.nodeNames.get,
                path = updating.path.get,
                tags = updating.tags.getOrElse(Map.empty)
              )
            case Some(previous) =>
              Creation(
                group = key.group(),
                name = key.name(),
                nodeNames = updating.nodeNames.getOrElse(previous.nodeNames),
                path = updating.path.getOrElse(previous.path),
                tags = updating.tags.getOrElse(previous.tags)
              )
          })
      )
      .hookOfGet(Future.successful(_))
      .hookOfList(Future.successful(_))
      .hookBeforeDelete(_ => Future.unit)
      .build()
} 
Example 2
Source File: TestClusterNameUpperCaseRoute.scala    From ohara   with Apache License 2.0 5 votes vote down vote up
package oharastream.ohara.configurator.route

import oharastream.ohara.client.configurator.{NodeApi, ZookeeperApi}
import oharastream.ohara.common.rule.OharaTest
import oharastream.ohara.common.util.{CommonUtils, Releasable}
import oharastream.ohara.configurator.Configurator
import org.junit.{After, Test}
import org.scalatest.matchers.should.Matchers._
import spray.json.DeserializationException

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}

class TestClusterNameUpperCaseRoute extends OharaTest {
  private[this] val numberOfCluster = 1
  private[this] val configurator =
    Configurator.builder.fake(numberOfCluster, numberOfCluster, "zk").build()
  private[this] val nodeApi      = NodeApi.access.hostname(configurator.hostname).port(configurator.port)
  private[this] val zookeeperApi = ZookeeperApi.access.hostname(configurator.hostname).port(configurator.port)

  private[this] def result[T](f: Future[T]): T = Await.result(f, Duration("20 seconds"))
  @Test
  def testAddZookeeper(): Unit = {
    result(nodeApi.request.nodeName("host1").port(22).user("b").password("c").create())

    an[DeserializationException] should be thrownBy result(
      zookeeperApi.request.name(s"ZK-${CommonUtils.randomString(10)}").nodeName("host1").create()
    )
  }

  @After
  def tearDown(): Unit = Releasable.close(configurator)
} 
Example 3
Source File: UnmarshallersTest.scala    From JustinDB   with Apache License 2.0 5 votes vote down vote up
package justin.httpapi

import java.util.UUID

import org.scalatest.{FlatSpec, Matchers}
import spray.json.{DeserializationException, JsNumber, JsString}

class UnmarshallersTest extends FlatSpec with Matchers {

  behavior of "Unmarshaller"

  it should "encode JSON into UUID" in {
    val uuid = UUID.randomUUID()
    val jsString = JsString(uuid.toString)

    Unmarshallers.UuidFormat.read(jsString) shouldBe uuid
  }

  it should "decode UUID into JSON" in {
    val uuid = UUID.randomUUID()
    val expectedJSON = Unmarshallers.UuidFormat.write(uuid)

    expectedJSON shouldBe JsString(uuid.toString)
  }

  it should "handle not expected format of JSON" in {
    val jsNumber = JsNumber(1)

    intercept[DeserializationException] {
      Unmarshallers.UuidFormat.read(jsNumber)
    }
  }

  it should "handle wrong format of UUID" in {
    val fakeUUID = "1-2-3-4"
    val jsString = JsString(fakeUUID)

    intercept[DeserializationException] {
      Unmarshallers.UuidFormat.read(jsString)
    }
  }
} 
Example 4
Source File: Privilege.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.entitlement

import scala.util.Try

import spray.json.DeserializationException
import spray.json.JsString
import spray.json.JsValue
import spray.json.RootJsonFormat

sealed trait Privilege


protected[core] object Privilege extends Enumeration {

  case object READ extends Privilege
  case object PUT extends Privilege
  case object DELETE extends Privilege
  case object ACTIVATE extends Privilege
  case object REJECT extends Privilege

  val CRUD: Set[Privilege] = Set(READ, PUT, DELETE)
  val ALL: Set[Privilege] = CRUD + ACTIVATE

  def fromName(name: String) = name match {
    case "READ"     => READ
    case "PUT"      => PUT
    case "DELETE"   => DELETE
    case "ACTIVATE" => ACTIVATE
    case "REJECT"   => REJECT
  }

  implicit val serdes = new RootJsonFormat[Privilege] {
    def write(p: Privilege) = JsString(p.toString)

    def read(json: JsValue) =
      Try {
        val JsString(str) = json
        Privilege.fromName(str.trim.toUpperCase)
      } getOrElse {
        throw new DeserializationException("Privilege must be a valid string")
      }
  }
} 
Example 5
Source File: CodeCommit.scala    From cloudformation-template-generator   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package com.monsanto.arch.cloudformation.model.resource

import com.monsanto.arch.cloudformation.model.Token.TokenSeq
import com.monsanto.arch.cloudformation.model._
import spray.json.DefaultJsonProtocol._
import spray.json.{ DeserializationException, JsString, JsValue, JsonFormat, RootJsonFormat }

sealed trait CodeCommitEvent extends Product with Serializable

object CodeCommitEvent {
  private type T = CodeCommitEvent
  case object all extends T
  case object updateReference extends T
  case object createReference extends T
  case object deleteReference extends T
  implicit lazy val format: JsonFormat[T] = new JsonFormat[T] {
    def write(t: T): JsValue = JsString(t.toString)
    def read(json: JsValue): T = json match {
      case JsString("all") => all
      case JsString("updateReference") => updateReference
      case JsString("createReference") => createReference
      case JsString("deleteReference") => deleteReference
      case _ => throw DeserializationException(s"Can't parse as CodeCommitEvent: $json")
    }
  }
}

case class CodeCommitTrigger(
                              Branches: Option[TokenSeq[String]] = None,
                              CustomData: Option[String] = None,
                              DestinationArn: Option[Token[String]] = None,
                              Events: Option[Seq[CodeCommitEvent]] = None,
                              Name: String
                            )
object CodeCommitTrigger {
  private type T = CodeCommitTrigger
  implicit lazy val format: JsonFormat[T] = jsonFormat5(apply)
}

case class `AWS::CodeCommit::Repository`(
                                          name: String,
                                          RepositoryName: String,
                                          RepositoryDescription: Option[String] = None,
                                          Triggers: Option[Seq[CodeCommitTrigger]] = None,
                                          override val Condition: Option[ConditionRef] = None,
                                          override val DependsOn: Option[Seq[String]] = None
                                        ) extends Resource[`AWS::CodeCommit::Repository`] {
  override def when(newCondition: Option[ConditionRef]): `AWS::CodeCommit::Repository` = copy(Condition = newCondition)
}

object `AWS::CodeCommit::Repository` {
  implicit lazy val format : RootJsonFormat[`AWS::CodeCommit::Repository`] = jsonFormat6(apply)
} 
Example 6
Source File: FileEntry.scala    From seahorse   with Apache License 2.0 5 votes vote down vote up
package ai.deepsense.libraryservice

import java.io.File

import spray.json.{DefaultJsonProtocol, DeserializationException, JsString, JsValue, JsonFormat}
import ai.deepsense.commons.json.EnumerationSerializer._

case class FileEntry private[libraryservice] ( name: String,
                                               kind: FileType.Value,
                                               children: Seq[FileEntry])

object FileEntry {
  def fromFile(file: java.io.File): FileEntry = {
    FileEntry(file.getName, FileType.File, Nil)
  }

  def fromDirectory(directory: java.io.File): FileEntry = {
    val sortedFiles = directory.listFiles.sortBy(f => (f.isFile, f.getName))
    val children = sortedFiles.map(fileToFileEntry)
    FileEntry(directory.getName, FileType.Directory, children)
  }

  def fileToFileEntry(f: File): FileEntry = {
    if (f.isFile) {
      fromFile(f)
    } else {
      fromDirectory(f)
    }
  }
}

object FileType extends Enumeration {
  val File = Value("file")
  val Directory = Value("directory")

  implicit val fileTypeJsonFormat = jsonEnumFormat(FileType)
}

object FileEntryJsonProtocol extends DefaultJsonProtocol {
  implicit val fileEntryJsonFormat: JsonFormat[FileEntry] =
    lazyFormat(jsonFormat3(FileEntry.apply))
} 
Example 7
Source File: AbstractChoiceParamSpec.scala    From seahorse   with Apache License 2.0 5 votes vote down vote up
package ai.deepsense.deeplang.params.choice

import scala.reflect.runtime.universe._

import spray.json.{DeserializationException, JsObject}

import ai.deepsense.deeplang.params.exceptions.NoArgumentConstructorRequiredException
import ai.deepsense.deeplang.params.{AbstractParamSpec, Param}
import ai.deepsense.models.json.graph.GraphJsonProtocol.GraphReader

abstract class AbstractChoiceParamSpec[T, U <: Param[T]] extends AbstractParamSpec[T, U] {

  protected def createChoiceParam[V <: Choice : TypeTag](
    name: String, description: String): Param[V]

  className should {
    "throw an exception when choices don't have no-arg constructor" in {
      a[NoArgumentConstructorRequiredException] should be thrownBy
        createChoiceParam[BaseChoice]("name", "description")
    }
    "throw an exception when unsupported choice is given" in {
      val graphReader = mock[GraphReader]
      a[DeserializationException] should be thrownBy
        createChoiceParam[ChoiceABC]("name", "description").valueFromJson(
          JsObject(
            "unsupportedClass" -> JsObject()
          ),
          graphReader
        )
    }
    "throw an exception when not all choices are declared" in {
      an[IllegalArgumentException] should be thrownBy
        createChoiceParam[ChoiceWithoutDeclaration]("name", "description")
    }
  }
} 
Example 8
Source File: AsyncInterface.scala    From mist   with Apache License 2.0 5 votes vote down vote up
package io.hydrosphere.mist.master.interfaces.async

import io.hydrosphere.mist.master.JobDetails.Source
import io.hydrosphere.mist.master.MainService
import io.hydrosphere.mist.master.interfaces.JsonCodecs._
import io.hydrosphere.mist.master.models._
import io.hydrosphere.mist.utils.Logger
import spray.json.{DeserializationException, JsValue, JsonParser}
import spray.json.enrichString

import scala.util.{Failure, Success, Try}

class AsyncInterface(
  mainService: MainService,
  input: AsyncInput,
  val name: String
) extends Logger {

  private val source = Source.Async(name)

  def start(): this.type  = {
    input.start(process)
    this
  }

  private def process(message: String): Unit = {
    def asFunctionRequest(js: JsValue) = js.convertTo[AsyncFunctionStartRequest]
    def asDevRequest(js: JsValue) = js.convertTo[DevJobStartRequestModel]

    try {
      val js = message.parseJson

      Try[Any](asDevRequest(js)).orElse(Try(asFunctionRequest(js))) match {
        case Success(req: AsyncFunctionStartRequest) =>
          mainService.runJob(req.toCommon, source)
        case Success(req: DevJobStartRequestModel) =>
          mainService.devRun(req.toCommon, source)
        case Success(x) => throw new IllegalArgumentException("Unknown request type")
        case Failure(e) => throw e
      }
    } catch {
      case e: DeserializationException =>
        logger.warn(s"Message $message does not conform with start request")
      case e: JsonParser.ParsingException =>
        logger.warn(s"Handled invalid message $message")
      case e: Throwable =>
        logger.error(s"Error occurred during handling message $message", e)
    }
  }


  def close(): Unit = input.close()

} 
Example 9
Source File: EchoEnumService.scala    From swagger-akka-http-sample   with Apache License 2.0 5 votes vote down vote up
package com.example.akka.echoenum

import akka.http.scaladsl.server.{Directives, Route}
import com.example.akka.DefaultJsonFormats
import com.fasterxml.jackson.core.`type`.TypeReference
import com.fasterxml.jackson.module.scala.JsonScalaEnumeration
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.{Content, Schema}
import io.swagger.v3.oas.annotations.parameters.RequestBody
import io.swagger.v3.oas.annotations.responses.ApiResponse
import javax.ws.rs.core.MediaType
import javax.ws.rs.{Consumes, POST, Path, Produces}
import spray.json.{DeserializationException, JsString, JsValue, RootJsonFormat}

@Path("/echoenum")
object EchoEnumService extends Directives with DefaultJsonFormats {

  //case class EchoEnum(@Schema(required = true, `type` = "string", allowableValues = Array("TALL", "GRANDE", "VENTI"))
  //                    enumValue: SizeEnum.Value)
  class SizeEnumTypeClass extends TypeReference[SizeEnum.type]
  case class EchoEnum(@JsonScalaEnumeration(classOf[SizeEnumTypeClass]) enumValue: SizeEnum.Value)

  implicit val enumFormat: RootJsonFormat[SizeEnum.Value] =
    new RootJsonFormat[SizeEnum.Value] {
      def write(obj: SizeEnum.Value): JsValue = JsString(obj.toString)
      def read(json: JsValue): SizeEnum.Value = {
        json match {
          case JsString(txt) => SizeEnum.withName(txt)
          case somethingElse => throw DeserializationException(s"Expected a value from enum $SizeEnum instead of $somethingElse")
        }
      }
    }
  implicit val echoEnumFormat: RootJsonFormat[EchoEnum] = jsonFormat1(EchoEnum)

  val route: Route = echo

  @POST
  @Consumes(Array(MediaType.APPLICATION_JSON))
  @Produces(Array(MediaType.APPLICATION_JSON))
  @Operation(summary = "Echo Enum", description = "Echo Enum",
    requestBody = new RequestBody(content = Array(new Content(schema = new Schema(implementation = classOf[EchoEnum])))),
    responses = Array(
      new ApiResponse(responseCode = "200", description = "Echo Enum",
        content = Array(new Content(schema = new Schema(implementation = classOf[EchoEnum])))),
      new ApiResponse(responseCode = "400", description = "Bad Request"))
  )
  def echo: Route =
    path("echoenum") {
      post {
        entity(as[EchoEnum]) { request =>
          complete(request)
        }
      }
    }

} 
Example 10
Source File: VwMultilabelModelPluginJsonReader.scala    From aloha   with MIT License 5 votes vote down vote up
package com.eharmony.aloha.models.vw.jni.multilabel.json

import com.eharmony.aloha.dataset.vw.multilabel.VwMultilabelRowCreator.{LabelNamespaces, determineLabelNamespaces}
import com.eharmony.aloha.models.multilabel.SparsePredictorProducer
import com.eharmony.aloha.models.vw.jni.Namespaces
import com.eharmony.aloha.models.vw.jni.multilabel.VwSparseMultilabelPredictorProducer
import com.eharmony.aloha.util.Logging
import spray.json.{DeserializationException, JsValue, JsonReader}

import scala.collection.breakOut
import scala.collection.immutable.ListMap


case class VwMultilabelModelPluginJsonReader[K](featureNames: Seq[String], numLabelsInTrainingSet: Int)
   extends JsonReader[SparsePredictorProducer[K]]
      with VwMultilabelModelJson
      with Namespaces
      with Logging {

  import VwMultilabelModelPluginJsonReader._

  override def read(json: JsValue): VwSparseMultilabelPredictorProducer[K] = {
    val ast = json.asJsObject(notObjErr(json)).convertTo[VwMultilabelAst]
    val (namespaces, defaultNs, missing) =
      allNamespaceIndices(featureNames, ast.namespaces.getOrElse(ListMap.empty))

    if (missing.nonEmpty)
      info(s"features in namespaces not found in featureNames: $missing")

    val namespaceNames: Set[String] = namespaces.map(_._1)(breakOut)
    val labelAndDummyLabelNss = determineLabelNamespaces(namespaceNames)

    labelAndDummyLabelNss match {
      case Some(LabelNamespaces(labelNs, _)) =>
        VwSparseMultilabelPredictorProducer[K](ast.modelSource, defaultNs, namespaces, labelNs, numLabelsInTrainingSet)
      case _ =>
        throw new DeserializationException(
          "Could not determine label namespace.  Found namespaces: " +
            namespaceNames.mkString(", ")
        )
    }
  }
}

object VwMultilabelModelPluginJsonReader extends Logging {
  private val JsonErrStrLength = 100

  private[multilabel] def notObjErr(json: JsValue): String = {
    val str = json.prettyPrint
    val substr = str.substring(0, JsonErrStrLength)
    s"JSON object expected.  Found " + substr + (if (str.length != substr.length) " ..." else "")
  }
} 
Example 11
Source File: ErrorModel.scala    From aloha   with MIT License 5 votes vote down vote up
package com.eharmony.aloha.models

import com.eharmony.aloha.audit.Auditor
import com.eharmony.aloha.factory._
import com.eharmony.aloha.factory.jsext.JsValueExtensions
import com.eharmony.aloha.id.ModelIdentity
import com.eharmony.aloha.reflect.RefInfo
import com.eharmony.aloha.semantics.Semantics
import spray.json.{DeserializationException, JsValue, JsonFormat, JsonReader}


case class ErrorModel[U, +B <: U](modelId: ModelIdentity, errors: Seq[String], auditor: Auditor[U, Nothing, B]) extends SubmodelBase[U, Nothing, Any, B] {
  def subvalue(a: Any): Subvalue[B, Nothing] = failure(errors, Set.empty)
  override def toString(): String = "ErrorModel(" + modelId + "," + errors + ")"
}

object ErrorModel extends ParserProviderCompanion {
  object Parser extends ModelSubmodelParsingPlugin {
    val modelType = "Error"
    private[this] val errorField = "errors"

    override def commonJsonReader[U, N, A, B <: U](
        factory: SubmodelFactory[U, A],
        semantics: Semantics[A],
        auditor: Auditor[U, N, B])
       (implicit r: RefInfo[N], jf: JsonFormat[N]): Option[JsonReader[ErrorModel[U, B]]] = {

      Some(new JsonReader[ErrorModel[U, B]] {
        def read(json: JsValue): ErrorModel[U, B] = {
          val model = for {
            errors <- json.sa(errorField) orElse { Option(Seq("Error with unspecified reason.")) }
            mId <- getModelId(json)
          } yield ErrorModel(mId, errors, auditor)

          model getOrElse { throw new DeserializationException("") }
        }
      })
    }
  }

  def parser: ModelParser = Parser
} 
Example 12
Source File: ConstantModel.scala    From aloha   with MIT License 5 votes vote down vote up
package com.eharmony.aloha.models


import com.eharmony.aloha.audit.Auditor
import com.eharmony.aloha.factory._
import com.eharmony.aloha.factory.jsext.JsValueExtensions
import com.eharmony.aloha.id.ModelIdentity
import com.eharmony.aloha.reflect.RefInfo
import com.eharmony.aloha.semantics.Semantics
import spray.json.DefaultJsonProtocol.optionFormat
import spray.json.{DeserializationException, JsValue, JsonFormat, JsonReader}

case class ConstantModel[U, N, +B <: U](
    constant: Option[N],
    modelId: ModelIdentity,
    auditor: Auditor[U, N, B]
) extends SubmodelBase[U, N, Any, B] {
  def subvalue(a: Any): Subvalue[B, N] =
    constant.map(n => success(n))
            .getOrElse(failure(Seq("No constant supplied"), Set.empty))
}

object ConstantModel extends ParserProviderCompanion {
  object Parser extends ModelSubmodelParsingPlugin {
    val modelType = "Constant"
    private val valueField = "value"

    override def commonJsonReader[U, N, A, B <: U](
        factory: SubmodelFactory[U, A],
        semantics: Semantics[A],
        auditor: Auditor[U, N, B])
       (implicit r: RefInfo[N], jf: JsonFormat[N]): Option[JsonReader[ConstantModel[U, N, B]]] = {

      Some(new JsonReader[ConstantModel[U, N, B]] {
        override def read(json: JsValue): ConstantModel[U, N, B] = {
          val model = for {
            jsV <- json(valueField)
            mId <- getModelId(json)
            v = jsV.convertTo[Option[N]]
            m = new ConstantModel(v, mId, auditor)
          } yield m

          model getOrElse { throw new DeserializationException("") }
        }
      })
    }
  }

  def parser: ModelParser = Parser
} 
Example 13
Source File: CloserTesterModel.scala    From aloha   with MIT License 5 votes vote down vote up
package com.eharmony.aloha.models

import java.util.concurrent.atomic.AtomicBoolean

import com.eharmony.aloha.audit.Auditor
import com.eharmony.aloha.ex.SchrodingerException
import com.eharmony.aloha.factory.{ModelSubmodelParsingPlugin, ModelParser, ParserProviderCompanion, SubmodelFactory}
import com.eharmony.aloha.id.ModelIdentity
import com.eharmony.aloha.reflect.RefInfo
import com.eharmony.aloha.semantics.Semantics
import spray.json.{DeserializationException, JsValue, JsonFormat, JsonReader}
import spray.json.DefaultJsonProtocol.{BooleanJsonFormat, optionFormat}
import com.eharmony.aloha.factory.jsext.JsValueExtensions


case class CloserTesterModel[U, N, +B <: U](modelId: ModelIdentity, auditor: Auditor[U, N, B], shouldThrowOnClose: Boolean = false)
   extends Model[Any, B]
      with Submodel[N, Any, B] {

  private[this] val closed = new AtomicBoolean(false)
  def isClosed: Boolean = closed.get()
  override def apply(a: Any): B = throw new UnsupportedOperationException
  override def subvalue(a: Any): Subvalue[B, N] = throw new UnsupportedOperationException
  override def close(): Unit = {
    closed.set(true)
    if (shouldThrowOnClose)
      throw new SchrodingerException
  }
}

object CloserTesterModel extends ParserProviderCompanion {
  object Parser extends ModelSubmodelParsingPlugin {
    val modelType = "CloserTester"
    private val shouldThrowField = "shouldThrow"

    override def commonJsonReader[U, N, A, B <: U](
        factory: SubmodelFactory[U, A],
        semantics: Semantics[A],
        auditor: Auditor[U, N, B])
       (implicit r: RefInfo[N], jf: JsonFormat[N]): Option[JsonReader[CloserTesterModel[U, N, B]]] = {

      Some(new JsonReader[CloserTesterModel[U, N, B]] {
        override def read(json: JsValue): CloserTesterModel[U, N, B] = {
          val model = getModelId(json) map { id =>
            val shouldThrow = json(shouldThrowField).flatMap(st => st.convertTo[Option[Boolean]]) getOrElse false
            new CloserTesterModel(id, auditor, shouldThrow)
          }
          model getOrElse { throw new DeserializationException("Couldn't get model ID for CloserTester model.") }
        }
      })
    }
  }

  def parser: ModelParser = Parser
} 
Example 14
Source File: AbstractChoiceParamSpec.scala    From seahorse-workflow-executor   with Apache License 2.0 5 votes vote down vote up
package io.deepsense.deeplang.params.choice

import scala.reflect.runtime.universe._

import spray.json.{DeserializationException, JsObject}

import io.deepsense.deeplang.params.exceptions.NoArgumentConstructorRequiredException
import io.deepsense.deeplang.params.{AbstractParamSpec, Param}

abstract class AbstractChoiceParamSpec[T, U <: Param[T]] extends AbstractParamSpec[T, U] {

  protected def createChoiceParam[V <: Choice : TypeTag](
    name: String, description: String): Param[V]

  className should {
    "throw an exception when choices don't have no-arg constructor" in {
      a[NoArgumentConstructorRequiredException] should be thrownBy
        createChoiceParam[BaseChoice]("name", "description")
    }
    "throw an exception when unsupported choice is given" in {
      a[DeserializationException] should be thrownBy
        createChoiceParam[ChoiceABC]("name", "description").valueFromJson(
          JsObject(
            "unsupportedClass" -> JsObject()
          )
        )
    }
    "throw an exception when not all choices are declared" in {
      an[IllegalArgumentException] should be thrownBy
        createChoiceParam[ChoiceWithoutDeclaration]("name", "description")
    }
  }
}