Skip to content

Commit

Permalink
Initial implementation of search.
Browse files Browse the repository at this point in the history
  • Loading branch information
Dave Shiga committed May 8, 2015
1 parent 6c6674d commit 43f128c
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ object AgoraEntity {
case HttpEntity.Empty new AgoraEntity()
}

implicit val SeqAgoraEntityUnmarshaller =
Unmarshaller[Seq[AgoraEntity]](`application/json`) {
case HttpEntity.NonEmpty(contentType, data) => {
grater[AgoraEntity].fromJSONArray(data.asString)
}
case HttpEntity.Empty => {
Seq(new AgoraEntity())
}
}

implicit val AgoraEntityMarshaller =
Marshaller.of[AgoraEntity](`application/json`) { (value, contentType, context) =>
context.marshalTo(HttpEntity(contentType, grater[AgoraEntity].toCompactJSON(value)))
Expand All @@ -35,7 +45,16 @@ object AgoraEntity {
payload = Option(agoraAddRequest.payload)
)
}


def fromAgoraSearch(agoraSearch: AgoraSearch) = {
new AgoraEntity(namespace = agoraSearch.namespace,
name = agoraSearch.name,
id = agoraSearch.id,
synopsis = agoraSearch.synopsis,
documentation = agoraSearch.documentation,
owner = agoraSearch.owner,
payload = agoraSearch.payload)
}
}

object AgoraAddRequest {
Expand Down Expand Up @@ -69,6 +88,23 @@ case class AgoraEntity(@(ApiModelProperty@field)(required = true, value = "The n
payload: Option[String] = None
)

@ApiModel(value = "Agora Search")
case class AgoraSearch(@(ApiModelProperty@field)(required = true, value = "The namespace to which the method belongs")
namespace: Option[String] = None,
@(ApiModelProperty@field)(required = true, value = "The method name ")
name: Option[String] = None,
@(ApiModelProperty@field)(required = true, value = "The method id")
var id: Option[Int] = None,
@(ApiModelProperty@field)(required = true, value = "User who owns this method in the methods repo")
owner: Option[String] = None,
@(ApiModelProperty@field)(required = true, value = "A short description of the method")
synopsis: Option[String] = None,
@(ApiModelProperty@field)(required = true, value = "Method documentation")
documentation: Option[String] = None,
@(ApiModelProperty@field)(required = true, value = "The method payload")
payload: Option[String] = None
)

@ApiModel(value = "Request to add method")
case class AgoraAddRequest(@(ApiModelProperty@field)(required = true, value = "The namespace to which the method belongs")
namespace: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package org.broadinstitute.dsde.agora.server.webservice.methods

import akka.actor.Actor
import org.broadinstitute.dsde.agora.server.dataaccess.AgoraDao
import org.broadinstitute.dsde.agora.server.model.AgoraEntity
import org.broadinstitute.dsde.agora.server.model.{AgoraSearch, AgoraEntity}
import org.broadinstitute.dsde.agora.server.webservice.util.ServiceMessages
import org.broadinstitute.dsde.agora.server.webservice.PerRequest._
import spray.http.StatusCodes._
Expand All @@ -11,17 +11,19 @@ import com.novus.salat._
import com.novus.salat.global._



/**
* Actor responsible for querying the methods repository.
*/
class MethodsQueryHandler extends Actor {
implicit val system = context.system

def receive = {
case ServiceMessages.Query(requestContext: RequestContext, namespace: String, name: String, id: Int) =>
case ServiceMessages.QueryByNamespaceNameId(requestContext: RequestContext, namespace: String, name: String, id: Int) =>
query(requestContext, namespace, name, id)
context.stop(self)
case ServiceMessages.Query(requestContext: RequestContext, agoraSearch: AgoraSearch) =>
query(requestContext, agoraSearch)
context.stop(self)
}

def query(requestContext: RequestContext, namespace: String, name: String, id: Int): Unit = {
Expand All @@ -30,4 +32,9 @@ class MethodsQueryHandler extends Actor {
case Some(method) => context.parent ! grater[AgoraEntity].toJSON(method)
}
}

def query(requestContext: RequestContext, agoraSearch: AgoraSearch): Unit = {
val entities = AgoraDao.createAgoraDao.find(AgoraEntity.fromAgoraSearch(agoraSearch))
context.parent ! grater[AgoraEntity].toJSONArray(entities)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.broadinstitute.dsde.agora.server.webservice.methods

import com.wordnik.swagger.annotations._
import org.broadinstitute.dsde.agora.server.model.{AgoraAddRequest, AgoraEntity}
import org.broadinstitute.dsde.agora.server.model.{AgoraSearch, AgoraAddRequest, AgoraEntity}
import org.broadinstitute.dsde.agora.server.webservice.util.{ApiUtil, ServiceHandlerProps, ServiceMessages}
import org.broadinstitute.dsde.agora.server.webservice.PerRequestCreator
import spray.routing.HttpService
Expand All @@ -10,9 +10,9 @@ import spray.routing.HttpService
trait MethodsService extends HttpService with PerRequestCreator {
this: ServiceHandlerProps => // Require a concrete ServiceHandlerProps creator to be mixed in

val routes = queryRoute ~ postRoute
val routes = queryRoute ~ queryByEntityRoute ~ postRoute

@ApiOperation(value = "Query a method from the method repository by namespace, name, and id",
@ApiOperation(value = "Get a method in the method repository matching namespace, name, and id",
nickname = "methods",
httpMethod = "GET",
produces = "application/json",
Expand All @@ -32,7 +32,36 @@ trait MethodsService extends HttpService with PerRequestCreator {
path(ApiUtil.Methods.path / Segment / Segment / Segment) { (namespace, name, id) =>
get {
requestContext =>
perRequest(requestContext, methodsQueryHandlerProps, ServiceMessages.Query(requestContext, namespace, name, id.toInt))
perRequest(requestContext, methodsQueryHandlerProps, ServiceMessages.QueryByNamespaceNameId(requestContext, namespace, name, id.toInt))
}
}

@ApiOperation(value = "Query for methods in the method repository",
nickname = "methods",
httpMethod = "GET",
produces = "application/json",
response = classOf[AgoraEntity],
notes = "API is rapidly changing.")
@ApiImplicitParams(Array(
new ApiImplicitParam(name = "namespace", required = true, dataType = "string", paramType = "path", value = "Namespace"),
new ApiImplicitParam(name = "name", required = true, dataType = "string", paramType = "path", value = "Name"),
new ApiImplicitParam(name = "id", required = true, dataType = "string", paramType = "path", value = "Id"),
new ApiImplicitParam(name = "synopsis", required = true, dataType = "string", paramType = "path", value = "Synopsis"),
new ApiImplicitParam(name = "documentation", required = true, dataType = "string", paramType = "path", value = "Documentation"),
new ApiImplicitParam(name = "owner", required = true, dataType = "string", paramType = "path", value = "Owner"),
new ApiImplicitParam(name = "payload", required = true, dataType = "string", paramType = "path", value = "Payload")
))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "Successful Request"),
new ApiResponse(code = 500, message = "Internal Error")
))
def queryByEntityRoute =
path(ApiUtil.Methods.path) {
get {
parameters('namespace?, 'name?, 'id.as[Int]?, 'synopsis?, 'documentation?, 'owner?, 'payload?).as(AgoraSearch) { agoraSearch =>
requestContext =>
perRequest(requestContext, methodsQueryHandlerProps, ServiceMessages.Query(requestContext, agoraSearch))
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package org.broadinstitute.dsde.agora.server.webservice.util

import org.broadinstitute.dsde.agora.server.model.AgoraAddRequest
import org.broadinstitute.dsde.agora.server.model.{AgoraSearch, AgoraEntity, AgoraAddRequest}
import spray.routing.RequestContext

/**
* Case classes representing messages to pass to service handler actors
*/
object ServiceMessages {
case class Query(requestContext: RequestContext, namespace: String, name: String, id: Int)

case class QueryByNamespaceNameId(requestContext: RequestContext, namespace: String, name: String, id: Int)

case class Query(requestContext: RequestContext, agoraSearch: AgoraSearch)

case class Add(requestContext: RequestContext, agoraAddRequest: AgoraAddRequest)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ trait AgoraTestData {
val namespace = "broad"

val name = "testMethod"

val name2 = "testMethod2"

val synopsis = "This is a test method"

Expand All @@ -30,6 +32,8 @@ trait AgoraTestData {
|}""".stripMargin

val testEntity = AgoraEntity(namespace = Option(namespace), name = Option(name))

val testEntity2 = AgoraEntity(namespace = Option(namespace), name = Option(name2))

val testAddRequest = new AgoraAddRequest(
namespace = namespace,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ class ApiServiceSpec extends FlatSpec with Matchers with Directives with Scalate
}
}

"Agora" should "return methods matching the query" in {
agoraDao.insert(testEntity2)
Get(ApiUtil.Methods.withLeadingSlash + "?namespace=broad") ~> methodsService.queryByEntityRoute ~> check {
responseAs[Seq[AgoraEntity]] === Seq(testEntity, testEntity2)
}
}

"Agora" should "create and return a method" in {
Post(ApiUtil.Methods.withLeadingSlash, marshal(testAddRequest)) ~> methodsService.postRoute ~> check {
val response = responseAs[AgoraEntity]
Expand Down

0 comments on commit 43f128c

Please sign in to comment.