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

play.api.data.mapping.Path.scala Maven / Gradle / Ivy

The newest version!
package play.api.data.mapping

import scala.language.higherKinds
import scala.language.implicitConversions

sealed trait PathNode
case class KeyPathNode(key: String) extends PathNode {
  override def toString = key
}

case class IdxPathNode(idx: Int) extends PathNode {
  override def toString = s"[$idx]"
}

object \: {
  def unapply(path: Path): Option[(Path, Path)] = {
    path match {
      case Path(n :: ns) => Some((Path \ n) -> Path(ns))
      case Path(Nil) => None
    }
  }
}

case object Path extends Path(Nil) {
  def apply(path: String) = new Path(KeyPathNode(path) :: Nil)
  def apply(path: List[PathNode] = Nil) = new Path(path)
  def unapply(p: Path): Option[List[PathNode]] = Some(p.path)
}

class Path(val path: List[PathNode]) {

  def \(key: String): Path = this \ KeyPathNode(key)
  def \(idx: Int): Path = this \ IdxPathNode(idx)
  def \(child: PathNode): Path = Path(path :+ child)

  /**
   * Aggregate 2 paths
   * {{{
   *   (Path \ "foo" \ "bar").compose(Path \ "baz") == (Path \ "foo" \ "bar" \ "baz")
   * }}}
   */
  def compose(p: Path): Path = Path(this.path ++ p.path)
  def ++(other: Path) = this compose other

  class Deferred[I] private[Path] (reader: Reader[I]) {
    def apply[J, O](sub: => RuleLike[J, O])(implicit r: Path => RuleLike[I, J]): Rule[I, O] =
      reader.read(sub)
  }

  def from[I] = new Deferred(Reader[I](this))

  def read[I, J, O](sub: => RuleLike[J, O])(implicit r: Path => RuleLike[I, J]): Rule[I, O] =
    Reader[I](this).read(sub)

  def read[I, O](implicit r: Path => RuleLike[I, O]): Rule[I, O] =
    Reader[I](this).read[O]

  /**
   * Creates a Writes the serialize data to the desired output type
   * {{{
   *   val contact = Contact("Julien", "Tournay")
   *   implicit def contactWrite = (Path \ "firstname").write[String, UrlFormEncoded]
   *   contactWrite.writes(contact) mustEqual Map("firstname" -> "Julien")
   * }}}
   */
  def write[O, I](implicit w: Path => WriteLike[O, I]): Write[O, I] =
    Writer[I](this).write(w)

  /**
   * Creates a Writes the serialize data to the desired output type using a provided format.
   * * {{{
   *   val w = (Path \ "date").write(date("yyyy-MM-dd""))
   *   w.writes(new Date()) == Json.obj("date" -> "2013-10-3")
   * }}}
   */
  def write[O, J, I](format: => WriteLike[O, J])(implicit w: Path => WriteLike[J, I]): Write[O, I] =
    Writer[I](this).write(format)

  override def toString = this.path match {
    case Nil => "/"
    case hs => hs.foldLeft("") {
      case (path, IdxPathNode(i)) => path + s"[$i]"
      case (path, KeyPathNode(k)) => path + "/" + k
    }
  }

  override def hashCode = path.hashCode
  override def equals(o: Any) = {
    if (canEqual(o)) {
      val j = o.asInstanceOf[Path]
      this.path == j.path
    } else
      false
  }
  def canEqual(o: Any) = o.isInstanceOf[Path]
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy