io.lemonlabs.uri.dsl.UrlDsl.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala-uri_2.12 Show documentation
Show all versions of scala-uri_2.12 Show documentation
Simple scala library for building and parsing URIs
package io.lemonlabs.uri.dsl
import io.lemonlabs.uri.Url
import io.lemonlabs.uri.parsing.UrlParser
/**
* Value class to add DSL functionality to Urls
*/
class UrlDsl(val url: Url) extends AnyVal {
import url.config
private def anyToQueryValue(any: Any): Option[String] = any match {
case v: Option[_] => v.map(_.toString)
case _ => Some(any.toString)
}
/**
* Adds a new Query String parameter key-value pair. If the value for the Query String parameter is None, then this
* Query String parameter will be rendered without a value e.g. `?param` as opposed to `?param=value`
* @param kv Tuple2 representing the query string parameter
* @return A new Uri with the new Query String parameter
*/
def ?(kv: (String, Any)): Url =
url.addParam(kv._1, anyToQueryValue(kv._2))
/**
* Adds a new Query String. The specified String is parsed as a Query String param.
* @return A new Uri with the new Query String parameter
*/
def ?(kv: String): Url =
url.addParamOptionValue(UrlParser.parseQueryParam(kv).get)
/**
* Adds a trailing forward slash to the path and a new Query String parameter key-value pair.
* If the value for the Query String parameter is None, then this Query String parameter will
* be rendered without a value e.g. `?param` as opposed to `?param=value`
* @param kv Tuple2 representing the query string parameter
* @return A new Uri with the new Query String parameter
*/
def /?(kv: (String, Any)): Url =
/("").addParam(kv._1, anyToQueryValue(kv._2))
/**
* Maybe adds a new Query String parameter key-value pair.
* If the value for the Query String parameter is None, then this Query String parameter will not be added,
* otherwise it will be added
* @param kv Tuple2 representing the query string parameter
* @return A new Uri with the new Query String parameter
*/
def &&(kv: (String, Any)): Url = kv match {
case (k, None) => url
case (k, v) => &(k, v)
}
/**
* Adds a new Query String parameter key-value pair. If the value for the Query String parameter is None, then this
* Query String parameter will be rendered without a value e.g. `?param` as opposed to `?param=value`
* @param kv Tuple2 representing the query string parameter
* @return A new Uri with the new Query String parameter
*/
def &(kv: (String, Any)): Url =
url.addParam(kv._1, anyToQueryValue(kv._2))
/**
* Adds a new Query String. The specified String is parsed as a Query String param.
* @return A new Uri with the new Query String parameter
*/
def &(kv: String): Url =
?(kv)
/**
* Adds all the specified key-value pairs as parameters to the query
*
* @param kvs A list of key-value pairs to add as query parameters
* @return A new Url with the new Query String parameters
*/
def addParams(kvs: Iterable[(String, Any)]): Url =
url.addParamsOptionValues(kvs.map { case (k, v) => (k, anyToQueryValue(v)) })
/**
* Adds a fragment to the end of the uri
* @param fragment String representing the fragment
* @return A new Uri with this fragment
*/
def `#`(fragment: String): Url =
url.withFragment(fragment)
/**
* Appends a path part to the path of this URI
* @param pp The path part
* @return A new Uri with this path part appended
*/
def /(pp: String): Url =
url.addPathPart(pp)
/**
* Operator precedence in Scala will mean that our DSL will not always be executed left to right.
*
* For the operators this DSL cares about, the order will be
*
* (all letters)
* &
* :
* /
* `#` ?
*
* (see Scala Reference - 6.12.3 Infix Operations: http://www.scala-lang.org/docu/files/ScalaReference.pdf)
*
* To handle cases where the right hard part of the DSL is executed first, we turn that into a Uri, and merge
* it with the left had side. It is assumed the right hand Uri is generated from this DSL only to add path
* parts, query parameters or to overwrite the fragment
*
* @param other A Uri generated by more DSL to the right of us
* @return A Uri with the right hand DSL merged into us
*/
private def merge(other: Url): Url =
url.withFragment(other.fragment.orElse(url.fragment))
.withQueryString(url.query.addParams(other.query))
.withPath(url.path.addParts(other.path.parts))
def /(other: Url): Url = merge(other)
def ?(other: Url): Url = merge(other)
def `#`(other: Url): Url = merge(other)
def &(other: Url): Url = merge(other)
}