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

org.scalatra.commands.CommandSupport.scala Maven / Gradle / Ivy

package org.scalatra
package commands

import util.{ParamsValueReaderProperties, MultiMap}
import collection.mutable
import java.util.Date
import org.joda.time.DateTime
import collection.JavaConverters._
import java.util.concurrent.ConcurrentHashMap
import grizzled.slf4j.Logger
import javax.servlet.http.HttpServletRequest
import _root_.akka.dispatch.{Future, ExecutionContext}


/**
* Support for [[org.scalatra.commands.Command]] binding and validation.
*/
trait CommandSupport extends ParamsValueReaderProperties with CommandExecutors { this: ScalatraBase =>

  type CommandType <: Command

  private[this] val commandFactories: mutable.ConcurrentMap[Class[_], () => Command] = new ConcurrentHashMap[Class[_], () => Command].asScala

  def registerCommand[T <: Command](cmd: => T)(implicit mf: Manifest[T]) {
    commandFactories += (mf.erasure -> (() => cmd))
  }

  /**
   * Create and bind a [[org.scalatra.commands.Command]] of the given type with the current Scalatra params.
   *
   * For every command type, creation and binding is performed only once and then stored into
   * a request attribute.
   */
  def command[T <: CommandType](implicit request: HttpServletRequest, mf: Manifest[T]): T = {
    def createCommand = commandFactories.get(mf.erasure).map(_()).getOrElse(mf.erasure.newInstance()).asInstanceOf[T]
    commandOption[T] getOrElse bindCommand(createCommand)
  }

  /**
   * Create and bind a [[org.scalatra.commands.Command]] of the given type with the current Scalatra params.
   *
   * For every command type, creation and binding is performed only once and then stored into
   * a request attribute.
   */
  def commandOrElse[T <: CommandType](factory: ⇒ T)(implicit request: HttpServletRequest, mf: Manifest[T]): T = {
    commandOption[T] getOrElse bindCommand(factory)
  }

  protected def bindCommand[T <: CommandType](newCommand: T)(implicit request: HttpServletRequest, mf: Manifest[T]): T = {
    newCommand.bindTo(params(request), multiParams(request), request.headers)
    newCommand
  }

  def commandOption[T <: CommandType](implicit request: HttpServletRequest, mf: Manifest[T]) : Option[T] =
    request.get(commandRequestKey[T]).map(_.asInstanceOf[T])

  private[commands] def commandRequestKey[T <: CommandType](implicit request: HttpServletRequest, mf: Manifest[T]) =
    "_command_" + manifest[T].erasure.getName

  private class CommandRouteMatcher[T <: CommandType ](implicit mf: Manifest[T]) extends RouteMatcher {

    override def apply(requestPath: String) = if (command[T].isValid) Some(MultiMap()) else None
  }

  /**
   * Create a [[org.scalatra.RouteMatcher]] that evaluates '''true''' only if a command is valid.
   */
  def ifValid[T <: CommandType](implicit mf: Manifest[T]): RouteMatcher = new CommandRouteMatcher[T]


}

trait ParamsOnlyCommandSupport extends CommandSupport { this: ScalatraBase =>
  type CommandType = ParamsOnlyCommand
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy