Skip to content

Commit 8a540f5

Browse files
committed
updated to match 1.3.3-SNAPSHOT
1 parent b7321fc commit 8a540f5

File tree

1 file changed

+116
-3
lines changed

1 file changed

+116
-3
lines changed

modules/swagger-play2/app/play/modules/swagger/PlayApiReader.scala

+116-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import java.lang.reflect.Method
2020
import javax.ws.rs.core.Context
2121
import javax.ws.rs._
2222

23+
import scala.collection.mutable.ListBuffer
24+
2325
case class RouteEntry(httpMethod: String, path: String)
2426

2527
object SwaggerUtils {
@@ -29,9 +31,120 @@ object SwaggerUtils {
2931
}
3032

3133
class PlayApiReader(val routes: Option[Routes]) extends JaxrsApiReader {
32-
3334
private var _routesCache: Map[String, RouteEntry] = null
3435

36+
override
37+
def readRecursive(
38+
docRoot: String,
39+
parentPath: String, cls: Class[_],
40+
config: SwaggerConfig,
41+
operations: ListBuffer[Tuple3[String, String, ListBuffer[Operation]]],
42+
parentMethods: ListBuffer[Method]): Option[ApiListing] = {
43+
val api = cls.getAnnotation(classOf[Api])
44+
45+
// must have @Api annotation to process!
46+
if(api != null) {
47+
val consumes = Option(api.consumes) match {
48+
case Some(e) if(e != "") => e.split(",").map(_.trim).toList
49+
case _ => cls.getAnnotation(classOf[Consumes]) match {
50+
case e: Consumes => e.value.toList
51+
case _ => List()
52+
}
53+
}
54+
val produces = Option(api.produces) match {
55+
case Some(e) if(e != "") => e.split(",").map(_.trim).toList
56+
case _ => cls.getAnnotation(classOf[Produces]) match {
57+
case e: Produces => e.value.toList
58+
case _ => List()
59+
}
60+
}
61+
val protocols = Option(api.protocols) match {
62+
case Some(e) if(e != "") => e.split(",").map(_.trim).toList
63+
case _ => List()
64+
}
65+
val description = api.description match {
66+
case e: String if(e != "") => Some(e)
67+
case _ => None
68+
}
69+
// look for method-level annotated properties
70+
val parentParams: List[Parameter] = (for(field <- getAllFields(cls))
71+
yield {
72+
// only process fields with @ApiParam, @QueryParam, @HeaderParam, @PathParam
73+
if(field.getAnnotation(classOf[QueryParam]) != null || field.getAnnotation(classOf[HeaderParam]) != null ||
74+
field.getAnnotation(classOf[HeaderParam]) != null || field.getAnnotation(classOf[PathParam]) != null ||
75+
field.getAnnotation(classOf[ApiParam]) != null) {
76+
val param = new MutableParameter
77+
param.dataType = field.getType.getName
78+
Option (field.getAnnotation(classOf[ApiParam])) match {
79+
case Some(annotation) => toAllowableValues(annotation.allowableValues)
80+
case _ =>
81+
}
82+
val annotations = field.getAnnotations
83+
processParamAnnotations(param, annotations)
84+
}
85+
else None
86+
}
87+
).flatten.toList
88+
89+
for(method <- cls.getMethods) {
90+
val returnType = findSubresourceType(method)
91+
val path = method.getAnnotation(classOf[Path]) match {
92+
case e: Path => e.value()
93+
case _ => ""
94+
}
95+
val endpoint = (parentPath + pathFromMethod(method)).replace("//", "/")
96+
Option(returnType.getAnnotation(classOf[Api])) match {
97+
case Some(e) => {
98+
val root = docRoot + api.value + pathFromMethod(method)
99+
parentMethods += method
100+
readRecursive(root, endpoint, returnType, config, operations, parentMethods)
101+
parentMethods -= method
102+
}
103+
case _ => {
104+
if(method.getAnnotation(classOf[ApiOperation]) != null) {
105+
readMethod(method, parentParams, parentMethods) match {
106+
case Some(op) => appendOperation(endpoint, path, op, operations)
107+
case None =>
108+
}
109+
}
110+
}
111+
}
112+
}
113+
// sort them by min position in the operations
114+
val s = (for(op <- operations) yield {
115+
(op, op._3.map(_.position).toList.min)
116+
}).sortWith(_._2 < _._2).toList
117+
val orderedOperations = new ListBuffer[Tuple3[String, String, ListBuffer[Operation]]]
118+
s.foreach(op => {
119+
val ops = op._1._3.sortWith(_.position < _.position)
120+
orderedOperations += Tuple3(op._1._1, op._1._2, ops)
121+
})
122+
val apis = (for ((endpoint, resourcePath, operationList) <- orderedOperations) yield {
123+
val orderedOperations = new ListBuffer[Operation]
124+
operationList.sortWith(_.position < _.position).foreach(e => orderedOperations += e)
125+
ApiDescription(
126+
addLeadingSlash(endpoint),
127+
None,
128+
orderedOperations.toList)
129+
}).toList
130+
val models = ModelUtil.modelsFromApis(apis)
131+
Some(ApiListing (
132+
apiVersion = config.apiVersion,
133+
swaggerVersion = config.swaggerVersion,
134+
basePath = config.basePath,
135+
resourcePath = addLeadingSlash(api.value),
136+
apis = ModelUtil.stripPackages(apis),
137+
models = models,
138+
description = description,
139+
produces = produces,
140+
consumes = consumes,
141+
protocols = protocols,
142+
position = api.position)
143+
)
144+
}
145+
else None
146+
}
147+
35148
override def read(docRoot: String, cls: Class[_], config: SwaggerConfig): Option[ApiListing] = {
36149
Logger("swagger").debug("ControllerReader: read(docRoot = %s, cls = %s, config = %s)".format(docRoot, cls.getName, config.toString))
37150
val api = cls.getAnnotation(classOf[Api])
@@ -353,10 +466,10 @@ class PlayApiReader(val routes: Option[Routes]) extends JaxrsApiReader {
353466
* @deprecated - do not be tempted to use this.... this is here to cover the method in the superclass.
354467
*/
355468
@Deprecated
356-
override def readMethod(method : java.lang.reflect.Method, parentParams : scala.List[com.wordnik.swagger.model.Parameter], parentMethods : scala.collection.mutable.ListBuffer[java.lang.reflect.Method]) : com.wordnik.swagger.model.Operation = {
469+
override def readMethod(method: Method, parentParams : List[Parameter], parentMethods : ListBuffer[Method]) : Option[Operation] = {
357470
// don't use this - it is specific to Jax-RS models.
358471
throw new RuntimeException("method not in use..")
359-
null
472+
None
360473
}
361474

362475
def findSubresourceType(method: Method): Class[_] = {

0 commit comments

Comments
 (0)