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

net.hamnaberg.json.collection.Property.scala Maven / Gradle / Ivy

There is a newer version: 2.5
Show newest version
package net.hamnaberg.json.collection

import net.hamnaberg.json.collection.Json4sHelpers._
import org.json4s._
import org.json4s.JsonDSL._


sealed trait Property extends Extensible[Property] {
  lazy val name: String = getAsString(underlying, "name").getOrElse(throw new MissingFieldException("name", "property"))
  lazy val prompt: Option[String] = getAsString(underlying, "prompt")

  def isValue: Boolean = false
  def isArray: Boolean = false
  def isObject: Boolean = false

  def asValue: Option[Value[_]] = None
  def asArray: List[Value[_]] = Nil
  def asObject: Map[String, Value[_]] = Map.empty
}

object Property {
  def apply(obj: JObject): Property = {
    val map = obj.values
    obj match {
      case o if map.contains("array") => ListProperty(o)
      case o if map.contains("object") => ObjectProperty(o)
      case _ => ValueProperty(obj)
    }
  }

  def apply(name: String, value: Any): Property = {
    import net.hamnaberg.json.collection.{Value => V}
    value match {
      case l: Seq[_] => ListProperty(name, None, l.map(V.toValue))
      case l: Map[_,_] => ObjectProperty(name, None, l.map{case (k: Any, v: Any) => k.toString -> V.toValue(v)}.toMap)
      case v: Option[_] => ValueProperty(name, None, v.map(V.toValue))
      case v => ValueProperty(name, None, Some(V.toValue(v)))
    }
  }

  object Value {
    def unapply(v: ValueProperty) = v.asValue
  }
  object Array {
    def unapply(v: ListProperty) = Some(v.asArray)
  }
  object Object {
    def unapply(v: ObjectProperty) = Some(v.asObject)
  }
}

case class ValueProperty private[collection](underlying: JObject) extends Property {
  def copy(obj: JObject) = ValueProperty(obj)

  override val isValue = true

  override val asValue = (underlying \ "value").toOption.flatMap(Value(_))
}

object ValueProperty {
  def apply(name: String, prompt: Option[String] = None, value: Option[Value[_]] = None): ValueProperty = {
    apply(
      filtered(("name" -> name) ~
        ("prompt" -> prompt) ~
        ("value" -> value.map(_.toJson)))
    )
  }
  def apply[A](name: String, prompt: Option[String], value: Option[A])(implicit converter: ValueConverter[A, _]): ValueProperty = {
    apply(name, prompt, value.map(converter.convert))
  }

  def apply[A](name: String, value: Option[A])(implicit converter: ValueConverter[A, _]): ValueProperty = apply(name, None, value)
}

case class ListProperty private[collection](underlying: JObject) extends Property {
  def copy(obj: JObject) = ListProperty(obj)

  override val isArray = true

  override val asArray = getAsValueList(underlying, "array").flatMap(Value(_))
}

object ListProperty {
  def apply(name: String, prompt: Option[String] = None, value: Seq[Value[_]] = Nil): ListProperty = {
    apply(
      filtered(("name" -> name) ~
        ("prompt" -> prompt) ~
        ("array" -> value.map(_.toJson)))
    )
  }

  def apply[A](name: String, prompt: Option[String], value: Seq[A])(implicit converter: ValueConverter[A, _]): ListProperty =
    apply(name, prompt, value.map(converter.convert))

  def apply[A](name: String, value: Seq[A])(implicit converter: ValueConverter[A, _]): ListProperty = apply(name, None, value)
}

case class ObjectProperty private[collection](underlying: JObject) extends Property {
  def copy(obj: JObject) = ObjectProperty(obj)

  override val isObject = true

  override val asObject = getAsObject(underlying, "object").map(obj => {
    val values : Seq[(String, Option[Value[_]])] = obj.obj.map{case (n,v) => n -> Value(v)}
    values.collect{case (a, Some(b)) => a -> b}.toMap[String, Value[_]]
  }).getOrElse(Map.empty)
}

object ObjectProperty {
  def apply(name: String, prompt: Option[String] = None, value: Map[String, Value[_]] = Map.empty): ObjectProperty = {
    apply(
      filtered(("name" -> name) ~
        ("prompt" -> prompt) ~
        ("object" -> JObject(value.map{case (x,y) => JField(x, y.toJson)}.toList)))
    )
  }

  def apply(name: String, value: Map[String, Any]): ObjectProperty = {
    ObjectProperty(name, None, value.mapValues(Value.toValue))
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy