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

skinny.micro.routing.Route.scala Maven / Gradle / Ivy

package skinny.micro.routing

import javax.servlet.http.HttpServletRequest

import skinny.micro.{ RouteTransformer, MultiParams, Action }
import skinny.micro.data.MultiMap

/**
 * A route is a set of matchers and an action.  A route is considered to match
 * if all of its route matchers return Some.  If a route matches, its action
 * may be invoked.  The route parameters extracted by the matchers are made
 * available to the action.
 */
case class Route(
  routeMatchers: Seq[RouteMatcher] = Seq.empty,
  action: Action,
  contextPath: HttpServletRequest => String = _ => "",
  metadata: Map[Symbol, Any] = Map.empty) {
  /**
   * Optionally returns this route's action and the multi-map of route
   * parameters extracted from the matchers.  Each matcher's returned params
   * are merged into those of the previous.  If any matcher returns None,
   * None is returned.  If there are no route matchers, some empty map is
   * returned.
   */
  def apply(requestPath: String): Option[MatchedRoute] = {
    routeMatchers.foldLeft(Option(MultiMap())) {
      (acc: Option[MultiParams], routeMatcher: RouteMatcher) =>
        for {
          routeParams <- acc
          matcherParams <- routeMatcher(requestPath)
        } yield routeParams ++ matcherParams
    } map { routeParams => MatchedRoute(action, routeParams) }
  }

  /**
   * The reversible matcher of a route is the first reversible matcher, if
   * any.  This matcher may be used to generate URIs.
   */
  lazy val reversibleMatcher: Option[RouteMatcher] = {
    routeMatchers find (_.isInstanceOf[ReversibleRouteMatcher])
  }

  /**
   * Determines whether this is a reversible route.
   */
  lazy val isReversible: Boolean = !reversibleMatcher.isEmpty

  override def toString: String = routeMatchers.mkString(" ")
}

object Route {

  def apply(transformers: Seq[RouteTransformer], action: Action): Route = {
    apply(transformers, action, (_: HttpServletRequest) => "")
  }

  // TODO: remove HttpServletRequest from contextPath
  def apply(
    transformers: Seq[RouteTransformer],
    action: Action,
    contextPath: HttpServletRequest => String): Route = {
    val route = Route(action = action, contextPath = contextPath)
    transformers.foldLeft(route) { (route, transformer) => transformer(route) }
  }

  def appendMatcher(matcher: RouteMatcher): RouteTransformer = { (route: Route) =>
    route.copy(routeMatchers = route.routeMatchers :+ matcher)
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy