andrea
Committed by Gerrit Code Review

[ONOS-2706] Insert Support for REST API model schema in Swagger UI

Change-Id: Iad158d90f203101fd23328f30f2507b7677a1997
...@@ -51,6 +51,7 @@ public class DhcpWebResource extends AbstractWebResource { ...@@ -51,6 +51,7 @@ public class DhcpWebResource extends AbstractWebResource {
51 * Shows lease, renewal and rebinding times in seconds. 51 * Shows lease, renewal and rebinding times in seconds.
52 * 52 *
53 * @return 200 OK 53 * @return 200 OK
54 + * @rsModel DhcpConfigGet
54 */ 55 */
55 @GET 56 @GET
56 @Path("config") 57 @Path("config")
...@@ -84,7 +85,6 @@ public class DhcpWebResource extends AbstractWebResource { ...@@ -84,7 +85,6 @@ public class DhcpWebResource extends AbstractWebResource {
84 } 85 }
85 86
86 87
87 -
88 /** 88 /**
89 * Get all available IPs. 89 * Get all available IPs.
90 * Shows all the IPs in the free pool of the DHCP Server. 90 * Shows all the IPs in the free pool of the DHCP Server.
...@@ -106,6 +106,7 @@ public class DhcpWebResource extends AbstractWebResource { ...@@ -106,6 +106,7 @@ public class DhcpWebResource extends AbstractWebResource {
106 * Post a new static MAC/IP binding. 106 * Post a new static MAC/IP binding.
107 * Registers a static binding to the DHCP server, and displays the current set of bindings. 107 * Registers a static binding to the DHCP server, and displays the current set of bindings.
108 * 108 *
109 + * @rsModel DhcpConfigPut
109 * @param stream JSON stream 110 * @param stream JSON stream
110 * @return 200 OK 111 * @return 200 OK
111 */ 112 */
...@@ -114,7 +115,6 @@ public class DhcpWebResource extends AbstractWebResource { ...@@ -114,7 +115,6 @@ public class DhcpWebResource extends AbstractWebResource {
114 @Consumes(MediaType.APPLICATION_JSON) 115 @Consumes(MediaType.APPLICATION_JSON)
115 public Response setMapping(InputStream stream) { 116 public Response setMapping(InputStream stream) {
116 ObjectNode root = mapper().createObjectNode(); 117 ObjectNode root = mapper().createObjectNode();
117 -
118 try { 118 try {
119 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); 119 ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
120 JsonNode macID = jsonTree.get("mac"); 120 JsonNode macID = jsonTree.get("mac");
...@@ -122,8 +122,10 @@ public class DhcpWebResource extends AbstractWebResource { ...@@ -122,8 +122,10 @@ public class DhcpWebResource extends AbstractWebResource {
122 if (macID != null && ip != null) { 122 if (macID != null && ip != null) {
123 123
124 if (!service.setStaticMapping(MacAddress.valueOf(macID.asText()), 124 if (!service.setStaticMapping(MacAddress.valueOf(macID.asText()),
125 - Ip4Address.valueOf(ip.asText()), false, Lists.newArrayList())) { 125 + Ip4Address.valueOf(ip.asText()),
126 - throw new IllegalArgumentException("Static Mapping Failed. The IP maybe unavailable."); 126 + false, Lists.newArrayList())) {
127 + throw new IllegalArgumentException("Static Mapping Failed. " +
128 + "The IP maybe unavailable.");
127 } 129 }
128 } 130 }
129 131
......
1 +{
2 + "type": "object",
3 + "required": [
4 + "leaseTime",
5 + "renewalTime",
6 + "rebindingTime"
7 + ],
8 + "properties": {
9 + "leaseTime": {
10 + "type": "integer",
11 + "format": "int64",
12 + "example": "250"
13 + },
14 + "renewalTime": {
15 + "type": "integer",
16 + "format": "int64",
17 + "example": "250"
18 + },
19 + "rebindingTime": {
20 + "type": "integer",
21 + "format": "int64",
22 + "example": "250"
23 + }
24 + }
25 +}
26 +
1 +{
2 + "type": "object",
3 + "required": [
4 + "mac",
5 + "ip"],
6 + "properties": {
7 + "mac": {
8 + "type": "String",
9 + "example": "be:48:89:d5:75:59"
10 + },
11 + "ip": {
12 + "type": "String",
13 + "example": "10.128.12.4"
14 + }
15 + }
16 +}
17 +
...@@ -49,7 +49,8 @@ ...@@ -49,7 +49,8 @@
49 <version>2.10.1</version> 49 <version>2.10.1</version>
50 <configuration> 50 <configuration>
51 <show>package</show> 51 <show>package</show>
52 - <excludePackageNames>@external-excludes</excludePackageNames> 52 + <excludePackageNames>@external-excludes
53 + </excludePackageNames>
53 <docfilessubdirs>true</docfilessubdirs> 54 <docfilessubdirs>true</docfilessubdirs>
54 <doctitle>ONOS Java API (1.4.0-SNAPSHOT)</doctitle> 55 <doctitle>ONOS Java API (1.4.0-SNAPSHOT)</doctitle>
55 <groups> 56 <groups>
...@@ -58,7 +59,8 @@ ...@@ -58,7 +59,8 @@
58 <packages>@external-apis</packages> 59 <packages>@external-apis</packages>
59 </group> 60 </group>
60 <group> 61 <group>
61 - <title>Incubator for Network Model &amp; Services</title> 62 + <title>Incubator for Network Model &amp; Services
63 + </title>
62 <packages>@external-incubator-apis</packages> 64 <packages>@external-incubator-apis</packages>
63 </group> 65 </group>
64 <group> 66 <group>
...@@ -66,6 +68,13 @@ ...@@ -66,6 +68,13 @@
66 <packages>@utils</packages> 68 <packages>@utils</packages>
67 </group> 69 </group>
68 </groups> 70 </groups>
71 + <tags>
72 + <tag>
73 + <name>rsModel</name>
74 + <placement>m</placement>
75 + <head>Json model for REST api:</head>
76 + </tag>
77 + </tags>
69 </configuration> 78 </configuration>
70 </plugin> 79 </plugin>
71 </plugins> 80 </plugins>
......
...@@ -51,14 +51,16 @@ ...@@ -51,14 +51,16 @@
51 <show>package</show> 51 <show>package</show>
52 <docfilessubdirs>true</docfilessubdirs> 52 <docfilessubdirs>true</docfilessubdirs>
53 <doctitle>ONOS Java API (1.4.0-SNAPSHOT)</doctitle> 53 <doctitle>ONOS Java API (1.4.0-SNAPSHOT)</doctitle>
54 - <excludePackageNames>@internal-excludes</excludePackageNames> 54 + <excludePackageNames>@internal-excludes
55 + </excludePackageNames>
55 <groups> 56 <groups>
56 <group> 57 <group>
57 <title>Network Model &amp; Services</title> 58 <title>Network Model &amp; Services</title>
58 <packages>@internal-apis</packages> 59 <packages>@internal-apis</packages>
59 </group> 60 </group>
60 <group> 61 <group>
61 - <title>Incubator for Network Model &amp; Services</title> 62 + <title>Incubator for Network Model &amp; Services
63 + </title>
62 <packages>@internal-incubator-apis</packages> 64 <packages>@internal-incubator-apis</packages>
63 </group> 65 </group>
64 <group> 66 <group>
...@@ -70,7 +72,9 @@ ...@@ -70,7 +72,9 @@
70 <packages>@internal-stores</packages> 72 <packages>@internal-stores</packages>
71 </group> 73 </group>
72 <group> 74 <group>
73 - <title>Incubator for Core Subsystems &amp; Distributed Stores</title> 75 + <title>Incubator for Core Subsystems &amp;
76 + Distributed Stores
77 + </title>
74 <packages>@internal-incubator</packages> 78 <packages>@internal-incubator</packages>
75 </group> 79 </group>
76 <group> 80 <group>
...@@ -114,10 +118,18 @@ ...@@ -114,10 +118,18 @@
114 <packages>@internal-apps</packages> 118 <packages>@internal-apps</packages>
115 </group> 119 </group>
116 <group> 120 <group>
117 - <title>Test Instrumentation &amp; Applications</title> 121 + <title>Test Instrumentation &amp; Applications
122 + </title>
118 <packages>@internal-test-apps</packages> 123 <packages>@internal-test-apps</packages>
119 </group> 124 </group>
120 </groups> 125 </groups>
126 + <tags>
127 + <tag>
128 + <name>rsModel</name>
129 + <placement>m</placement>
130 + <head>Json model for REST api:</head>
131 + </tag>
132 + </tags>
121 </configuration> 133 </configuration>
122 </plugin> 134 </plugin>
123 </plugins> 135 </plugins>
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
39 <description>Open Network Operating System root project</description> 39 <description>Open Network Operating System root project</description>
40 40
41 <modules> 41 <modules>
42 + <module>tools/package/maven-plugin</module>
42 <module>utils</module> 43 <module>utils</module>
43 <module>core</module> 44 <module>core</module>
44 <module>web</module> 45 <module>web</module>
...@@ -545,7 +546,20 @@ ...@@ -545,7 +546,20 @@
545 <rerunFailingTestsCount>1</rerunFailingTestsCount> 546 <rerunFailingTestsCount>1</rerunFailingTestsCount>
546 </configuration> 547 </configuration>
547 </plugin> 548 </plugin>
548 - 549 + <plugin>
550 + <groupId>org.apache.maven.plugins</groupId>
551 + <artifactId>maven-javadoc-plugin</artifactId>
552 + <version>2.10.3</version>
553 + <configuration>
554 + <tags>
555 + <tag>
556 + <name>rsModel</name>
557 + <placement>m</placement>
558 + <head>Json model for REST api:</head>
559 + </tag>
560 + </tags>
561 + </configuration>
562 + </plugin>
549 <plugin> 563 <plugin>
550 <groupId>org.apache.maven.plugins</groupId> 564 <groupId>org.apache.maven.plugins</groupId>
551 <artifactId>maven-jar-plugin</artifactId> 565 <artifactId>maven-jar-plugin</artifactId>
...@@ -631,7 +645,7 @@ ...@@ -631,7 +645,7 @@
631 <plugin> 645 <plugin>
632 <groupId>org.onosproject</groupId> 646 <groupId>org.onosproject</groupId>
633 <artifactId>onos-maven-plugin</artifactId> 647 <artifactId>onos-maven-plugin</artifactId>
634 - <version>1.5</version> 648 + <version>1.6-SNAPSHOT</version>
635 <executions> 649 <executions>
636 <execution> 650 <execution>
637 <id>cfg</id> 651 <id>cfg</id>
......
...@@ -85,6 +85,11 @@ ...@@ -85,6 +85,11 @@
85 <artifactId>jackson-annotations</artifactId> 85 <artifactId>jackson-annotations</artifactId>
86 <version>2.4.2</version> 86 <version>2.4.2</version>
87 </dependency> 87 </dependency>
88 + <dependency>
89 + <groupId>commons-io</groupId>
90 + <artifactId>commons-io</artifactId>
91 + <version>2.4</version>
92 + </dependency>
88 </dependencies> 93 </dependencies>
89 94
90 <build> 95 <build>
......
...@@ -18,6 +18,7 @@ package org.onosproject.maven; ...@@ -18,6 +18,7 @@ package org.onosproject.maven;
18 import com.fasterxml.jackson.databind.ObjectMapper; 18 import com.fasterxml.jackson.databind.ObjectMapper;
19 import com.fasterxml.jackson.databind.node.ArrayNode; 19 import com.fasterxml.jackson.databind.node.ArrayNode;
20 import com.fasterxml.jackson.databind.node.ObjectNode; 20 import com.fasterxml.jackson.databind.node.ObjectNode;
21 +import com.google.common.base.Charsets;
21 import com.google.common.io.ByteStreams; 22 import com.google.common.io.ByteStreams;
22 import com.google.common.io.Files; 23 import com.google.common.io.Files;
23 import com.thoughtworks.qdox.JavaProjectBuilder; 24 import com.thoughtworks.qdox.JavaProjectBuilder;
...@@ -124,11 +125,13 @@ public class OnosSwaggerMojo extends AbstractMojo { ...@@ -124,11 +125,13 @@ public class OnosSwaggerMojo extends AbstractMojo {
124 ObjectNode root = initializeRoot(); 125 ObjectNode root = initializeRoot();
125 ArrayNode tags = mapper.createArrayNode(); 126 ArrayNode tags = mapper.createArrayNode();
126 ObjectNode paths = mapper.createObjectNode(); 127 ObjectNode paths = mapper.createObjectNode();
128 + ObjectNode definitions = mapper.createObjectNode();
127 129
128 root.set("tags", tags); 130 root.set("tags", tags);
129 root.set("paths", paths); 131 root.set("paths", paths);
132 + root.set("definitions", definitions);
130 133
131 - builder.getClasses().forEach(jc -> processClass(jc, paths, tags)); 134 + builder.getClasses().forEach(jc -> processClass(jc, paths, tags, definitions));
132 135
133 if (paths.size() > 0) { 136 if (paths.size() > 0) {
134 getLog().info("Generating ONOS REST API documentation..."); 137 getLog().info("Generating ONOS REST API documentation...");
...@@ -172,7 +175,7 @@ public class OnosSwaggerMojo extends AbstractMojo { ...@@ -172,7 +175,7 @@ public class OnosSwaggerMojo extends AbstractMojo {
172 175
173 // Checks whether javaClass has a path tag associated with it and if it does 176 // Checks whether javaClass has a path tag associated with it and if it does
174 // processes its methods and creates a tag for the class on the root 177 // processes its methods and creates a tag for the class on the root
175 - void processClass(JavaClass javaClass, ObjectNode paths, ArrayNode tags) { 178 + void processClass(JavaClass javaClass, ObjectNode paths, ArrayNode tags, ObjectNode definitions) {
176 // If the class does not have a Path tag then ignore it 179 // If the class does not have a Path tag then ignore it
177 JavaAnnotation annotation = getPathAnnotation(javaClass); 180 JavaAnnotation annotation = getPathAnnotation(javaClass);
178 if (annotation == null) { 181 if (annotation == null) {
...@@ -199,7 +202,7 @@ public class OnosSwaggerMojo extends AbstractMojo { ...@@ -199,7 +202,7 @@ public class OnosSwaggerMojo extends AbstractMojo {
199 ArrayNode tagArray = mapper.createArrayNode(); 202 ArrayNode tagArray = mapper.createArrayNode();
200 tagArray.add(tagPath); 203 tagArray.add(tagPath);
201 204
202 - processAllMethods(javaClass, resourcePath, paths, tagArray); 205 + processAllMethods(javaClass, resourcePath, paths, tagArray, definitions);
203 } 206 }
204 207
205 private JavaAnnotation getPathAnnotation(JavaClass javaClass) { 208 private JavaAnnotation getPathAnnotation(JavaClass javaClass) {
...@@ -211,7 +214,7 @@ public class OnosSwaggerMojo extends AbstractMojo { ...@@ -211,7 +214,7 @@ public class OnosSwaggerMojo extends AbstractMojo {
211 // Checks whether a class's methods are REST methods and then places all the 214 // Checks whether a class's methods are REST methods and then places all the
212 // methods under a specific path into the paths node 215 // methods under a specific path into the paths node
213 private void processAllMethods(JavaClass javaClass, String resourcePath, 216 private void processAllMethods(JavaClass javaClass, String resourcePath,
214 - ObjectNode paths, ArrayNode tagArray) { 217 + ObjectNode paths, ArrayNode tagArray, ObjectNode definitions) {
215 // map of the path to its methods represented by an ObjectNode 218 // map of the path to its methods represented by an ObjectNode
216 Map<String, ObjectNode> pathMap = new HashMap<>(); 219 Map<String, ObjectNode> pathMap = new HashMap<>();
217 220
...@@ -221,7 +224,7 @@ public class OnosSwaggerMojo extends AbstractMojo { ...@@ -221,7 +224,7 @@ public class OnosSwaggerMojo extends AbstractMojo {
221 if (name.equals(POST) || name.equals(GET) || name.equals(DELETE) || name.equals(PUT)) { 224 if (name.equals(POST) || name.equals(GET) || name.equals(DELETE) || name.equals(PUT)) {
222 // substring(12) removes "javax.ws.rs." 225 // substring(12) removes "javax.ws.rs."
223 String method = annotation.getType().toString().substring(12).toLowerCase(); 226 String method = annotation.getType().toString().substring(12).toLowerCase();
224 - processRestMethod(javaMethod, method, pathMap, resourcePath, tagArray); 227 + processRestMethod(javaMethod, method, pathMap, resourcePath, tagArray, definitions);
225 } 228 }
226 }); 229 });
227 }); 230 });
...@@ -236,9 +239,10 @@ public class OnosSwaggerMojo extends AbstractMojo { ...@@ -236,9 +239,10 @@ public class OnosSwaggerMojo extends AbstractMojo {
236 239
237 private void processRestMethod(JavaMethod javaMethod, String method, 240 private void processRestMethod(JavaMethod javaMethod, String method,
238 Map<String, ObjectNode> pathMap, 241 Map<String, ObjectNode> pathMap,
239 - String resourcePath, ArrayNode tagArray) { 242 + String resourcePath, ArrayNode tagArray, ObjectNode definitions) {
240 String fullPath = resourcePath, consumes = "", produces = "", 243 String fullPath = resourcePath, consumes = "", produces = "",
241 comment = javaMethod.getComment(); 244 comment = javaMethod.getComment();
245 + DocletTag tag = javaMethod.getTagByName("rsModel");
242 for (JavaAnnotation annotation : javaMethod.getAnnotations()) { 246 for (JavaAnnotation annotation : javaMethod.getAnnotations()) {
243 String name = annotation.getType().getName(); 247 String name = annotation.getType().getName();
244 if (name.equals(PATH)) { 248 if (name.equals(PATH)) {
...@@ -256,12 +260,19 @@ public class OnosSwaggerMojo extends AbstractMojo { ...@@ -256,12 +260,19 @@ public class OnosSwaggerMojo extends AbstractMojo {
256 methodNode.set("tags", tagArray); 260 methodNode.set("tags", tagArray);
257 261
258 addSummaryDescriptions(methodNode, comment); 262 addSummaryDescriptions(methodNode, comment);
259 - processParameters(javaMethod, methodNode); 263 + addJsonSchemaDefinition(definitions, tag);
264 + addJsonSchemaDefinition(definitions, tag);
265 +
266 + processParameters(javaMethod, methodNode, method, tag);
260 267
261 processConsumesProduces(methodNode, "consumes", consumes); 268 processConsumesProduces(methodNode, "consumes", consumes);
262 processConsumesProduces(methodNode, "produces", produces); 269 processConsumesProduces(methodNode, "produces", produces);
263 - 270 + if (tag == null || ((method.toLowerCase().equals("post") || method.toLowerCase().equals("put"))
264 - addResponses(methodNode); 271 + && !(tag.getParameters().size() > 1))) {
272 + addResponses(methodNode, tag, false);
273 + } else {
274 + addResponses(methodNode, tag, true);
275 + }
265 276
266 ObjectNode operations = pathMap.get(fullPath); 277 ObjectNode operations = pathMap.get(fullPath);
267 if (operations == null) { 278 if (operations == null) {
...@@ -273,6 +284,24 @@ public class OnosSwaggerMojo extends AbstractMojo { ...@@ -273,6 +284,24 @@ public class OnosSwaggerMojo extends AbstractMojo {
273 } 284 }
274 } 285 }
275 286
287 + private void addJsonSchemaDefinition(ObjectNode definitions, DocletTag tag) {
288 + File definitionsDirectory = new File(srcDirectory + "/src/main/resources/definitions");
289 + if (tag != null) {
290 + tag.getParameters().stream().forEach(param -> {
291 + try {
292 + File config = new File(definitionsDirectory.getAbsolutePath() + "/"
293 + + param + ".json");
294 + String lines = Files.readLines(config, Charsets.UTF_8).stream().reduce((t, u) -> t + u).
295 + get();
296 + definitions.putPOJO(param, lines);
297 + } catch (IOException e) {
298 + e.printStackTrace();
299 + }
300 + });
301 +
302 + }
303 + }
304 +
276 private void processConsumesProduces(ObjectNode methodNode, String type, String io) { 305 private void processConsumesProduces(ObjectNode methodNode, String type, String io) {
277 if (!io.equals("")) { 306 if (!io.equals("")) {
278 ArrayNode array = mapper.createArrayNode(); 307 ArrayNode array = mapper.createArrayNode();
...@@ -299,13 +328,19 @@ public class OnosSwaggerMojo extends AbstractMojo { ...@@ -299,13 +328,19 @@ public class OnosSwaggerMojo extends AbstractMojo {
299 328
300 // Temporary solution to add responses to a method 329 // Temporary solution to add responses to a method
301 // TODO Provide annotations in the web resources for responses and parse them 330 // TODO Provide annotations in the web resources for responses and parse them
302 - private void addResponses(ObjectNode methodNode) { 331 + private void addResponses(ObjectNode methodNode, DocletTag tag, boolean responseJson) {
303 ObjectNode responses = mapper.createObjectNode(); 332 ObjectNode responses = mapper.createObjectNode();
304 methodNode.set("responses", responses); 333 methodNode.set("responses", responses);
305 334
306 ObjectNode success = mapper.createObjectNode(); 335 ObjectNode success = mapper.createObjectNode();
307 success.put("description", "successful operation"); 336 success.put("description", "successful operation");
308 responses.set("200", success); 337 responses.set("200", success);
338 + if (tag != null && responseJson) {
339 + ObjectNode schema = mapper.createObjectNode();
340 + tag.getParameters().stream().forEach(
341 + param -> schema.put("$ref", "#/definitions/" + param));
342 + success.set("schema", schema);
343 + }
309 344
310 ObjectNode defaultObj = mapper.createObjectNode(); 345 ObjectNode defaultObj = mapper.createObjectNode();
311 defaultObj.put("description", "Unexpected error"); 346 defaultObj.put("description", "Unexpected error");
...@@ -329,7 +364,7 @@ public class OnosSwaggerMojo extends AbstractMojo { ...@@ -329,7 +364,7 @@ public class OnosSwaggerMojo extends AbstractMojo {
329 } 364 }
330 365
331 // Processes parameters of javaMethod and enters the proper key-values into the methodNode 366 // Processes parameters of javaMethod and enters the proper key-values into the methodNode
332 - private void processParameters(JavaMethod javaMethod, ObjectNode methodNode) { 367 + private void processParameters(JavaMethod javaMethod, ObjectNode methodNode, String method, DocletTag tag) {
333 ArrayNode parameters = mapper.createArrayNode(); 368 ArrayNode parameters = mapper.createArrayNode();
334 methodNode.set("parameters", parameters); 369 methodNode.set("parameters", parameters);
335 boolean required = true; 370 boolean required = true;
...@@ -346,7 +381,8 @@ public class OnosSwaggerMojo extends AbstractMojo { ...@@ -346,7 +381,8 @@ public class OnosSwaggerMojo extends AbstractMojo {
346 381
347 if (pathType != null) { //the parameter is a path or query parameter 382 if (pathType != null) { //the parameter is a path or query parameter
348 individualParameterNode.put("name", 383 individualParameterNode.put("name",
349 - pathType.getNamedParameter("value").toString().replace("\"", "")); 384 + pathType.getNamedParameter("value")
385 + .toString().replace("\"", ""));
350 if (pathType.getType().getName().equals(PATH_PARAM)) { 386 if (pathType.getType().getName().equals(PATH_PARAM)) {
351 individualParameterNode.put("in", "path"); 387 individualParameterNode.put("in", "path");
352 } else if (pathType.getType().getName().equals(QUERY_PARAM)) { 388 } else if (pathType.getType().getName().equals(QUERY_PARAM)) {
...@@ -357,11 +393,17 @@ public class OnosSwaggerMojo extends AbstractMojo { ...@@ -357,11 +393,17 @@ public class OnosSwaggerMojo extends AbstractMojo {
357 individualParameterNode.put("name", annotationName); 393 individualParameterNode.put("name", annotationName);
358 individualParameterNode.put("in", "body"); 394 individualParameterNode.put("in", "body");
359 395
360 - // TODO add actual hardcoded schemas and a type 396 + // Adds the reference to the Json model for the input
361 - // body parameters must have a schema associated with them 397 + // that goes in the post or put operation
362 - ArrayNode schema = mapper.createArrayNode(); 398 + if (tag != null && (method.toLowerCase().equals("post") ||
399 + method.toLowerCase().equals("put"))) {
400 + ObjectNode schema = mapper.createObjectNode();
401 + tag.getParameters().stream().forEach(param -> {
402 + schema.put("$ref", "#/definitions/" + param);
403 + });
363 individualParameterNode.set("schema", schema); 404 individualParameterNode.set("schema", schema);
364 } 405 }
406 + }
365 for (DocletTag p : javaMethod.getTagsByName("param")) { 407 for (DocletTag p : javaMethod.getTagsByName("param")) {
366 if (p.getValue().contains(annotationName)) { 408 if (p.getValue().contains(annotationName)) {
367 try { 409 try {
......