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

de.leanovate.swaggercheck.shrinkable.CheckJsObject.scala Maven / Gradle / Ivy

package de.leanovate.swaggercheck.shrinkable

import com.fasterxml.jackson.core.JsonGenerator
import org.scalacheck.Shrink

import scala.collection.immutable.Stream._

/**
  * Json object.
  *
  * @param required optional set of required fields for shrinking
  * @param order optional order of fields
  * @param fields the fields of the object
  */
case class CheckJsObject(
                          required: Set[String],
                          order: Option[Seq[String]],
                          fields: Map[String, CheckJsValue]
                        ) extends CheckJsValue {
  override def generate(json: JsonGenerator): Unit = {
    json.writeStartObject()
    order match {
      case Some(fieldNames) => fieldNames.foreach {
        name =>
          fields.get(name).foreach {
            value =>
              json.writeFieldName(name)
              value.generate(json)
          }
      }
      case None =>
        fields.foreach {
          case (key, value) =>
            json.writeFieldName(key)
            value.generate(json)
        }
    }
    json.writeEndObject()
  }

  override def shrink: Stream[CheckJsObject] = {
    removeChunks(fields.keySet -- required).map {
      removeFields =>
        CheckJsObject(required, order, fields -- removeFields)
    }.append(shrinkOne(fields))
  }

  def removeChunks(names: Traversable[String]): Stream[Traversable[String]] = {
    if (names.isEmpty)
      empty
    else if (names.tail.isEmpty)
      Stream(names)
    else {
      val half = names.size / 2
      val left = names.take(half)
      val right = names.drop(half)

      cons(names, removeChunks(left).append(removeChunks(right)))
    }
  }

  private def shrinkOne(remaining: Map[String, CheckJsValue]): Stream[CheckJsObject] =
    if (remaining.isEmpty)
      empty
    else {
      val head = remaining.head
      val tail = remaining.tail

      val headShrink = Shrink.shrink[CheckJsValue](head._2).map(v => CheckJsObject(required, order, fields.updated(head._1, v)))

      headShrink.append(shrinkOne(tail))
    }
}

object CheckJsObject {
  def empty: CheckJsObject = CheckJsObject(Set.empty, None, Map.empty)

  /**
    * Create a fixed json object that will not shrink.
    */
  def fixed(fields: Seq[(String, CheckJsValue)]): CheckJsObject =
    CheckJsObject(fields.map(_._1).toSet, Some(fields.map(_._1)), fields.toMap)

  implicit lazy val shrinkJsValue: Shrink[CheckJsObject] = Shrink[CheckJsObject](_.shrink)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy