Skip to content

Commit

Permalink
support for #489
Browse files Browse the repository at this point in the history
  • Loading branch information
fehguy committed Mar 15, 2014
1 parent c29d50d commit 697a4bd
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.wordnik.swagger.jersey
import com.wordnik.swagger.jaxrs._
import com.wordnik.swagger.core._
import com.wordnik.swagger.model._
import com.wordnik.swagger.config._
import com.wordnik.swagger.annotations._

import com.wordnik.swagger.core.util._
Expand All @@ -37,8 +38,118 @@ import com.sun.jersey.core.header.FormDataContentDisposition
import com.sun.jersey.multipart.FormDataParam
import com.sun.jersey.api.core.InjectParam

import scala.collection.mutable.{ ListBuffer, HashMap, HashSet }

class JerseyApiReader extends JaxrsApiReader {
private val LOGGER = LoggerFactory.getLogger(classOf[JerseyApiReader])
def readRecursive(
docRoot: String,
parentPath: String, cls: Class[_],
config: SwaggerConfig,
operations: ListBuffer[Tuple3[String, String, ListBuffer[Operation]]],
parentMethods: ListBuffer[Method]): Option[ApiListing] = {
val api = cls.getAnnotation(classOf[Api])

// must have @Api annotation to process!
if(api != null) {
val consumes = Option(api.consumes) match {
case Some(e) if(e != "") => e.split(",").map(_.trim).toList
case _ => cls.getAnnotation(classOf[Consumes]) match {
case e: Consumes => e.value.toList
case _ => List()
}
}
val produces = Option(api.produces) match {
case Some(e) if(e != "") => e.split(",").map(_.trim).toList
case _ => cls.getAnnotation(classOf[Produces]) match {
case e: Produces => e.value.toList
case _ => List()
}
}
val protocols = Option(api.protocols) match {
case Some(e) if(e != "") => e.split(",").map(_.trim).toList
case _ => List()
}
val description = api.description match {
case e: String if(e != "") => Some(e)
case _ => None
}
// look for method-level annotated properties
val parentParams: List[Parameter] = (for(field <- getAllFields(cls))
yield {
// only process fields with @ApiParam, @QueryParam, @HeaderParam, @PathParam
if(field.getAnnotation(classOf[QueryParam]) != null || field.getAnnotation(classOf[HeaderParam]) != null ||
field.getAnnotation(classOf[HeaderParam]) != null || field.getAnnotation(classOf[PathParam]) != null ||
field.getAnnotation(classOf[ApiParam]) != null) {
val param = new MutableParameter
param.dataType = field.getType.getName
Option (field.getAnnotation(classOf[ApiParam])) match {
case Some(annotation) => toAllowableValues(annotation.allowableValues)
case _ =>
}
val annotations = field.getAnnotations
processParamAnnotations(param, annotations)
}
else None
}
).flatten.toList

for(method <- cls.getMethods) {
val returnType = findSubresourceType(method)
val path = method.getAnnotation(classOf[Path]) match {
case e: Path => e.value()
case _ => ""
}
val endpoint = (parentPath + pathFromMethod(method)).replace("//", "/")
Option(returnType.getAnnotation(classOf[Api])) match {
case Some(e) => {
val root = docRoot + api.value + pathFromMethod(method)
parentMethods += method
readRecursive(root, endpoint, returnType, config, operations, parentMethods)
parentMethods -= method
}
case _ => {
if(method.getAnnotation(classOf[ApiOperation]) != null) {
val op = readMethod(method, parentParams, parentMethods)
appendOperation(endpoint, path, op, operations)
}
}
}
}
// sort them by min position in the operations
val s = (for(op <- operations) yield {
(op, op._3.map(_.position).toList.min)
}).sortWith(_._2 < _._2).toList
val orderedOperations = new ListBuffer[Tuple3[String, String, ListBuffer[Operation]]]
s.foreach(op => {
val ops = op._1._3.sortWith(_.position < _.position)
orderedOperations += Tuple3(op._1._1, op._1._2, ops)
})
val apis = (for ((endpoint, resourcePath, operationList) <- orderedOperations) yield {
val orderedOperations = new ListBuffer[Operation]
operationList.sortWith(_.position < _.position).foreach(e => orderedOperations += e)
ApiDescription(
addLeadingSlash(endpoint),
None,
orderedOperations.toList)
}).toList
val models = ModelUtil.modelsFromApis(apis)
Some(ApiListing (
apiVersion = config.apiVersion,
swaggerVersion = config.swaggerVersion,
basePath = config.basePath,
resourcePath = addLeadingSlash(api.value),
apis = ModelUtil.stripPackages(apis),
models = models,
description = description,
produces = produces,
consumes = consumes,
protocols = protocols,
position = api.position)
)
}
else None
}

def processParamAnnotations(mutable: MutableParameter, paramAnnotations: Array[Annotation]): Option[Parameter] = {
var shouldIgnore = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.wordnik.swagger.jersey
import com.wordnik.swagger.jaxrs._
import com.wordnik.swagger.core._
import com.wordnik.swagger.model._
import com.wordnik.swagger.config._
import com.wordnik.swagger.annotations._

import com.wordnik.swagger.core.util._
Expand All @@ -36,9 +37,120 @@ import java.lang.annotation.Annotation
import org.glassfish.jersey.media.multipart.FormDataContentDisposition
import org.glassfish.jersey.media.multipart.FormDataParam

import scala.collection.mutable.{ ListBuffer, HashMap, HashSet }

class JerseyApiReader extends JaxrsApiReader {
private val LOGGER = LoggerFactory.getLogger(classOf[JerseyApiReader])

def readRecursive(
docRoot: String,
parentPath: String, cls: Class[_],
config: SwaggerConfig,
operations: ListBuffer[Tuple3[String, String, ListBuffer[Operation]]],
parentMethods: ListBuffer[Method]): Option[ApiListing] = {
val api = cls.getAnnotation(classOf[Api])

// must have @Api annotation to process!
if(api != null) {
val consumes = Option(api.consumes) match {
case Some(e) if(e != "") => e.split(",").map(_.trim).toList
case _ => cls.getAnnotation(classOf[Consumes]) match {
case e: Consumes => e.value.toList
case _ => List()
}
}
val produces = Option(api.produces) match {
case Some(e) if(e != "") => e.split(",").map(_.trim).toList
case _ => cls.getAnnotation(classOf[Produces]) match {
case e: Produces => e.value.toList
case _ => List()
}
}
val protocols = Option(api.protocols) match {
case Some(e) if(e != "") => e.split(",").map(_.trim).toList
case _ => List()
}
val description = api.description match {
case e: String if(e != "") => Some(e)
case _ => None
}
// look for method-level annotated properties
val parentParams: List[Parameter] = (for(field <- getAllFields(cls))
yield {
// only process fields with @ApiParam, @QueryParam, @HeaderParam, @PathParam
if(field.getAnnotation(classOf[QueryParam]) != null || field.getAnnotation(classOf[HeaderParam]) != null ||
field.getAnnotation(classOf[HeaderParam]) != null || field.getAnnotation(classOf[PathParam]) != null ||
field.getAnnotation(classOf[ApiParam]) != null) {
val param = new MutableParameter
param.dataType = field.getType.getName
Option (field.getAnnotation(classOf[ApiParam])) match {
case Some(annotation) => toAllowableValues(annotation.allowableValues)
case _ =>
}
val annotations = field.getAnnotations
processParamAnnotations(param, annotations)
}
else None
}
).flatten.toList

for(method <- cls.getMethods) {
val returnType = findSubresourceType(method)
val path = method.getAnnotation(classOf[Path]) match {
case e: Path => e.value()
case _ => ""
}
val endpoint = (parentPath + pathFromMethod(method)).replace("//", "/")
Option(returnType.getAnnotation(classOf[Api])) match {
case Some(e) => {
val root = docRoot + api.value + pathFromMethod(method)
parentMethods += method
readRecursive(root, endpoint, returnType, config, operations, parentMethods)
parentMethods -= method
}
case _ => {
if(method.getAnnotation(classOf[ApiOperation]) != null) {
val op = readMethod(method, parentParams, parentMethods)
appendOperation(endpoint, path, op, operations)
}
}
}
}
// sort them by min position in the operations
val s = (for(op <- operations) yield {
(op, op._3.map(_.position).toList.min)
}).sortWith(_._2 < _._2).toList
val orderedOperations = new ListBuffer[Tuple3[String, String, ListBuffer[Operation]]]
s.foreach(op => {
val ops = op._1._3.sortWith(_.position < _.position)
orderedOperations += Tuple3(op._1._1, op._1._2, ops)
})
val apis = (for ((endpoint, resourcePath, operationList) <- orderedOperations) yield {
val orderedOperations = new ListBuffer[Operation]
operationList.sortWith(_.position < _.position).foreach(e => orderedOperations += e)
ApiDescription(
addLeadingSlash(endpoint),
None,
orderedOperations.toList)
}).toList
val models = ModelUtil.modelsFromApis(apis)
Some(ApiListing (
apiVersion = config.apiVersion,
swaggerVersion = config.swaggerVersion,
basePath = config.basePath,
resourcePath = addLeadingSlash(api.value),
apis = ModelUtil.stripPackages(apis),
models = models,
description = description,
produces = produces,
consumes = consumes,
protocols = protocols,
position = api.position)
)
}
else None
}

def processParamAnnotations(mutable: MutableParameter, paramAnnotations: Array[Annotation]): Option[Parameter] = {
var shouldIgnore = false
for (pa <- paramAnnotations) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import javax.ws.rs.core.Response

@Api(value = "/child",
description = "Media Type Test",
produces = "application/json; charset=utf8",
produces = "application/json; charset=utf-8",
protocols = "http, https")
class SubresourceLocatorChildTest {
@GET
Expand Down

0 comments on commit 697a4bd

Please sign in to comment.