Skip to content

Commit 4770335

Browse files
committed
Swagger Play2 module:
1) add default httpMethod/nickname to operation; 2) add default dataType to implicit parameter
1 parent c9c3c93 commit 4770335

File tree

4 files changed

+87
-60
lines changed

4 files changed

+87
-60
lines changed

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

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,12 @@ class PlayApiReader(val routes: Option[Routes]) extends JaxrsApiReader {
7272
// only process methods with @ApiOperation annotations
7373
if (method.getAnnotation(classOf[ApiOperation]) != null) {
7474
Logger("swagger").debug("ApiOperation: found on method: %s".format(method.getName))
75-
val operation = readMethod(method).get
76-
val fullOperationResourcePath = getPath(cls, method)
7775

78-
fullOperationResourcePath match {
79-
case Some(path) => {
76+
val fullMethodName = getFullMethodName(cls, method)
77+
routesCache.get(fullMethodName) match {
78+
case Some(RouteEntry(httpMethod, path)) => {
8079
// got to remove any path element specified in basepath
80+
val operation = readMethod(method, fullMethodName).get
8181
val basepathUrl = new java.net.URL(config.getBasePath)
8282
val basepath = basepathUrl.getPath
8383
val resourcePath = path.stripPrefix(basepath)
@@ -123,12 +123,20 @@ class PlayApiReader(val routes: Option[Routes]) extends JaxrsApiReader {
123123
}
124124

125125

126-
def readMethod(method: Method): Option[Operation] = {
126+
def readMethod(method: Method, fullMethodName: String): Option[Operation] = {
127127
val apiOperation = method.getAnnotation(classOf[ApiOperation])
128+
val routeEntry = routesCache.get(fullMethodName)
128129

129130
if (method.getAnnotation(classOf[ApiOperation]) != null) {
130131
Logger("swagger").debug("annotation: ApiOperation: %s,".format(apiOperation.toString))
131132

133+
val httpMethod = routeEntry.map(_.httpMethod).getOrElse(apiOperation.httpMethod)
134+
135+
val nickname = apiOperation.nickname match {
136+
case e: String if e.trim != "" => e
137+
case _ => genNickname(fullMethodName, routeEntry.map(_.httpMethod))
138+
}
139+
132140
val produces = apiOperation.produces match {
133141
case e: String if e.trim != "" => e.split(",").map(_.trim).toList
134142
case _ => List()
@@ -165,11 +173,11 @@ class PlayApiReader(val routes: Option[Routes]) extends JaxrsApiReader {
165173
val params = processParams(method)
166174

167175
Some(Operation(
168-
apiOperation.httpMethod,
176+
httpMethod,
169177
apiOperation.value,
170178
apiOperation.notes,
171179
responseClass,
172-
apiOperation.nickname,
180+
nickname,
173181
apiOperation.position,
174182
produces,
175183
consumes,
@@ -189,14 +197,15 @@ class PlayApiReader(val routes: Option[Routes]) extends JaxrsApiReader {
189197
case Some(e) => {
190198
(for (param <- e.value) yield {
191199
Logger("swagger").debug("processing " + param)
200+
val dataType = if (param.dataType.isEmpty) "String" else param.dataType
192201
val allowableValues = toAllowableValues(param.allowableValues)
193202
Parameter(
194203
param.name,
195204
Option(readString(param.value)),
196205
Option(param.defaultValue).filter(_.trim.nonEmpty),
197206
param.required,
198207
param.allowMultiple,
199-
param.dataType,
208+
dataType,
200209
allowableValues,
201210
param.paramType,
202211
Option(param.access).filter(_.trim.nonEmpty))
@@ -295,7 +304,7 @@ class PlayApiReader(val routes: Option[Routes]) extends JaxrsApiReader {
295304
}
296305
}
297306

298-
def routesCache = {
307+
def routesCache = synchronized {
299308
if (_routesCache == null) _routesCache = populateRoutesCache
300309
_routesCache
301310
}
@@ -325,6 +334,10 @@ class PlayApiReader(val routes: Option[Routes]) extends JaxrsApiReader {
325334
}
326335
}
327336

337+
def genNickname(fullMethodName: String, httpMethod: Option[String] = None): String = {
338+
httpMethod.getOrElse("") + "_" + fullMethodName.replace(".", "_")
339+
}
340+
328341
private def populateRoutesCache: Map[String, RouteEntry] = {
329342
val r = routes.get.documentation
330343
(for (route <- r) yield {

modules/swagger-play2/test/PlayApiReaderSpec.scala

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ class PlayApiReaderSpec extends Specification with Mockito {
8282
}
8383
}
8484

85+
def readDogMethod(name: String) = {
86+
val method = dogMethod(name).get
87+
val fullMethodName = reader.getFullMethodName(dogControllerClass, method)
88+
reader.readMethod(method, fullMethodName)
89+
}
90+
8591

8692
"with Object as Controller" should {
8793

@@ -159,193 +165,199 @@ class PlayApiReaderSpec extends Specification with Mockito {
159165
"readMethod with Object as controller" should {
160166

161167
"create Operation for annotated method" in {
162-
val maybeOperation: Option[Operation] = reader.readMethod(dogMethod("list").get)
168+
val maybeOperation: Option[Operation] = readDogMethod("list")
163169
maybeOperation.nonEmpty must beTrue
164170
}
165171

166172
"does not creates Operation when no annotation" in {
167-
val maybeOperation: Option[Operation] = reader.readMethod(dogMethod("no_annotations").get)
173+
val maybeOperation: Option[Operation] = readDogMethod("no_annotations")
168174
"an operation should not have been returned" ! maybeOperation.isEmpty
169175
}
170176

171177
"adds empty 'consumes' when not defined" in {
172-
val operation: Operation = reader.readMethod(dogMethod("add1").get).get
178+
val operation: Operation = readDogMethod("add1").get
173179
operation.consumes must beEqualTo(List.empty)
174180
}
175181

176182
"adds 'consumes' when defined and trims" in {
177-
val operation: Operation = reader.readMethod(dogMethod("add2").get).get
183+
val operation: Operation = readDogMethod("add2").get
178184
operation.consumes.length must beEqualTo(1)
179185
operation.consumes.head must beEqualTo("application/json")
180186
}
181187

182-
"adds mulitple 'consumes' when defined and trims" in {
183-
val operation: Operation = reader.readMethod(dogMethod("add3").get).get
188+
"adds multiple 'consumes' when defined and trims" in {
189+
val operation: Operation = readDogMethod("add3").get
184190
operation.consumes.length must beEqualTo(2)
185191
operation.consumes.contains("application/json") must beTrue
186192
operation.consumes.contains("text/yaml") must beTrue
187193
}
188194

189195
"adds empty 'authorizations' when not defined" in {
190-
val operation: Operation = reader.readMethod(dogMethod("add1").get).get
191-
operation.authorizations must beEqualTo(List.empty)
196+
val operation: Operation = readDogMethod("add1").get
197+
operation.authorizations must beEqualTo(Nil)
192198
}
193199

194200
"adds 'authorizations' when defined" in {
195-
val operation: Operation = reader.readMethod(dogMethod("add2").get).get
201+
val operation: Operation = readDogMethod("add2").get
196202
operation.authorizations.length must beEqualTo(1)
197-
operation.authorizations.head must beEqualTo("vet")
203+
operation.authorizations.head.`type` must beEqualTo("vet")
198204
}
199205

200-
"adds mulitple 'authorizations' when defined" in {
201-
val operation: Operation = reader.readMethod(dogMethod("add3").get).get
206+
"adds multiple 'authorizations' when defined" in {
207+
val operation: Operation = readDogMethod("add3").get
202208
operation.authorizations.length must beEqualTo(2)
203-
operation.authorizations.contains("vet") must beTrue
204-
operation.authorizations.contains("owner") must beTrue
209+
operation.authorizations.map(_.`type`).contains("vet") must beTrue
210+
operation.authorizations.map(_.`type`).contains("owner") must beTrue
205211
}
206212

207213
"adds empty 'produces' when not defined" in {
208-
val operation: Operation = reader.readMethod(get1Method).get
214+
val fullMethodName = reader.getFullMethodName(dogControllerClass, get1Method)
215+
val operation: Operation = reader.readMethod(get1Method, fullMethodName).get
209216
operation.produces must beEqualTo(List.empty)
210217
}
211218

212219
"adds 'produces' when defined and trims" in {
213-
val operation: Operation = reader.readMethod(get2Method).get
220+
val fullMethodName = reader.getFullMethodName(dogControllerClass, get2Method)
221+
val operation: Operation = reader.readMethod(get2Method, fullMethodName).get
214222
operation.produces.length must beEqualTo(1)
215223
operation.produces.head must beEqualTo("application/json")
216224
}
217225

218-
"adds mulitple 'produces' when defined and trims" in {
219-
val operation: Operation = reader.readMethod(get3Method).get
226+
"adds multiple 'produces' when defined and trims" in {
227+
val fullMethodName = reader.getFullMethodName(dogControllerClass, get3Method)
228+
val operation: Operation = reader.readMethod(get3Method, fullMethodName).get
220229
operation.produces.length must beEqualTo(2)
221230
operation.produces.contains("application/json") must beTrue
222231
operation.produces.contains("application/xml") must beTrue
223232
}
224233

225234
"adds 'protocols' when defined and trims" in {
226-
val operation: Operation = reader.readMethod(dogMethod("add2").get).get
235+
val operation: Operation = readDogMethod("add2").get
227236
operation.protocols.length must beEqualTo(1)
228237
operation.protocols.head must beEqualTo("http")
229238
}
230239

231-
"adds mulitple 'protocols' when defined and trims" in {
232-
val operation: Operation = reader.readMethod(dogMethod("add3").get).get
240+
"adds multiple 'protocols' when defined and trims" in {
241+
val operation: Operation = readDogMethod("add3").get
233242
operation.protocols.length must beEqualTo(2)
234243
operation.protocols.contains("http") must beTrue
235244
operation.protocols.contains("https") must beTrue
236245
}
237246

238247
"adds empty 'protocols' when not defined" in {
239-
val operation: Operation = reader.readMethod(dogMethod("add1").get).get
248+
val operation: Operation = readDogMethod("add1").get
240249
operation.protocols must beEqualTo(List.empty)
241250
}
242251

243252
"adds 'deprecated' when defined" in {
244-
val operation: Operation = reader.readMethod(dogMethod("deprecated").get).get
253+
val operation: Operation = readDogMethod("deprecated").get
245254
operation.deprecated must beEqualTo(Some("true"))
246255
}
247256

248257
"does not add 'deprecated' when not defined" in {
249-
val operation: Operation = reader.readMethod(dogMethod("add1").get).get
258+
val operation: Operation = readDogMethod("add1").get
250259
operation.deprecated must beEqualTo(None)
251260
}
252261

253262
"adds 'method' when defined" in {
254-
val operation: Operation = reader.readMethod(dogMethod("add1").get).get
263+
val operation: Operation = readDogMethod("add1").get
255264
operation.method must beEqualTo("PUT")
256265
}
257266

258267
"adds any-string for 'method' when defined" in {
259-
val operation: Operation = reader.readMethod(dogMethod("unknown_method").get).get
268+
val operation: Operation = readDogMethod("unknown_method").get
260269
operation.method must beEqualTo("UNKNOWN")
261270
}
262271

263272
"results in empty String for 'method' when not defined" in {
264-
val operation: Operation = reader.readMethod(dogMethod("undefined_method").get).get
273+
val operation: Operation = readDogMethod("undefined_method").get
265274
operation.method must beEqualTo("")
266275
}
267276

268-
"results in empty String for 'nickname' when not defined" in {
269-
val operation: Operation = reader.readMethod(dogMethod("add1").get).get
270-
operation.nickname must beEqualTo("")
277+
"results in httpMethod + fullMethodName for 'nickname' when not defined" in {
278+
val operation: Operation = readDogMethod("add1").get
279+
val fullMethodName = reader.getFullMethodName(dogControllerClass, dogMethod("add1").get)
280+
operation.nickname.toLowerCase must beEqualTo(reader.genNickname(fullMethodName, Some("PUT")).toLowerCase)
271281
}
272282

273283
"adds 'nickname' when defined" in {
274-
val operation: Operation = reader.readMethod(dogMethod("add2").get).get
284+
val operation: Operation = readDogMethod("add2").get
275285
operation.nickname must beEqualTo("addDog2_nickname")
276286
}
277287

278288
"results in empty String for 'notes' when not defined" in {
279-
val operation: Operation = reader.readMethod(dogMethod("add1").get).get
289+
val operation: Operation = readDogMethod("add1").get
280290
operation.notes must beEqualTo("")
281291
}
282292

283293
"adds 'notes' when defined" in {
284-
val operation: Operation = reader.readMethod(dogMethod("add2").get).get
294+
val operation: Operation = readDogMethod("add2").get
285295
operation.notes must beEqualTo("Adds a dogs better")
286296
}
287297

288298

289299
"adds 'summary' when defined in 'value'" in {
290-
val operation: Operation = reader.readMethod(dogMethod("add2").get).get
300+
val operation: Operation = readDogMethod("add2").get
291301
operation.summary must beEqualTo("addDog2")
292302
}
293303

294304
"defaults to 0 for 'position' when not defined" in {
295-
val operation: Operation = reader.readMethod(dogMethod("add1").get).get
305+
val operation: Operation = readDogMethod("add1").get
296306
operation.position must beEqualTo(0)
297307
}
298308

299309
"adds 'position' when defined" in {
300-
val operation: Operation = reader.readMethod(dogMethod("add2").get).get
310+
val operation: Operation = readDogMethod("add2").get
301311
operation.position must beEqualTo(2)
302312
}
303313

304314
"results in 0 'responseMessages' when not defined" in {
305-
val operation: Operation = reader.readMethod(dogMethod("add1").get).get
315+
val operation: Operation = readDogMethod("add1").get
306316
operation.responseMessages.length must beEqualTo(0)
307317
}
308318

309319
"results in 0 'responseMessages' when defined as empty array" in {
310-
val operation: Operation = reader.readMethod(dogMethod("add2").get).get
320+
val operation: Operation = readDogMethod("add2").get
311321
operation.responseMessages.length must beEqualTo(0)
312322
}
313323

314324
"adds multiple 'responseMessages' when defined" in {
315-
val operation: Operation = reader.readMethod(dogMethod("add3").get).get
325+
val operation: Operation = readDogMethod("add3").get
316326
operation.responseMessages.length must beEqualTo(2)
317327
operation.responseMessages.filter(responseMessage => responseMessage.code == 405).head.message must beEqualTo("Invalid input")
318328
operation.responseMessages.filter(responseMessage => responseMessage.code == 666).head.message must beEqualTo("Big Problem")
319329
}
320330

321331
"returns 'void' for 'responseClass' when not defined" in {
322-
val operation: Operation = reader.readMethod(dogMethod("add1").get).get
332+
val operation: Operation = readDogMethod("add1").get
323333
operation.responseClass must beEqualTo("java.lang.Void")
324334
}
325335

326336
"adds 'responseClass' when defined" in {
327-
val operation: Operation = reader.readMethod(get1Method).get
337+
val fullMethodName = reader.getFullMethodName(dogControllerClass, get1Method)
338+
val operation: Operation = reader.readMethod(get1Method, fullMethodName).get
328339
operation.responseClass must beEqualTo("test.testdata.Dog")
329340
}
330341

331342
"adds 'responseClass' correctly when defined as list" in {
332-
val operation = reader.readMethod(dogMethod("list").get).get
343+
val operation = readDogMethod("list").get
333344
operation.responseClass must beEqualTo("List[test.testdata.Dog]")
334345
}
335346

336347
"results in 0 'parameters' when not defined" in {
337-
val operation: Operation = reader.readMethod(dogMethod("list").get).get
348+
val operation: Operation = readDogMethod("list").get
338349
operation.parameters must beEqualTo(List.empty)
339350
}
340351

341352
"adds 'parameters' when defined by @ApiParam" in {
342-
val operation: Operation = reader.readMethod(get1Method).get
353+
val fullMethodName = reader.getFullMethodName(dogControllerClass, get1Method)
354+
val operation: Operation = reader.readMethod(get1Method, fullMethodName).get
343355
operation.parameters.length must beEqualTo(1)
344356
operation.parameters.head must beEqualTo(Parameter("dogId", Some("ID of dog to fetch"), None, true, false, "long", null, "path", None))
345357
}
346358

347359
"adds 'parameters' when defined by @ApiImplicitParams" in {
348-
val operation: Operation = reader.readMethod(dogMethod("add1").get).get
360+
val operation: Operation = readDogMethod("add1").get
349361
operation.parameters.length must beEqualTo(1)
350362
operation.parameters.head must beEqualTo(Parameter("dog", Some("Dog object to add"), None, true, false, "Dog", null, "body", None))
351363
}
@@ -355,7 +367,9 @@ class PlayApiReaderSpec extends Specification with Mockito {
355367
"readMethod with Class as controller" should {
356368

357369
"create Operation for annotated method" in {
358-
val maybeOperation: Option[Operation] = reader.readMethod(catMethod("list").get)
370+
val listMethod = catMethod("list").get
371+
val fullMethodName = reader.getFullMethodName(catControllerClass, listMethod)
372+
val maybeOperation: Option[Operation] = reader.readMethod(listMethod, fullMethodName)
359373
maybeOperation.nonEmpty must beTrue
360374
}
361375
}

modules/swagger-play2/test/testdata/CatController.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class CatController extends Controller {
1717

1818
@ApiOperation(value = "addCat1",
1919
httpMethod = "PUT",
20-
authorizations = "",
20+
authorizations = Array(),
2121
consumes = "",
2222
protocols = "")
2323
@ApiImplicitParams(Array(

0 commit comments

Comments
 (0)