Skip to content

Commit

Permalink
(refs #1)Seq type support for query parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
takezoe committed Nov 28, 2016
1 parent 13037eb commit 6ca99e9
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 25 deletions.
4 changes: 1 addition & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ name := "resty"

organization := "com.github.takezoe"

version := "0.0.1"

scalaVersion := "2.12.0"
version := "0.0.2-SNAPSHOT"

val jettyVersion = "9.2.3.v20140905"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,15 @@ class InitializeListener extends ServletContextListener {
class SampleController {

@Action(method = "GET", path = "/hello/{name}")
def hello(name: Option[String]): Message = {
Message(s"Hello ${name.getOrElse("World")}!")
def hello(name: String): Message = {
Message(s"Hello ${name}!")
}

@Action(method = "GET", path = "/hello")
def helloSeq(names: Seq[String]): Seq[String] = {
names.map { name =>
s"Hello ${name}!"
}
}

@Action(method = "POST", path = "/hello")
Expand Down
6 changes: 3 additions & 3 deletions src/main/scala/com/github/takezoe/resty/Resty.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,16 @@ object Resty {
}
}

def findAction(path: String, method: String): Option[(ControllerDef, ActionDef, Map[String, String])] = {
val pathParams = new mutable.HashMap[String, String]()
def findAction(path: String, method: String): Option[(ControllerDef, ActionDef, Map[String, Seq[String]])] = {
val pathParams = new mutable.HashMap[String, Seq[String]]()

_actions.asScala.filter(_._2.method == method).find { case (controller, action) =>
val requestPath = path.split("/")
val actionPath = action.path.split("/")
if(requestPath.length == actionPath.length){
(requestPath zip actionPath).forall { case (requestPathFragment, actionPathFragment) =>
if(actionPathFragment.startsWith("{") && actionPathFragment.endsWith("}")){
pathParams += (actionPathFragment.substring(1, actionPathFragment.length - 1) -> requestPathFragment)
pathParams += (actionPathFragment.substring(1, actionPathFragment.length - 1) -> Seq(requestPathFragment))
true
} else {
requestPathFragment == actionPathFragment
Expand Down
10 changes: 7 additions & 3 deletions src/main/scala/com/github/takezoe/resty/RestyKernel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,15 @@ trait RestyKernel {
}
}

protected def prepareParams(request: HttpServletRequest, pathParams: Map[String, String], paramDefs: Seq[ParamDef]): Either[Seq[String], Seq[AnyRef]] = {
protected def prepareParams(request: HttpServletRequest,
pathParams: Map[String, Seq[String]],
paramDefs: Seq[ParamDef]): Either[Seq[String], Seq[AnyRef]] = {
val converted = paramDefs.map { paramDef =>
paramDef match {
case ParamDef.Param(name, converter) => converter.convert(pathParams.get(name).getOrElse(request.getParameter(name)))
case ParamDef.Body(_, _, converter) => converter.convert(IOUtils.toString(request.getInputStream, "UTF-8"))
case ParamDef.Param(name, converter) =>
converter.convert(pathParams.get(name).getOrElse(request.getParameterValues(name)))
case ParamDef.Body(_, _, converter) =>
converter.convert(Seq(IOUtils.toString(request.getInputStream, "UTF-8")))
}
}

Expand Down
28 changes: 24 additions & 4 deletions src/main/scala/com/github/takezoe/resty/SwaggerController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.github.takezoe.resty

import java.lang.reflect.Field

import com.github.takezoe.resty.model.ParamConverter.{OptionStringConverter, SeqStringConverter}
import com.github.takezoe.resty.model.ParamDef
import com.github.takezoe.resty.util.ReflectionUtils
import io.swagger.models._
Expand Down Expand Up @@ -53,16 +54,35 @@ class SwaggerController {

action.params.foreach { paramDef =>
paramDef match {
case ParamDef.Param(name, _) if action.path.contains(s"{${name}}") => {
case ParamDef.Param(name, converter) if action.path.contains(s"{${name}}") => {
val parameter = new PathParameter()
parameter.setName(name)
parameter.setType("string") // TODO Int, Long and Option support
converter match {
// array type is not supported in path parameter
//case _: SeqStringConverter =>
// parameter.setType("array")
// parameter.setItems(new StringProperty())
case _: OptionStringConverter =>
parameter.setType("string")
parameter.setRequired(false)
case _ =>
parameter.setType("string")
}
operation.addParameter(parameter)
}
case ParamDef.Param(name, _) => {
case ParamDef.Param(name, converter) => {
val parameter = new QueryParameter()
parameter.setName(name)
parameter.setType("string") // TODO Int, Long and Option support
converter match {
case _: SeqStringConverter =>
parameter.setType("array")
parameter.setItems(new StringProperty())
case _: OptionStringConverter =>
parameter.setType("string")
parameter.setRequired(false)
case _ =>
parameter.setType("string")
}
operation.addParameter(parameter)
}
case ParamDef.Body(name, clazz, _) => {
Expand Down
30 changes: 20 additions & 10 deletions src/main/scala/com/github/takezoe/resty/model/ParamConverter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,48 @@ package com.github.takezoe.resty.model
import com.github.takezoe.resty.util.JsonUtils

trait ParamConverter {
def convert(value: String): Either[String, AnyRef]
def convert(values: Seq[String]): Either[String, AnyRef]
}

object ParamConverter {

class StringConverter(name: String) extends ParamConverter {
override def convert(value: String): Either[String, AnyRef] = {
if (value == null) {
override def convert(values: Seq[String]): Either[String, AnyRef] = {
if (values == null || values.isEmpty) {
Left(s"${name} is required.")
} else {
Right(value)
Right(values.head)
}
}
}

class SeqStringConverter(name: String) extends ParamConverter {
override def convert(values: Seq[String]): Either[String, AnyRef] = {
if (values == null) {
Right(Seq.empty)
} else {
Right(values)
}
}
}

class OptionStringConverter(name: String) extends ParamConverter {
override def convert(value: String): Either[String, AnyRef] = {
if (value == null) {
override def convert(values: Seq[String]): Either[String, AnyRef] = {
if (values == null || values.isEmpty) {
Right(None)
} else {
Right(Some(value))
Right(Some(values.head))
}
}
}

class JsonConverter(clazz: Class[_]) extends ParamConverter {
override def convert(value: String): Either[String, AnyRef] = {
if (value == null) {
override def convert(values: Seq[String]): Either[String, AnyRef] = {
if (values == null || values.isEmpty) {
Left("Body is required")
} else {
try {
Right(JsonUtils.deserialize(value, clazz))
Right(JsonUtils.deserialize(values.head, clazz))
} catch {
case e: Exception => Left(e.getMessage)
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/scala/com/github/takezoe/resty/model/ParamDef.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ object ParamDef {
def apply(name: String, clazz: Class[_]): ParamDef = {
if(clazz == classOf[String]){
Param(name, new ParamConverter.StringConverter(name))
} else if(clazz == classOf[Seq[_]]){
Param(name, new ParamConverter.SeqStringConverter(name))
} else if(clazz == classOf[Option[_]]){
Param(name, new ParamConverter.OptionStringConverter(name))
} else {
Expand Down

0 comments on commit 6ca99e9

Please sign in to comment.