View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.rest;
18  
19  import static org.apache.juneau.TestUtils.*;
20  import static org.junit.jupiter.api.Assertions.*;
21  
22  import java.io.*;
23  import java.util.*;
24  
25  import org.apache.juneau.*;
26  import org.apache.juneau.annotation.*;
27  import org.apache.juneau.cp.*;
28  import org.apache.juneau.http.annotation.*;
29  import org.apache.juneau.http.annotation.Tag;
30  import org.apache.juneau.json.*;
31  import org.apache.juneau.rest.annotation.*;
32  import org.apache.juneau.rest.mock.*;
33  import org.apache.juneau.rest.servlet.*;
34  import org.apache.juneau.rest.staticfile.*;
35  import org.apache.juneau.rest.swagger.*;
36  import org.apache.juneau.xml.*;
37  import org.junit.jupiter.api.*;
38  
39  class Swagger_Test extends TestBase {
40  
41  	//------------------------------------------------------------------------------------------------------------------
42  	// Setup
43  	//------------------------------------------------------------------------------------------------------------------
44  
45  	public void testMethod() { /* no-op */ }
46  
47  	private org.apache.juneau.bean.swagger.Swagger getSwaggerWithFile(Object resource) throws Exception {
48  		var rc = RestContext.create(resource.getClass(),null,null).init(()->resource).defaultClasses(TestClasspathFileFinder.class).build();
49  		var roc = RestOpContext.create(Swagger_Test.class.getMethod("testMethod"), rc).build();
50  		var call = RestSession.create(rc).resource(resource).req(new MockServletRequest()).res(new MockServletResponse()).build();
51  		var req = roc.createRequest(call);
52  		var ip = rc.getSwaggerProvider();
53  		return ip.getSwagger(rc, req.getLocale());
54  	}
55  
56  	private static org.apache.juneau.bean.swagger.Swagger getSwagger(Object resource) throws Exception {
57  		var rc = RestContext.create(resource.getClass(),null,null).init(()->resource).build();
58  		var roc = RestOpContext.create(Swagger_Test.class.getMethod("testMethod"), rc).build();
59  		var call = RestSession.create(rc).resource(resource).req(new MockServletRequest()).res(new MockServletResponse()).build();
60  		var req = roc.createRequest(call);
61  		var ip = rc.getSwaggerProvider();
62  		return ip.getSwagger(rc, req.getLocale());
63  	}
64  
65  	public static class TestClasspathFileFinder extends BasicStaticFiles {
66  
67  		public TestClasspathFileFinder() {
68  			super(StaticFiles.create(BeanStore.INSTANCE).cp(Swagger_Test.class, null, false));
69  		}
70  
71  		@Override /* FileFinder */
72  		public Optional<InputStream> getStream(String name, Locale locale) throws IOException {
73  			if (name.endsWith(".json"))
74  				return opt(SwaggerProvider.class.getResourceAsStream("BasicRestInfoProviderTest_swagger.json"));
75  			return super.getStream(name, locale);
76  		}
77  	}
78  
79  	//------------------------------------------------------------------------------------------------------------------
80  	// /<root>
81  	//------------------------------------------------------------------------------------------------------------------
82  
83  	@Rest
84  	public static class A1 {}
85  
86  	@Test void a01_swagger_default() throws Exception {
87  		assertBean(getSwagger(new A1()), "swagger,host,basePath,schemes", "2.0,<null>,<null>,<null>");
88  	}
89  	@Test void a01_swagger_default_withFile() throws Exception {
90  		assertBean(getSwaggerWithFile(new A1()), "swagger,host,basePath,schemes", "0.0,s-host,s-basePath,[s-scheme]");
91  	}
92  
93  
94  	@Rest(swagger=@Swagger("{swagger:'3.0',host:'a-host',basePath:'a-basePath',schemes:['a-scheme']}"))
95  	public static class A2 {}
96  
97  	@Test void a02_swagger_Swagger_value() throws Exception {
98  		assertBean(getSwagger(new A2()), "swagger,host,basePath,schemes", "3.0,a-host,a-basePath,[a-scheme]");
99  	}
100 	@Test void a02_swagger_Swagger_value_withFile() throws Exception {
101 		assertBean(getSwaggerWithFile(new A2()), "swagger,host,basePath,schemes", "3.0,a-host,a-basePath,[a-scheme]");
102 	}
103 
104 	//------------------------------------------------------------------------------------------------------------------
105 	// /info
106 	//------------------------------------------------------------------------------------------------------------------
107 
108 	@Rest(
109 		title="a-title",
110 		description="a-description"
111 	)
112 	public static class B1 {}
113 
114 	@Test void b01a_info_Rest() throws Exception {
115 		assertBean(
116 			getSwagger(new B1()).getInfo(),
117 			"title,description,version,termsOfService,contact,license",
118 			"a-title,a-description,<null>,<null>,<null>,<null>"
119 		);
120 	}
121 
122 	@Test void b01b_info_Rest_withFile() throws Exception {
123 		assertBean(
124 			getSwaggerWithFile(new B1()).getInfo(),
125 			"title,description,version,termsOfService,contact{name,url,email},license{name,url}",
126 			"s-title,s-description,0.0.0,s-termsOfService,{s-name,s-url,s-email},{s-name,s-url}"
127 		);
128 	}
129 
130 	@Rest(
131 		messages="BasicRestInfoProviderTest",
132 		title="$L{foo}",
133 		description="$L{foo}"
134 	)
135 	public static class B2 {}
136 
137 	@Test void b02a_info_Rest_localized() throws Exception {
138 		assertBean(getSwagger(new B2()).getInfo(), "title,description", "l-foo,l-foo");
139 	}
140 	@Test void b02b_info_Rest_localized_withFile() throws Exception {
141 		assertBean(getSwaggerWithFile(new B2()).getInfo(), "title,description", "s-title,s-description");
142 	}
143 
144 	@Rest(
145 		title="a-title",
146 		description="a-description",
147 		swagger=@Swagger(
148 			{
149 				"info:{",
150 					"title:'b-title',",
151 					"description:'b-description',",
152 					"version:'2.0.0',",
153 					"termsOfService:'a-termsOfService',",
154 					"contact:{name:'a-name',url:'a-url',email:'a-email'},",
155 					"license:{name:'a-name',url:'a-url'}",
156 				"}"
157 			}
158 		)
159 	)
160 	public static class B3 {}
161 
162 	@Test void b03a_info_Swagger_value() throws Exception {
163 		assertBean(
164 			getSwagger(new B3()).getInfo(),
165 			"title,description,version,termsOfService,contact{name,url,email},license{name,url}",
166 			"b-title,b-description,2.0.0,a-termsOfService,{a-name,a-url,a-email},{a-name,a-url}"
167 		);
168 	}
169 	@Test void b03b_info_Swagger_value_withFile() throws Exception {
170 		assertBean(
171 			getSwaggerWithFile(new B3()).getInfo(),
172 			"title,description,version,termsOfService,contact{name,url,email},license{name,url}",
173 			"b-title,b-description,2.0.0,a-termsOfService,{a-name,a-url,a-email},{a-name,a-url}"
174 		);
175 	}
176 
177 	@Rest(
178 		messages="BasicRestInfoProviderTest",
179 		title="a-title",
180 		description="a-description",
181 		swagger=@Swagger("{info:{title:'$L{bar}',description:'$L{bar}'}}")
182 	)
183 	public static class B4 {}
184 
185 	@Test void b04_info_Swagger_value_localised() throws Exception {
186 		assertBean(getSwagger(new B4()), "info{title,description}", "{l-bar,l-bar}");
187 		assertBean(getSwaggerWithFile(new B4()), "info{title,description}", "{l-bar,l-bar}");
188 	}
189 
190 	@Rest(
191 		title="a-title",
192 		description="a-description",
193 		swagger=@Swagger(
194 			value= {
195 				"info:{",
196 					"title:'b-title',",
197 					"description:'b-description',",
198 					"version:'2.0.0',",
199 					"termsOfService:'a-termsOfService',",
200 					"contact:{name:'a-name',url:'a-url',email:'a-email'},",
201 					"license:{name:'a-name',url:'a-url'}",
202 				"}"
203 			},
204 			title="c-title",
205 			description="c-description",
206 			version="3.0.0",
207 			termsOfService="b-termsOfService",
208 			contact=@Contact(name="b-name",url="b-url",email="b-email"),
209 			license=@License(name="b-name",url="b-url")
210 		)
211 	)
212 	public static class B5 {}
213 
214 	@Test void b05a_info_Swagger_title() throws Exception {
215 		var x = getSwagger(new B5()).getInfo();
216 		assertBean(
217 			x,
218 			"title,description,version,termsOfService,contact{name,url,email},license{name,url}",
219 			"c-title,c-description,3.0.0,b-termsOfService,{b-name,b-url,b-email},{b-name,b-url}"
220 		);
221 	}
222 	@Test void b05b_info_Swagger_title_withFile() throws Exception {
223 		var x = getSwaggerWithFile(new B5()).getInfo();
224 		assertBean(
225 			x,
226 			"title,description,version,termsOfService,contact{name,url,email},license{name,url}",
227 			"c-title,c-description,3.0.0,b-termsOfService,{b-name,b-url,b-email},{b-name,b-url}"
228 		);
229 	}
230 
231 	@Rest(
232 		title="a-title",
233 		description="a-description",
234 		swagger=@Swagger(
235 			value= {
236 				"info:{",
237 					"title:'b-title',",
238 					"description:'b-description',",
239 					"version:'2.0.0',",
240 					"termsOfService:'a-termsOfService',",
241 					"contact:{name:'a-name',url:'a-url',email:'a-email'},",
242 					"license:{name:'a-name',url:'a-url'}",
243 				"}"
244 			},
245 			title="$L{baz}",
246 			description="$L{baz}",
247 			version="$L{foo}",
248 			termsOfService="$L{foo}",
249 			contact=@Contact(name="$L{foo}",url="$L{bar}",email="$L{baz}"),
250 			license=@License(name="$L{foo}",url="$L{bar}")
251 		),
252 		messages="BasicRestInfoProviderTest"
253 	)
254 	public static class B6 {}
255 
256 	@Test void b06a_info_Swagger_title_localized() throws Exception {
257 		assertBean(
258 			getSwagger(new B6()).getInfo(),
259 			"title,description,version,termsOfService,contact{name,url,email},license{name,url}",
260 			"l-baz,l-baz,l-foo,l-foo,{l-foo,l-bar,l-baz},{l-foo,l-bar}"
261 		);
262 	}
263 	@Test void b06b_info_Swagger_title_localized_withFile() throws Exception {
264 		assertBean(
265 			getSwaggerWithFile(new B6()).getInfo(),
266 			"title,description,version,termsOfService,contact{name,url,email},license{name,url}",
267 			"l-baz,l-baz,l-foo,l-foo,{l-foo,l-bar,l-baz},{l-foo,l-bar}"
268 		);
269 	}
270 
271 	@Rest(
272 		swagger=@Swagger(
273 			title="c-title",
274 			description="c-description"
275 		)
276 	)
277 	public static class B07 {}
278 
279 	@Test void b07a_title_Swagger_title_only() throws Exception {
280 		assertBean(getSwagger(new B07()).getInfo(), "title,description", "c-title,c-description");
281 	}
282 	@Test void b07b_title_Swagger_title_only_withFile() throws Exception {
283 		assertBean(getSwaggerWithFile(new B07()).getInfo(), "title,description", "c-title,c-description");
284 	}
285 
286 	//------------------------------------------------------------------------------------------------------------------
287 	// /tags
288 	//------------------------------------------------------------------------------------------------------------------
289 
290 	@Rest
291 	public static class C1 {}
292 
293 	@Test void c01a_tags_default() throws Exception {
294 		assertNull(getSwagger(new C1()).getTags());
295 	}
296 	@Test void c01b_tags_default_withFile() throws Exception {
297 		var x = getSwaggerWithFile(new C1());
298 		assertBeans(
299 			x.getTags(),
300 			"name,description,externalDocs{description,url}",
301 			"s-name,s-description,{s-description,s-url}"
302 		);
303 	}
304 
305 	// Tags in @ResourceSwagger(value) should override file.
306 	@Rest(
307 		swagger=@Swagger(
308 			"{tags:[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}}]}"
309 		)
310 	)
311 	public static class C2 {}
312 
313 	@Test void c02a_tags_Swagger_value() throws Exception {
314 		assertBeans(
315 			getSwagger(new C2()).getTags(),
316 			"name,description,externalDocs{description,url}",
317 			"a-name,a-description,{a-description,a-url}"
318 		);
319 	}
320 	@Test void c02b_tags_Swagger_value_withFile() throws Exception {
321 		assertBeans(
322 			getSwaggerWithFile(new C2()).getTags(),
323 			"name,description,externalDocs{description,url}",
324 			"a-name,a-description,{a-description,a-url}"
325 		);
326 	}
327 
328 	// Tags in both @ResourceSwagger(value) and @ResourceSwagger(tags) should accumulate.
329 	@Rest(
330 		swagger=@Swagger(
331 			value="{tags:[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}}]}",
332 			tags=@Tag(name="b-name",description="b-description",externalDocs=@ExternalDocs(description="b-description",url="b-url"))
333 		)
334 	)
335 	public static class C3 {}
336 
337 	@Test void c03a_tags_Swagger_tags() throws Exception {
338 		assertBeans(
339 			getSwagger(new C3()).getTags(),
340 			"name,description,externalDocs{description,url}",
341 			"a-name,a-description,{a-description,a-url}",
342 			"b-name,b-description,{b-description,b-url}"
343 		);
344 	}
345 	@Test void c03b_tags_Swagger_tags_withFile() throws Exception {
346 		assertBeans(
347 			getSwaggerWithFile(new C3()).getTags(),
348 			"name,description,externalDocs{description,url}",
349 			"a-name,a-description,{a-description,a-url}",
350 			"b-name,b-description,{b-description,b-url}"
351 		);
352 	}
353 
354 	// Same as above but without [] outer characters.
355 	@Rest(
356 		swagger=@Swagger(
357 			value="{tags:[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}}]}",
358 			tags=@Tag(name="b-name",description="b-description", externalDocs=@ExternalDocs(description="b-description",url="b-url"))
359 		)
360 	)
361 	public static class C4 {}
362 
363 	@Test void c04a_tags_Swagger_tags() throws Exception {
364 		assertBeans(
365 			getSwagger(new C4()).getTags(),
366 			"name,description,externalDocs{description,url}",
367 			"a-name,a-description,{a-description,a-url}",
368 			"b-name,b-description,{b-description,b-url}"
369 		);
370 	}
371 	@Test void c04b_tags_Swagger_tags_withFile() throws Exception {
372 		assertBeans(
373 			getSwaggerWithFile(new C4()).getTags(),
374 			"name,description,externalDocs{description,url}",
375 			"a-name,a-description,{a-description,a-url}",
376 			"b-name,b-description,{b-description,b-url}"
377 		);
378 	}
379 
380 	// Tags in both Swagger.json and @ResourceSwagger(tags) should accumulate.
381 	@Rest(
382 		swagger=@Swagger(
383 			tags=@Tag(name="b-name",description="b-description",externalDocs=@ExternalDocs(description="b-description",url="b-url"))
384 		)
385 	)
386 	public static class C5 {}
387 
388 	@Test void c05a_tags_Swagger_tags_only() throws Exception {
389 		assertBeans(
390 			getSwagger(new C5()).getTags(),
391 			"name,description,externalDocs{description,url}",
392 			"b-name,b-description,{b-description,b-url}"
393 		);
394 	}
395 	@Test void c05b_tags_Swagger_tags_only_witFile() throws Exception {
396 		assertBeans(
397 			getSwaggerWithFile(new C5()).getTags(),
398 			"name,description,externalDocs{description,url}",
399 			"s-name,s-description,{s-description,s-url}",
400 			"b-name,b-description,{b-description,b-url}"
401 		);
402 	}
403 
404 	// Dup tag names should be overwritten
405 	@Rest(
406 		swagger=@Swagger(
407 			tags={
408 				@Tag(name="s-name",description="b-description",externalDocs=@ExternalDocs(description="b-description",url="b-url")),
409 				@Tag(name="s-name",description="c-description",externalDocs=@ExternalDocs(description="c-description",url="c-url"))
410 			}
411 		)
412 	)
413 	public static class C6 {}
414 
415 	@Test void c06a_tags_Swagger_tags_dups() throws Exception {
416 		assertBeans(
417 			getSwagger(new C6()).getTags(),
418 			"name,description,externalDocs{description,url}",
419 			"s-name,c-description,{c-description,c-url}"
420 		);
421 	}
422 	@Test void c06b_tags_Swagger_tags_dups_withFile() throws Exception {
423 		assertBeans(
424 			getSwaggerWithFile(new C6()).getTags(),
425 			"name,description,externalDocs{description,url}",
426 			"s-name,c-description,{c-description,c-url}"
427 		);
428 	}
429 
430 	@Rest(
431 		swagger=@Swagger(
432 			value="{tags:[{name:'$L{foo}',description:'$L{foo}',externalDocs:{description:'$L{foo}',url:'$L{foo}'}}]}",
433 			tags=@Tag(name="$L{foo}",description="$L{foo}",externalDocs=@ExternalDocs(description="$L{foo}",url="$L{foo}"))
434 		),
435 		messages="BasicRestInfoProviderTest"
436 	)
437 	public static class C7 {}
438 
439 	@Test void c07a_tags_Swagger_tags_localised() throws Exception {
440 		assertBeans(
441 			getSwagger(new C7()).getTags(),
442 			"name,description,externalDocs{description,url}",
443 			"l-foo,l-foo,{l-foo,l-foo}"
444 		);
445 	}
446 	@Test void c07b_tags_Swagger_tags_localised_withFile() throws Exception {
447 		assertBeans(
448 			getSwaggerWithFile(new C7()).getTags(),
449 			"name,description,externalDocs{description,url}",
450 			"l-foo,l-foo,{l-foo,l-foo}"
451 		);
452 	}
453 
454 	// Auto-detect tags defined on methods.
455 	@Rest
456 	public static class C8 {
457 		@RestOp(swagger=@OpSwagger(tags="foo"))
458 		public void a() { /* no-op */ }
459 	}
460 
461 	@Test void c08a_tags_Swagger_tags_loose() throws Exception {
462 		assertBeans(getSwagger(new C8()).getTags(), "name", "foo");
463 	}
464 	@Test void c08b_tags_Swagger_tags_loose_withFile() throws Exception {
465 		assertBeans(
466 			getSwaggerWithFile(new C8()).getTags(),
467 			"name,description,externalDocs{description,url}",
468 			"s-name,s-description,{s-description,s-url}",
469 			"foo,<null>,<null>"
470 		);
471 	}
472 
473 	// Comma-delimited list
474 	@Rest
475 	public static class C9 {
476 		@RestOp(swagger=@OpSwagger(tags=" foo, bar "))
477 		public void a() {/* no-op */}
478 	}
479 
480 	@Test void c09a_tags_Swagger_tags_loose_cdl() throws Exception {
481 		assertBeans(getSwagger(new C9()).getTags(), "name", "foo", "bar");
482 	}
483 	@Test void c09b_tags_Swagger_tags_loose_cdl_withFile() throws Exception {
484 		assertBeans(
485 			getSwaggerWithFile(new C9()).getTags(),
486 			"name,description,externalDocs{description,url}",
487 			"s-name,s-description,{s-description,s-url}",
488 			"foo,<null>,<null>",
489 			"bar,<null>,<null>"
490 		);
491 	}
492 
493 	// JsonList
494 	@Rest
495 	public static class C10 {
496 		@RestGet(swagger=@OpSwagger(tags="['foo', 'bar']"))
497 		public void a() {/* no-op */}
498 	}
499 
500 	@Test void c10a_tags_Swagger_tags_loose_olist() throws Exception {
501 		assertBeans(getSwagger(new C10()).getTags(), "name", "foo", "bar");
502 	}
503 	@Test void c10b_tags_Swagger_tags_loose_olist_withFile() throws Exception {
504 		assertBeans(
505 			getSwaggerWithFile(new C10()).getTags(),
506 			"name,description,externalDocs{description,url}",
507 			"s-name,s-description,{s-description,s-url}",
508 			"foo,<null>,<null>",
509 			"bar,<null>,<null>"
510 		);
511 	}
512 
513 	// JsonList localized
514 	@Rest(messages="BasicRestInfoProviderTest")
515 	public static class C11 {
516 		@RestGet(swagger=@OpSwagger(tags="['$L{foo}', '$L{bar}']"))
517 		public void a() {/* no-op */}
518 	}
519 
520 	@Test void c11a_tags_Swagger_tags_loose_olist_localized() throws Exception {
521 		assertBeans(getSwagger(new C11()).getTags(), "name", "l-foo", "l-bar");
522 	}
523 	@Test void c11b_tags_Swagger_tags_loose_olist_localized_withFile() throws Exception {
524 		assertBeans(
525 			getSwaggerWithFile(new C11()).getTags(),
526 			"name,description,externalDocs{description,url}",
527 			"s-name,s-description,{s-description,s-url}",
528 			"l-foo,<null>,<null>",
529 			"l-bar,<null>,<null>"
530 		);
531 	}
532 
533 	// Comma-delimited list localized
534 	@Rest(messages="BasicRestInfoProviderTest")
535 	public static class C12 {
536 		@RestGet(swagger=@OpSwagger(tags=" $L{foo}, $L{bar} "))
537 		public void a() {/* no-op */}
538 	}
539 
540 	@Test void c12a_tags_Swagger_tags_loose_cdl_localized() throws Exception {
541 		assertBeans(getSwagger(new C12()).getTags(), "name", "l-foo", "l-bar");
542 	}
543 	@Test void c12b_tags_Swagger_tags_loose_cdl_localized_withFile() throws Exception {
544 		assertBeans(
545 			getSwaggerWithFile(new C12()).getTags(),
546 			"name,description,externalDocs{description,url}",
547 			"s-name,s-description,{s-description,s-url}",
548 			"l-foo,<null>,<null>",
549 			"l-bar,<null>,<null>"
550 		);
551 	}
552 
553 	//------------------------------------------------------------------------------------------------------------------
554 	// /externalDocs
555 	//------------------------------------------------------------------------------------------------------------------
556 
557 	@Rest
558 	public static class D1 {}
559 
560 	@Test void d01a_externalDocs_default() throws Exception {
561 		assertNull(getSwagger(new D1()).getExternalDocs());
562 	}
563 	@Test void d01b_externalDocs_default_withFile() throws Exception {
564 		assertBean(getSwaggerWithFile(new D1()).getExternalDocs(), "description,url", "s-description,s-url");
565 	}
566 
567 
568 	@Rest(
569 		swagger=@Swagger("{externalDocs:{description:'a-description',url:'a-url'}}")
570 	)
571 	public static class D2 {}
572 
573 	@Test void d02a_externalDocs_Swagger_value() throws Exception {
574 		assertBean(getSwagger(new D2()).getExternalDocs(), "description,url", "a-description,a-url");
575 	}
576 	@Test void d02b_externalDocs_Swagger_value_withFile() throws Exception {
577 		assertBean(getSwaggerWithFile(new D2()).getExternalDocs(), "description,url", "a-description,a-url");
578 	}
579 
580 
581 	@Rest(
582 		swagger=@Swagger(
583 			value="{externalDocs:{description:'a-description',url:'a-url'}}",
584 			externalDocs=@ExternalDocs(description="b-description",url="b-url")
585 		)
586 	)
587 	public static class D3 {}
588 
589 	@Test void d03a_externalDocs_Swagger_externalDocs() throws Exception {
590 		assertBean(getSwagger(new D3()).getExternalDocs(), "description,url", "b-description,b-url");
591 	}
592 	@Test void d03b_externalDocs_Swagger_externalDocs_withFile() throws Exception {
593 		assertBean(getSwaggerWithFile(new D3()).getExternalDocs(), "description,url", "b-description,b-url");
594 	}
595 
596 	@Rest(
597 		swagger=@Swagger(
598 			value="{info:{externalDocs:{description:'a-description',url:'a-url'}}}",
599 			externalDocs=@ExternalDocs(description="b-description", url="b-url")
600 		)
601 	)
602 	public static class D4 {}
603 
604 	@Test void d04a_externalDocs_Swagger_externalDocs() throws Exception {
605 		var x = getSwagger(new D4()).getExternalDocs();
606 		assertBean(x, "description,url", "b-description,b-url");
607 	}
608 	@Test void d04b_externalDocs_Swagger_externalDocs_withFile() throws Exception {
609 		var x = getSwaggerWithFile(new D4()).getExternalDocs();
610 		assertBean(x, "description,url", "b-description,b-url");
611 	}
612 
613 	@Rest(
614 		swagger=@Swagger(
615 			value="{externalDocs:{description:'a-description',url:'a-url'}}",
616 			externalDocs=@ExternalDocs(description="$L{foo}",url="$L{bar}")
617 		),
618 		messages="BasicRestInfoProviderTest"
619 	)
620 	public static class D5 {}
621 
622 	@Test void d05a_externalDocs_Swagger_externalDocs_localised() throws Exception {
623 		var x = getSwagger(new D5()).getExternalDocs();
624 		assertBean(x, "description,url", "l-foo,l-bar");
625 	}
626 	@Test void d05b_externalDocs_Swagger_externalDocs_localised_withFile() throws Exception {
627 		var x = getSwaggerWithFile(new D5()).getExternalDocs();
628 		assertBean(x, "description,url", "l-foo,l-bar");
629 	}
630 
631 	//------------------------------------------------------------------------------------------------------------------
632 	// /paths/<path>/<method>
633 	//------------------------------------------------------------------------------------------------------------------
634 
635 	@Rest
636 	public static class E1 {
637 		@RestGet(path="/path/{foo}")
638 		public X a() {
639 			return null;
640 		}
641 	}
642 
643 	@Test void e01a_operation_summary_default() throws Exception {
644 		assertBean(getSwagger(new E1()).getPaths().get("/path/{foo}").get("get"),
645 			"operationId,summary,description,deprecated,schemes",
646 			"a,<null>,<null>,false,<null>");
647 	}
648 
649 	@Test void e01b_operation_summary_default_withFile() throws Exception {
650 		assertBean(getSwaggerWithFile(new E1()).getPaths().get("/path/{foo}").get("get"), "operationId,summary,description,deprecated,schemes", "s-operationId,s-summary,s-description,true,[s-scheme]");
651 	}
652 
653 	@Rest(
654 		swagger=@Swagger(
655 			"paths:{'/path/{foo}':{get:{operationId:'a-operationId',summary:'a-summary',description:'a-description',deprecated:false,schemes:['a-scheme']}}}"
656 		)
657 	)
658 	public static class E2 {
659 		@RestGet(path="/path/{foo}")
660 		public X a() {
661 			return null;
662 		}
663 	}
664 
665 	@Test void e02a_operation_summary_swaggerOnClass() throws Exception {
666 		assertBean(getSwagger(new E2()).getPaths().get("/path/{foo}").get("get"), "operationId,summary,description,deprecated,schemes", "a-operationId,a-summary,a-description,false,[a-scheme]");
667 	}
668 	@Test void e02b_operation_summary_swaggerOnClass_withFile() throws Exception {
669 		assertBean(getSwaggerWithFile(new E2()).getPaths().get("/path/{foo}").get("get"), "operationId,summary,description,deprecated,schemes", "a-operationId,a-summary,a-description,false,[a-scheme]");
670 	}
671 
672 	@Rest(
673 		swagger=@Swagger(
674 			"paths:{'/path/{foo}':{get:{operationId:'a-operationId',summary:'a-summary',description:'a-description',deprecated:false,schemes:['a-scheme']}}}"
675 		)
676 	)
677 	public static class E3 {
678 		@RestGet(path="/path/{foo}",
679 			swagger=@OpSwagger("operationId:'b-operationId',summary:'b-summary',description:'b-description',deprecated:false,schemes:['b-scheme']")
680 		)
681 		public X a() {
682 			return null;
683 		}
684 	}
685 
686 	@Test void e03a_operation_summary_swaggerOnMethod() throws Exception {
687 		assertBean(getSwagger(new E3()).getPaths().get("/path/{foo}").get("get"), "operationId,summary,description,deprecated,schemes", "b-operationId,b-summary,b-description,false,[b-scheme]");
688 	}
689 	@Test void e03b_operation_summary_swaggerOnMethod_withFile() throws Exception {
690 		assertBean(getSwaggerWithFile(new E3()).getPaths().get("/path/{foo}").get("get"), "operationId,summary,description,deprecated,schemes", "b-operationId,b-summary,b-description,false,[b-scheme]");
691 	}
692 
693 	@Rest(
694 		swagger=@Swagger(
695 			"paths:{'/path/{foo}':{get:{operationId:'a-operationId',summary:'a-summary',description:'a-description',deprecated:false,schemes:['a-scheme']}}}"
696 		)
697 	)
698 	public static class E4 {
699 		@RestGet(path="/path/{foo}",
700 			swagger=@OpSwagger(
701 				operationId="c-operationId",
702 				summary="c-summary",
703 				description="c-description",
704 				deprecated="false",
705 				schemes="d-scheme-1, d-scheme-2"
706 			)
707 		)
708 		public X a() {
709 			return null;
710 		}
711 	}
712 
713 	@Test void e04a_operation_summary_swaggerOnAnnotation() throws Exception {
714 		assertBean(getSwagger(new E4()).getPaths().get("/path/{foo}").get("get"), "operationId,summary,description,schemes", "c-operationId,c-summary,c-description,[d-scheme-1,d-scheme-2]");
715 	}
716 	@Test void e04b_operation_summary_swaggerOnAnnotation_withFile() throws Exception {
717 		assertBean(getSwaggerWithFile(new E4()).getPaths().get("/path/{foo}").get("get"), "operationId,summary,description,schemes", "c-operationId,c-summary,c-description,[d-scheme-1,d-scheme-2]");
718 	}
719 
720 	@Rest(
721 		messages="BasicRestInfoProviderTest",
722 		swagger=@Swagger(
723 			"paths:{'/path/{foo}':{get:{operationId:'a-operationId',summary:'a-summary',description:'a-description',deprecated:false,schemes:['a-scheme']}}}"
724 		)
725 	)
726 	public static class E5 {
727 		@RestGet(path="/path/{foo}",
728 			swagger=@OpSwagger(
729 				summary="$L{foo}",
730 				operationId="$L{foo}",
731 				description="$L{foo}",
732 				deprecated="$L{false}",
733 				schemes="$L{foo}"
734 			)
735 		)
736 		public X a() {
737 			return null;
738 		}
739 	}
740 
741 	@Test void e05a_operation_summary_swaggerOnAnnotation_localized() throws Exception {
742 		assertBean(getSwagger(new E5()).getPaths().get("/path/{foo}").get("get"), "operationId,summary,description,deprecated,schemes", "l-foo,l-foo,l-foo,false,[l-foo]");
743 	}
744 	@Test void e05b_operation_summary_swaggerOnAnnotation_localized_withFile() throws Exception {
745 		assertBean(getSwaggerWithFile(new E5()).getPaths().get("/path/{foo}").get("get"), "operationId,summary,description,deprecated,schemes", "l-foo,l-foo,l-foo,false,[l-foo]");
746 	}
747 
748 	@Rest(
749 		swagger=@Swagger(
750 			"paths:{'/path/{foo}':{get:{summary:'a-summary',description:'a-description'}}}"
751 		)
752 	)
753 	public static class E6 {
754 		@RestGet(path="/path/{foo}",
755 			summary="d-summary",
756 			description="d-description"
757 		)
758 		public X a() {
759 			return null;
760 		}
761 	}
762 
763 	@Test void e06a_operation_summary_RestOp() throws Exception {
764 		assertBean(getSwagger(new E6()).getPaths().get("/path/{foo}").get("get"), "summary,description", "a-summary,a-description");
765 	}
766 	@Test void e06b_operation_summary_RestOp_withFile() throws Exception {
767 		assertBean(getSwaggerWithFile(new E6()).getPaths().get("/path/{foo}").get("get"), "summary,description", "a-summary,a-description");
768 	}
769 
770 	@Rest(
771 		swagger=@Swagger(
772 			"paths:{'/path/{foo}':{get:{}}}"
773 		)
774 	)
775 	public static class E7 {
776 		@RestGet(path="/path/{foo}",
777 			summary="d-summary",
778 			description="d-description"
779 		)
780 		public X a() {
781 			return null;
782 		}
783 	}
784 
785 	@Test void e07a_operation_summary_RestOp() throws Exception {
786 		assertBean(getSwagger(new E7()).getPaths().get("/path/{foo}").get("get"), "summary,description", "d-summary,d-description");
787 	}
788 	@Test void e07b_operation_summary_RestOp_withFile() throws Exception {
789 		assertBean(getSwaggerWithFile(new E7()).getPaths().get("/path/{foo}").get("get"), "summary,description", "d-summary,d-description");
790 	}
791 
792 	//------------------------------------------------------------------------------------------------------------------
793 	// /paths/<path>/<method>/tags
794 	//------------------------------------------------------------------------------------------------------------------
795 
796 	@Rest
797 	public static class F1 {
798 
799 		@RestGet(path="/path/{foo}")
800 		public X a() {
801 			return null;
802 		}
803 	}
804 
805 	@Test void f01_operation_tags_default() throws Exception {
806 		assertNull(getSwagger(new F1()).getPaths().get("/path/{foo}").get("get").getTags());
807 		assertList(getSwaggerWithFile(new F1()).getPaths().get("/path/{foo}").get("get").getTags(), "s-tag");
808 	}
809 
810 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{tags:['a-tag']}}}"))
811 	public static class F2 {
812 		@RestGet(path="/path/{foo}")
813 		public X a() {
814 			return null;
815 		}
816 	}
817 
818 	@Test void f02_operation_tags_swaggerOnClass() throws Exception {
819 		assertList(getSwagger(new F2()).getPaths().get("/path/{foo}").get("get").getTags(), "a-tag");
820 		assertList(getSwaggerWithFile(new F2()).getPaths().get("/path/{foo}").get("get").getTags(), "a-tag");
821 	}
822 
823 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{tags:['a-tag']}}}"))
824 	public static class F3 {
825 		@RestGet(path="/path/{foo}",swagger=@OpSwagger("tags:['b-tag']"))
826 		public X a() {
827 			return null;
828 		}
829 	}
830 
831 	@Test void f03_operation_tags_swaggerOnMethod() throws Exception {
832 		assertList(getSwagger(new F3()).getPaths().get("/path/{foo}").get("get").getTags(), "b-tag");
833 		assertList(getSwaggerWithFile(new F3()).getPaths().get("/path/{foo}").get("get").getTags(), "b-tag");
834 	}
835 
836 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{tags:['a-tag']}}}"))
837 	public static class F4 {
838 		@RestGet(path="/path/{foo}",swagger=@OpSwagger(tags="['c-tag-1','c-tag-2']"))
839 		public X a() {
840 			return null;
841 		}
842 	}
843 
844 	@Test void f04_operation_tags_swaggerOnAnnotation() throws Exception {
845 		assertList(getSwagger(new F4()).getPaths().get("/path/{foo}").get("get").getTags(), "c-tag-1", "c-tag-2");
846 		assertList(getSwaggerWithFile(new F4()).getPaths().get("/path/{foo}").get("get").getTags(), "c-tag-1", "c-tag-2");
847 	}
848 
849 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{tags:['a-tag']}}}"))
850 	public static class F5 {
851 		@RestGet(path="/path/{foo}",swagger=@OpSwagger(tags="c-tag-1, c-tag-2"))
852 		public X a() {
853 			return null;
854 		}
855 	}
856 
857 	@Test void f05_operation_tags_swaggerOnAnnotation() throws Exception {
858 		assertList(getSwagger(new F5()).getPaths().get("/path/{foo}").get("get").getTags(), "c-tag-1", "c-tag-2");
859 		assertList(getSwaggerWithFile(new F5()).getPaths().get("/path/{foo}").get("get").getTags(), "c-tag-1", "c-tag-2");
860 	}
861 
862 	@Rest(messages="BasicRestInfoProviderTest", swagger=@Swagger("paths:{'/path/{foo}':{get:{tags:'a-tags'}}}"))
863 	public static class F6 {
864 		@RestGet(path="/path/{foo}",swagger=@OpSwagger(tags="$L{foo}"))
865 		public X a() {
866 			return null;
867 		}
868 	}
869 
870 	@Test void f06_operation_tags_swaggerOnAnnotation_localized() throws Exception {
871 		assertList(getSwagger(new F6()).getPaths().get("/path/{foo}").get("get").getTags(), "l-foo");
872 		assertList(getSwaggerWithFile(new F6()).getPaths().get("/path/{foo}").get("get").getTags(), "l-foo");
873 	}
874 
875 	//------------------------------------------------------------------------------------------------------------------
876 	// /paths/<path>/<method>/externalDocs
877 	//------------------------------------------------------------------------------------------------------------------
878 
879 	@Rest
880 	public static class G1 {
881 
882 		@RestGet(path="/path/{foo}")
883 		public X a() {
884 			return null;
885 		}
886 	}
887 
888 	@Test void g01_operation_externalDocs_default() throws Exception {
889 		assertNull(getSwagger(new G1()).getPaths().get("/path/{foo}").get("get").getExternalDocs());
890 		assertBean(getSwaggerWithFile(new G1()).getPaths().get("/path/{foo}").get("get").getExternalDocs(), "description,url", "s-description,s-url");
891 	}
892 
893 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
894 	public static class G2 {
895 		@RestGet(path="/path/{foo}")
896 		public X a() {
897 			return null;
898 		}
899 	}
900 
901 	@Test void g02_operation_externalDocs_swaggerOnClass() throws Exception {
902 		assertBean(getSwagger(new G2()).getPaths().get("/path/{foo}").get("get").getExternalDocs(), "description,url", "a-description,a-url");
903 		assertBean(getSwaggerWithFile(new G2()).getPaths().get("/path/{foo}").get("get").getExternalDocs(), "description,url", "a-description,a-url");
904 	}
905 
906 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
907 	public static class G3 {
908 		@RestGet(path="/path/{foo}",swagger=@OpSwagger("externalDocs:{description:'b-description',url:'b-url'}"))
909 		public X a() {
910 			return null;
911 		}
912 	}
913 
914 	@Test void g03_operation_externalDocs_swaggerOnMethod() throws Exception {
915 		assertBean(getSwagger(new G3()).getPaths().get("/path/{foo}").get("get").getExternalDocs(), "description,url", "b-description,b-url");
916 		assertBean(getSwaggerWithFile(new G3()).getPaths().get("/path/{foo}").get("get").getExternalDocs(), "description,url", "b-description,b-url");
917 	}
918 
919 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
920 	public static class G4 {
921 		@RestGet(path="/path/{foo}",swagger=@OpSwagger(externalDocs=@ExternalDocs(description="c-description",url="c-url")))
922 		public X a() {
923 			return null;
924 		}
925 	}
926 
927 	@Test void g04_operation_externalDocs_swaggerOnAnnotation() throws Exception {
928 		assertBean(getSwagger(new G4()).getPaths().get("/path/{foo}").get("get").getExternalDocs(), "description,url", "c-description,c-url");
929 		assertBean(getSwaggerWithFile(new G4()).getPaths().get("/path/{foo}").get("get").getExternalDocs(), "description,url", "c-description,c-url");
930 	}
931 
932 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
933 	public static class G5 {
934 		@RestGet(path="/path/{foo}",swagger=@OpSwagger(externalDocs=@ExternalDocs(description="d-description",url="d-url")))
935 		public X a() {
936 			return null;
937 		}
938 	}
939 
940 	@Test void g05_operation_externalDocs_swaggerOnAnnotation() throws Exception {
941 		assertBean(getSwagger(new G5()).getPaths().get("/path/{foo}").get("get").getExternalDocs(), "description,url", "d-description,d-url");
942 		assertBean(getSwaggerWithFile(new G5()).getPaths().get("/path/{foo}").get("get").getExternalDocs(), "description,url", "d-description,d-url");
943 	}
944 
945 	@Rest(messages="BasicRestInfoProviderTest", swagger=@Swagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
946 	public static class G6 {
947 		@RestGet(path="/path/{foo}",swagger=@OpSwagger(externalDocs=@ExternalDocs(description="$L{foo}",url="$L{foo}")))
948 		public X a() {
949 			return null;
950 		}
951 	}
952 
953 	@Test void g06_operation_externalDocs_swaggerOnAnnotation_localized() throws Exception {
954 		assertBean(getSwagger(new G6()).getPaths().get("/path/{foo}").get("get").getExternalDocs(), "description,url", "l-foo,l-foo");
955 		assertBean(getSwaggerWithFile(new G6()).getPaths().get("/path/{foo}").get("get").getExternalDocs(), "description,url", "l-foo,l-foo");
956 	}
957 
958 	//------------------------------------------------------------------------------------------------------------------
959 	// /paths/<path>/<method>/consumes
960 	//------------------------------------------------------------------------------------------------------------------
961 
962 	@Rest
963 	public static class H1 {
964 
965 		@RestGet(path="/path/{foo}")
966 		public X a() {
967 			return null;
968 		}
969 	}
970 
971 	@Test void h01_operation_consumes_default() throws Exception {
972 		assertNull(getSwagger(new H1()).getPaths().get("/path/{foo}").get("get").getConsumes());
973 		assertList(getSwaggerWithFile(new H1()).getPaths().get("/path/{foo}").get("get").getConsumes(), "s-consumes");
974 	}
975 
976 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
977 	public static class H2 {
978 		@RestGet(path="/path/{foo}")
979 		public X a() {
980 			return null;
981 		}
982 	}
983 
984 	@Test void h02_operation_consumes_swaggerOnClass() throws Exception {
985 		assertList(getSwagger(new H2()).getPaths().get("/path/{foo}").get("get").getConsumes(), "a-consumes");
986 		assertList(getSwaggerWithFile(new H2()).getPaths().get("/path/{foo}").get("get").getConsumes(), "a-consumes");
987 	}
988 
989 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
990 	public static class H3 {
991 		@RestGet(path="/path/{foo}",swagger=@OpSwagger("consumes:['b-consumes']"))
992 		public X a() {
993 			return null;
994 		}
995 	}
996 
997 	@Test void h03_operation_consumes_swaggerOnMethod() throws Exception {
998 		assertList(getSwagger(new H3()).getPaths().get("/path/{foo}").get("get").getConsumes(), "b-consumes");
999 		assertList(getSwaggerWithFile(new H3()).getPaths().get("/path/{foo}").get("get").getConsumes(), "b-consumes");
1000 	}
1001 
1002 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
1003 	public static class H4 {
1004 		@RestGet(path="/path/{foo}",swagger=@OpSwagger(consumes="['c-consumes-1','c-consumes-2']"))
1005 		public X a() {
1006 			return null;
1007 		}
1008 	}
1009 
1010 	@Test void h04_operation_consumes_swaggerOnAnnotation() throws Exception {
1011 		assertList(getSwagger(new H4()).getPaths().get("/path/{foo}").get("get").getConsumes(), "c-consumes-1", "c-consumes-2");
1012 		assertList(getSwaggerWithFile(new H4()).getPaths().get("/path/{foo}").get("get").getConsumes(), "c-consumes-1", "c-consumes-2");
1013 	}
1014 
1015 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
1016 	public static class H5 {
1017 		@RestGet(path="/path/{foo}",swagger=@OpSwagger(consumes="c-consumes-1, c-consumes-2"))
1018 		public X a() {
1019 			return null;
1020 		}
1021 	}
1022 
1023 	@Test void h05_operation_consumes_swaggerOnAnnotation() throws Exception {
1024 		assertList(getSwagger(new H5()).getPaths().get("/path/{foo}").get("get").getConsumes(), "c-consumes-1", "c-consumes-2");
1025 		assertList(getSwaggerWithFile(new H5()).getPaths().get("/path/{foo}").get("get").getConsumes(), "c-consumes-1", "c-consumes-2");
1026 	}
1027 
1028 	@Rest(messages="BasicRestInfoProviderTest", swagger=@Swagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
1029 	public static class H6 {
1030 		@RestGet(path="/path/{foo}",swagger=@OpSwagger(consumes="['$L{foo}']"))
1031 		public X a() {
1032 			return null;
1033 		}
1034 	}
1035 
1036 	@Test void h06_operation_consumes_swaggerOnAnnotation_localized() throws Exception {
1037 		assertList(getSwagger(new H6()).getPaths().get("/path/{foo}").get("get").getConsumes(), "l-foo");
1038 		assertList(getSwaggerWithFile(new H6()).getPaths().get("/path/{foo}").get("get").getConsumes(), "l-foo");
1039 	}
1040 
1041 	@Rest(parsers={JsonParser.class})
1042 	public static class H7 {
1043 		@RestPut(path="/path2/{foo}")
1044 		public X a() {
1045 			return null;
1046 		}
1047 	}
1048 
1049 	@Test void h07_operation_consumes_parsersOnClass() throws Exception {
1050 		assertNull(getSwagger(new H7()).getPaths().get("/path2/{foo}").get("put").getConsumes());
1051 		assertNull(getSwaggerWithFile(new H7()).getPaths().get("/path2/{foo}").get("put").getConsumes());
1052 	}
1053 
1054 	@Rest(parsers={JsonParser.class})
1055 	public static class H8 {
1056 		@RestPut(path="/path2/{foo}",parsers={XmlParser.class})
1057 		public X a() {
1058 			return null;
1059 		}
1060 		@RestPut(path="/b")
1061 		public X b() {
1062 			return null;
1063 		}
1064 	}
1065 
1066 	@Test void h08_operation_consumes_parsersOnClassAndMethod() throws Exception {
1067 		assertList(getSwagger(new H8()).getPaths().get("/path2/{foo}").get("put").getConsumes(), "text/xml", "application/xml");
1068 		assertList(getSwaggerWithFile(new H8()).getPaths().get("/path2/{foo}").get("put").getConsumes(), "text/xml", "application/xml");
1069 	}
1070 
1071 	@Rest(parsers={JsonParser.class},swagger=@Swagger("paths:{'/path2/{foo}':{put:{consumes:['a-consumes']}}}"))
1072 	public static class H9 {
1073 		@RestPut(path="/path2/{foo}",parsers={XmlParser.class})
1074 		public X a() {
1075 			return null;
1076 		}
1077 	}
1078 
1079 	@Test void h09_operation_consumes_parsersOnClassAndMethodWithSwagger() throws Exception {
1080 		assertList(getSwagger(new H9()).getPaths().get("/path2/{foo}").get("put").getConsumes(), "a-consumes");
1081 		assertList(getSwaggerWithFile(new H9()).getPaths().get("/path2/{foo}").get("put").getConsumes(), "a-consumes");
1082 	}
1083 
1084 	//------------------------------------------------------------------------------------------------------------------
1085 	// /paths/<path>/<method>/produces
1086 	//------------------------------------------------------------------------------------------------------------------
1087 
1088 	@Rest
1089 	public static class I1 {
1090 
1091 		@RestGet(path="/path/{foo}")
1092 		public X a() {
1093 			return null;
1094 		}
1095 	}
1096 
1097 	@Test void i01_operation_produces_default() throws Exception {
1098 		assertNull(getSwagger(new I1()).getPaths().get("/path/{foo}").get("get").getProduces());
1099 		assertList(getSwaggerWithFile(new I1()).getPaths().get("/path/{foo}").get("get").getProduces(), "s-produces");
1100 	}
1101 
1102 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
1103 	public static class I2 {
1104 		@RestGet(path="/path/{foo}")
1105 		public X a() {
1106 			return null;
1107 		}
1108 	}
1109 
1110 	@Test void i02_operation_produces_swaggerOnClass() throws Exception {
1111 		assertList(getSwagger(new I2()).getPaths().get("/path/{foo}").get("get").getProduces(), "a-produces");
1112 		assertList(getSwaggerWithFile(new I2()).getPaths().get("/path/{foo}").get("get").getProduces(), "a-produces");
1113 	}
1114 
1115 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
1116 	public static class I3 {
1117 		@RestGet(path="/path/{foo}",swagger=@OpSwagger("produces:['b-produces']"))
1118 		public X a() {
1119 			return null;
1120 		}
1121 	}
1122 
1123 	@Test void i03_operation_produces_swaggerOnMethod() throws Exception {
1124 		assertList(getSwagger(new I3()).getPaths().get("/path/{foo}").get("get").getProduces(), "b-produces");
1125 		assertList(getSwaggerWithFile(new I3()).getPaths().get("/path/{foo}").get("get").getProduces(), "b-produces");
1126 	}
1127 
1128 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
1129 	public static class I4 {
1130 		@RestGet(path="/path/{foo}",swagger=@OpSwagger(produces="['c-produces-1','c-produces-2']"))
1131 		public X a() {
1132 			return null;
1133 		}
1134 	}
1135 
1136 	@Test void i04_operation_produces_swaggerOnAnnotation() throws Exception {
1137 		assertList(getSwagger(new I4()).getPaths().get("/path/{foo}").get("get").getProduces(), "c-produces-1", "c-produces-2");
1138 		assertList(getSwaggerWithFile(new I4()).getPaths().get("/path/{foo}").get("get").getProduces(), "c-produces-1", "c-produces-2");
1139 	}
1140 
1141 	@Rest(swagger=@Swagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
1142 	public static class I5 {
1143 		@RestGet(path="/path/{foo}",swagger=@OpSwagger(produces="c-produces-1, c-produces-2"))
1144 		public X a() {
1145 			return null;
1146 		}
1147 	}
1148 
1149 	@Test void i05_operation_produces_swaggerOnAnnotation() throws Exception {
1150 		assertList(getSwagger(new I5()).getPaths().get("/path/{foo}").get("get").getProduces(), "c-produces-1", "c-produces-2");
1151 		assertList(getSwaggerWithFile(new I5()).getPaths().get("/path/{foo}").get("get").getProduces(), "c-produces-1", "c-produces-2");
1152 	}
1153 
1154 	@Rest(messages="BasicRestInfoProviderTest", swagger=@Swagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
1155 	public static class I6 {
1156 		@RestGet(path="/path/{foo}",swagger=@OpSwagger(produces="['$L{foo}']"))
1157 		public X a() {
1158 			return null;
1159 		}
1160 	}
1161 
1162 	@Test void i06_operation_produces_swaggerOnAnnotation_localized() throws Exception {
1163 		assertList(getSwagger(new I6()).getPaths().get("/path/{foo}").get("get").getProduces(), "l-foo");
1164 		assertList(getSwaggerWithFile(new I6()).getPaths().get("/path/{foo}").get("get").getProduces(), "l-foo");
1165 	}
1166 
1167 	@Rest(serializers={JsonSerializer.class})
1168 	public static class I7 {
1169 		@RestPut(path="/path2/{foo}")
1170 		public X a() {
1171 			return null;
1172 		}
1173 	}
1174 
1175 	@Test void i07_operation_produces_serializersOnClass() throws Exception {
1176 		assertNull(getSwagger(new I7()).getPaths().get("/path2/{foo}").get("put").getProduces());
1177 		assertNull(getSwaggerWithFile(new I7()).getPaths().get("/path2/{foo}").get("put").getProduces());
1178 	}
1179 
1180 	@Rest(serializers={JsonSerializer.class})
1181 	public static class I8 {
1182 		@RestPut(path="/path2/{foo}",serializers={XmlSerializer.class})
1183 		public X a() {
1184 			return null;
1185 		}
1186 		@RestGet(path="/b")
1187 		public X b() {
1188 			return null;
1189 		}
1190 	}
1191 
1192 	@Test void i08_operation_produces_serializersOnClassAndMethod() throws Exception {
1193 		assertList(getSwagger(new I8()).getPaths().get("/path2/{foo}").get("put").getProduces(), "text/xml");
1194 		assertList(getSwaggerWithFile(new I8()).getPaths().get("/path2/{foo}").get("put").getProduces(), "text/xml");
1195 	}
1196 
1197 	@Rest(serializers={JsonSerializer.class},swagger=@Swagger("paths:{'/path2/{foo}':{put:{produces:['a-produces']}}}"))
1198 	public static class I9 {
1199 		@RestPut(path="/path2/{foo}",serializers={XmlSerializer.class})
1200 		public X a() {
1201 			return null;
1202 		}
1203 	}
1204 
1205 	@Test void i09_operation_produces_serializersOnClassAndMethodWithSwagger() throws Exception {
1206 		assertList(getSwagger(new I9()).getPaths().get("/path2/{foo}").get("put").getProduces(), "a-produces");
1207 		assertList(getSwaggerWithFile(new I9()).getPaths().get("/path2/{foo}").get("put").getProduces(), "a-produces");
1208 	}
1209 
1210 	//------------------------------------------------------------------------------------------------------------------
1211 	// /paths/<path>/<method>/deprecated
1212 	//------------------------------------------------------------------------------------------------------------------
1213 
1214 	@Rest
1215 	public static class J1 {
1216 		@RestGet(path="/path2/{foo}")
1217 		@Deprecated
1218 		public X a() {
1219 			return null;
1220 		}
1221 	}
1222 
1223 	@Test void j01_operation_deprecated_Deprecated() throws Exception {
1224 		assertTrue(getSwagger(new J1()).getPaths().get("/path2/{foo}").get("get").getDeprecated());
1225 		assertTrue(getSwaggerWithFile(new J1()).getPaths().get("/path2/{foo}").get("get").getDeprecated());
1226 	}
1227 
1228 	@Rest
1229 	@Deprecated
1230 	public static class J2 {
1231 		@RestGet(path="/path2/{foo}")
1232 		public X a() {
1233 			return null;
1234 		}
1235 	}
1236 
1237 	@Test void j02_operation_deprecated_Deprecated() throws Exception {
1238 		assertTrue(getSwagger(new J2()).getPaths().get("/path2/{foo}").get("get").getDeprecated());  // NOSONAR
1239 		assertTrue(getSwaggerWithFile(new J2()).getPaths().get("/path2/{foo}").get("get").getDeprecated());  // NOSONAR
1240 	}
1241 
1242 	//------------------------------------------------------------------------------------------------------------------
1243 	// /paths/<path>/<method>/parameters/query
1244 	//------------------------------------------------------------------------------------------------------------------
1245 
1246 	@Rest
1247 	public static class K1 {
1248 		@RestGet(path="/path/{foo}/query")
1249 		public X a(@Query("foo") X foo) {
1250 			return null;
1251 		}
1252 	}
1253 
1254 	@Test void k01a_query_type_default() throws Exception {
1255 		assertBean(
1256 			getSwagger(new K1()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo"),
1257 			"type,description,required,allowEmptyValue,exclusiveMaximum,exclusiveMinimum,uniqueItems,format,collectionFormat,pattern,maximum,minimum,multipleOf,maxLength,minLength,maxItems,minItems",
1258 			"object,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>,<null>"
1259 		);
1260 	}
1261 	@Test void k01b_query_type_default_withFile() throws Exception {
1262 		assertBean(
1263 			getSwaggerWithFile(new K1()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo"),
1264 			"type,description,required,allowEmptyValue,exclusiveMaximum,exclusiveMinimum,uniqueItems,format,collectionFormat,pattern,maximum,minimum,multipleOf,maxLength,minLength,maxItems,minItems",
1265 			"string,s-description,true,true,true,true,true,s-format,s-collectionFormat,s-pattern,1.0,1.0,1.0,1,1,1,1"
1266 		);
1267 	}
1268 
1269 	@Rest(
1270 		swagger=@Swagger({
1271 			"paths:{'/path/{foo}/query':{get:{parameters:[{'in':'query',",
1272 				"name:'foo',",
1273 				"type:'int32',",
1274 				"description:'a-description',",
1275 				"required:false,",
1276 				"allowEmptyValue:false,",
1277 				"exclusiveMaximum:false,",
1278 				"exclusiveMinimum:false,",
1279 				"uniqueItems:false,",
1280 				"format:'a-format',",
1281 				"collectionFormat:'a-collectionFormat',",
1282 				"pattern:'a-pattern',",
1283 				"maximum:2.0,",
1284 				"minimum:2.0,",
1285 				"multipleOf:2.0,",
1286 				"maxLength:2,",
1287 				"minLength:2,",
1288 				"maxItems:2,",
1289 				"minItems:2",
1290 			"}]}}}"
1291 		})
1292 	)
1293 	public static class K2 {
1294 		@RestGet(path="/path/{foo}/query")
1295 		public X a(@Query("foo") X foo) {
1296 			return null;
1297 		}
1298 	}
1299 
1300 	@Test void k02a_query_type_swaggerOnClass() throws Exception {
1301 		assertBean(
1302 			getSwagger(new K2()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo"),
1303 			"type,description,required,allowEmptyValue,exclusiveMaximum,exclusiveMinimum,uniqueItems,format,collectionFormat,pattern,maximum,minimum,multipleOf,maxLength,minLength,maxItems,minItems",
1304 			"int32,a-description,false,false,false,false,false,a-format,a-collectionFormat,a-pattern,2.0,2.0,2.0,2,2,2,2"
1305 		);
1306 	}
1307 	@Test void k02b_query_type_swaggerOnClass_withFile() throws Exception {
1308 		assertBean(
1309 			getSwaggerWithFile(new K2()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo"),
1310 			"type,description,required,allowEmptyValue,exclusiveMaximum,exclusiveMinimum,uniqueItems,format,collectionFormat,pattern,maximum,minimum,multipleOf,maxLength,minLength,maxItems,minItems",
1311 			"int32,a-description,false,false,false,false,false,a-format,a-collectionFormat,a-pattern,2.0,2.0,2.0,2,2,2,2"
1312 		);
1313 	}
1314 
1315 	@Rest(
1316 		swagger=@Swagger({
1317 			"paths:{'/path/{foo}/query':{get:{parameters:[{",
1318 				"'in':'query',",
1319 				"name:'foo',",
1320 				"type:'int32',",
1321 				"description:'a-description',",
1322 				"required:false,",
1323 				"allowEmptyValue:false,",
1324 				"exclusiveMaximum:false,",
1325 				"exclusiveMinimum:false,",
1326 				"uniqueItems:false,",
1327 				"format:'a-format',",
1328 				"collectionFormat:'a-collectionFormat',",
1329 				"pattern:'a-pattern',",
1330 				"maximum:2.0,",
1331 				"minimum:2.0,",
1332 				"multipleOf:2.0,",
1333 				"maxLength:2,",
1334 				"minLength:2,",
1335 				"maxItems:2,",
1336 				"minItems:2",
1337 			"}]}}}"
1338 		})
1339 	)
1340 	public static class K3 {
1341 		@RestGet(path="/path/{foo}/query",
1342 			swagger=@OpSwagger({
1343 				"parameters:[{",
1344 					"'in':'query',",
1345 					"name:'foo',",
1346 					"type:'int64',",
1347 					"description:'b-description',",
1348 					"required:'true',",
1349 					"allowEmptyValue:'true',",
1350 					"exclusiveMaximum:'true',",
1351 					"exclusiveMinimum:'true',",
1352 					"uniqueItems:'true',",
1353 					"format:'b-format',",
1354 					"collectionFormat:'b-collectionFormat',",
1355 					"pattern:'b-pattern',",
1356 					"maximum:3.0,",
1357 					"minimum:3.0,",
1358 					"multipleOf:3.0,",
1359 					"maxLength:3,",
1360 					"minLength:3,",
1361 					"maxItems:3,",
1362 					"minItems:3",
1363 				"}]"
1364 			}))
1365 		public X a() {
1366 			return null;
1367 		}
1368 	}
1369 
1370 	@Test void k03a_query_type_swaggerOnMethod() throws Exception {
1371 		assertBean(
1372 			getSwagger(new K3()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo"),
1373 			"type,description,required,allowEmptyValue,exclusiveMaximum,exclusiveMinimum,uniqueItems,format,collectionFormat,pattern,maximum,minimum,multipleOf,maxLength,minLength,maxItems,minItems",
1374 			"int64,b-description,true,true,true,true,true,b-format,b-collectionFormat,b-pattern,3.0,3.0,3.0,3,3,3,3"
1375 		);
1376 	}
1377 	@Test void k03b_query_type_swaggerOnMethod_withFile() throws Exception {
1378 		assertBean(
1379 			getSwaggerWithFile(new K3()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo"),
1380 			"type,description,required,allowEmptyValue,exclusiveMaximum,exclusiveMinimum,uniqueItems,format,collectionFormat,pattern,maximum,minimum,multipleOf,maxLength,minLength,maxItems,minItems",
1381 			"int64,b-description,true,true,true,true,true,b-format,b-collectionFormat,b-pattern,3.0,3.0,3.0,3,3,3,3"
1382 		);
1383 	}
1384 
1385 	//------------------------------------------------------------------------------------------------------------------
1386 	// /paths/<path>/<method>/parameters/body/examples
1387 	//------------------------------------------------------------------------------------------------------------------
1388 
1389 	@Rest
1390 	public static class M1 {
1391 		@RestGet(path="/path/{foo}/body")
1392 		public X a(@Content X foo) {
1393 			return null;
1394 		}
1395 	}
1396 
1397 	//------------------------------------------------------------------------------------------------------------------
1398 	// /paths/<path>/<method>/parameters/query/schema
1399 	//------------------------------------------------------------------------------------------------------------------
1400 
1401 	@Rest
1402 	public static class N1 {
1403 		@RestGet(path="/path/{foo}/query")
1404 		public X a(@Query("foo") X foo) {
1405 			return null;
1406 		}
1407 	}
1408 
1409 	@Test void n01_query_schema_default() throws Exception {
1410 		assertBean(
1411 			getSwagger(new N1()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema(),
1412 			"properties{a{format,type}}",
1413 			"{{int32,integer}}"
1414 		);
1415 		assertBean(
1416 			getSwaggerWithFile(new N1()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema(),
1417 			"ref",
1418 			"#/definitions/Foo"
1419 		);
1420 	}
1421 
1422 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/query':{get:{parameters:[{in:'query',name:'foo',schema:{$ref:'b'}}]}}}"))
1423 	public static class N2 {
1424 		@RestGet(path="/path/{foo}/query")
1425 		public X a(@Query("foo") X foo) {
1426 			return null;
1427 		}
1428 	}
1429 
1430 	@Test void n02_query_schema_swaggerOnClass() throws Exception {
1431 		assertBean(getSwagger(new N2()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema(), "ref", "b");
1432 		assertBean(getSwaggerWithFile(new N2()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema(), "ref", "b");
1433 	}
1434 
1435 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/query':{get:{parameters:[{in:'query',name:'foo',schema:{$ref:'b'}}]}}}"))
1436 	public static class N3 {
1437 
1438 		@RestGet(path="/path/{foo}/query",swagger=@OpSwagger("parameters:[{'in':'query',name:'foo',schema:{$ref:'c'}}]"))
1439 		public X a() {
1440 			return null;
1441 		}
1442 	}
1443 
1444 	@Test void n03_query_schema_swaggerOnMethnt() throws Exception {
1445 		assertBean(getSwagger(new N3()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema(), "ref", "c");
1446 		assertBean(getSwaggerWithFile(new N3()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema(), "ref", "c");
1447 	}
1448 
1449 	//------------------------------------------------------------------------------------------------------------------
1450 	// /paths/<path>/<method>/responses/<response>/description
1451 	//------------------------------------------------------------------------------------------------------------------
1452 
1453 	@Rest
1454 	public static class O1a {
1455 		@RestGet(path="/path/{foo}/responses/100")
1456 		public void a(Value<O1c> foo) {/* no-op */}
1457 	}
1458 	@Rest
1459 	public static class O1b {
1460 		@RestGet(path="/path/{foo}/responses/100")
1461 		public O1c a() { return null;}
1462 	}
1463 	@Response @StatusCode(100)
1464 	public static class O1c {
1465 		public String a;
1466 	}
1467 
1468 	@Test void o01a_responses_100_description_default() throws Exception {
1469 		assertBean(getSwagger(new O1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "Continue");
1470 		assertBean(getSwaggerWithFile(new O1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "s-100-description");
1471 	}
1472 	@Test void o01b_responses_100_description_default() throws Exception {
1473 		assertBean(getSwagger(new O1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "Continue");
1474 		assertBean(getSwaggerWithFile(new O1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "s-100-description");
1475 	}
1476 
1477 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
1478 	public static class O2 {
1479 		@RestGet(path="/path/{foo}/responses/100")
1480 		public void a(@StatusCode Value<Integer> foo) {/* no-op */}
1481 	}
1482 
1483 	@Test void o02_response_100_description_swaggerOnClass() throws Exception {
1484 		assertBean(getSwagger(new O2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "a-100-description");
1485 		assertBean(getSwaggerWithFile(new O2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "a-100-description");
1486 	}
1487 
1488 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
1489 	public static class O3 {
1490 		@RestGet(path="/path/{foo}/responses/100",swagger=@OpSwagger("responses:{100:{description:'b-100-description'}}"))
1491 		public void a(@StatusCode Value<Integer> foo) {/* no-op */}
1492 	}
1493 
1494 	@Test void o03_response_100_description_swaggerOnMethod() throws Exception {
1495 		assertBean(getSwagger(new O3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "b-100-description");
1496 		assertBean(getSwaggerWithFile(new O3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "b-100-description");
1497 	}
1498 
1499 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
1500 	public static class O4a {
1501 		@RestGet(path="/path/{foo}/responses/100")
1502 		public void a(Value<O4c> foo) {/* no-op */}
1503 	}
1504 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
1505 	public static class O4b {
1506 		@RestGet(path="/path/{foo}/responses/100")
1507 		public O4c a() {return null;}
1508 	}
1509 	@Response @StatusCode(100) @Schema(description="c-100-description")
1510 	public static class O4c {}
1511 
1512 	@Test void o04a_response_100_description_swaggerOnAnnotation() throws Exception {
1513 		assertBean(getSwagger(new O4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "c-100-description");
1514 		assertBean(getSwaggerWithFile(new O4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "c-100-description");
1515 	}
1516 	@Test void o04b_response_100_description_swaggerOnAnnotation() throws Exception {
1517 		assertBean(getSwagger(new O4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "c-100-description");
1518 		assertBean(getSwaggerWithFile(new O4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "c-100-description");
1519 	}
1520 
1521 	@Rest(messages="BasicRestInfoProviderTest", swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
1522 	public static class O5a {
1523 		@RestGet(path="/path/{foo}/responses/100")
1524 		public void a(Value<O5c> foo) {/* no-op */}
1525 	}
1526 	@Rest(messages="BasicRestInfoProviderTest", swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
1527 	public static class O5b {
1528 		@RestGet(path="/path/{foo}/responses/100")
1529 		public O5c a() {return null;}
1530 	}
1531 	@Response @StatusCode(100) @Schema(description="$L{foo}")
1532 	public static class O5c {}
1533 
1534 	@Test void o05a_response_100_description_swaggerOnAnnotation_localized() throws Exception {
1535 		assertBean(getSwagger(new O5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "l-foo");
1536 		assertBean(getSwaggerWithFile(new O5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "l-foo");
1537 	}
1538 	@Test void o05b_response_100_description_swaggerOnAnnotation_localized() throws Exception {
1539 		assertBean(getSwagger(new O5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "l-foo");
1540 		assertBean(getSwaggerWithFile(new O5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100), "description", "l-foo");
1541 	}
1542 
1543 	//------------------------------------------------------------------------------------------------------------------
1544 	// /paths/<path>/<method>/responses/<response>/headers
1545 	//------------------------------------------------------------------------------------------------------------------
1546 
1547 	@Rest
1548 	public static class P1a {
1549 		@RestGet(path="/path/{foo}/responses/100")
1550 		public void a(Value<P1c> foo) {/* no-op */}
1551 	}
1552 	@Rest
1553 	public static class P1b {
1554 		@RestGet(path="/path/{foo}/responses/100")
1555 		public P1c a() {return null;}
1556 	}
1557 	@Response @StatusCode(100)
1558 	public static class P1c {
1559 		public String a;
1560 	}
1561 
1562 	@Test void p01a_responses_100_headers_default() throws Exception {
1563 		assertNull(getSwagger(new P1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
1564 		assertMap(getSwaggerWithFile(new P1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{s-description,integer,int32}");
1565 	}
1566 	@Test void p01b_responses_100_headers_default() throws Exception {
1567 		assertNull(getSwagger(new P1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
1568 		assertMap(getSwaggerWithFile(new P1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{s-description,integer,int32}");
1569 	}
1570 
1571 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
1572 	public static class P2 {
1573 		@RestGet(path="/path/{foo}/responses/100")
1574 		public X a(@StatusCode Value<Integer> foo) {
1575 			return null;
1576 		}
1577 	}
1578 
1579 	@Test void p02_response_100_headers_swaggerOnClass() throws Exception {
1580 		assertMap(getSwagger(new P2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{b-description,integer,int32}");
1581 		assertMap(getSwaggerWithFile(new P2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{b-description,integer,int32}");
1582 	}
1583 
1584 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
1585 	public static class P3 {
1586 		@RestGet(path="/path/{foo}/responses/100",swagger=@OpSwagger("responses:{100:{headers:{'X-Foo':{description:'c-description',type:'integer',format:'int32'}}}}"))
1587 		public X a(@StatusCode Value<Integer> foo) {
1588 			return null;
1589 		}
1590 	}
1591 
1592 	@Test void p03_response_100_headers_swaggerOnMethod() throws Exception {
1593 		assertMap(getSwagger(new P3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{c-description,integer,int32}");
1594 		assertMap(getSwaggerWithFile(new P3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{c-description,integer,int32}");
1595 	}
1596 
1597 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
1598 	public static class P4a {
1599 		@RestGet(path="/path/{foo}/responses/100")
1600 		public void a(Value<P4c> foo) {/* no-op */}
1601 	}
1602 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
1603 	public static class P4b {
1604 		@RestGet(path="/path/{foo}/responses/100")
1605 		public P4c a() {return null;}
1606 	}
1607 	@Response(headers=@Header(name="X-Foo",schema=@Schema(description="d-description",type="integer",format="int32"))) @StatusCode(100)
1608 	public static class P4c {}
1609 
1610 	@Test void p04a_response_100_headers_swaggerOnAnnotation() throws Exception {
1611 		assertMap(getSwagger(new P4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{d-description,integer,int32}");
1612 		assertMap(getSwaggerWithFile(new P4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{d-description,integer,int32}");
1613 	}
1614 	@Test void p04b_response_100_headers_swaggerOnAnnotation() throws Exception {
1615 		assertMap(getSwagger(new P4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{d-description,integer,int32}");
1616 		assertMap(getSwaggerWithFile(new P4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{d-description,integer,int32}");
1617 	}
1618 
1619 	@Rest(messages="BasicRestInfoProviderTest", swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
1620 	public static class P5a {
1621 		@RestGet(path="/path/{foo}/responses/100")
1622 		public void a(Value<P5c> foo) {/* no-op */}
1623 	}
1624 	@Rest(messages="BasicRestInfoProviderTest", swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
1625 	public static class P5b {
1626 		@RestGet(path="/path/{foo}/responses/100")
1627 		public P5c a() {return null;}
1628 	}
1629 	@Response(headers=@Header(name="X-Foo",schema=@Schema(description="$L{foo}",type="integer",format="int32"))) @StatusCode(100)
1630 	public static class P5c {}
1631 
1632 	@Test void p05a_response_100_headers_swaggerOnAnnotation_localized() throws Exception {
1633 		assertMap(getSwagger(new P5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{l-foo,integer,int32}");
1634 		assertMap(getSwaggerWithFile(new P5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{l-foo,integer,int32}");
1635 	}
1636 	@Test void p05b_response_100_headers_swaggerOnAnnotation_localized() throws Exception {
1637 		assertMap(getSwagger(new P5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{l-foo,integer,int32}");
1638 		assertMap(getSwaggerWithFile(new P5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders(), "X-Foo{description,type,format}", "{l-foo,integer,int32}");
1639 	}
1640 
1641 	//------------------------------------------------------------------------------------------------------------------
1642 	// /paths/<path>/<method>/responses/<response>/examples
1643 	//------------------------------------------------------------------------------------------------------------------
1644 
1645 	@Rest
1646 	public static class R1a {
1647 		@RestGet(path="/path/{foo}/responses/100")
1648 		public void a(Value<R1c> foo) {/* no-op */}
1649 	}
1650 	@Rest
1651 	public static class R1b {
1652 		@RestGet(path="/path/{foo}/responses/100")
1653 		public R1c a() {return null;}
1654 	}
1655 	@Response @StatusCode(100)
1656 	public static class R1c {
1657 		public String a;
1658 	}
1659 
1660 	@Test void r01a_responses_100_examples_default() throws Exception {
1661 		assertNull(getSwagger(new R1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
1662 		assertMap(getSwaggerWithFile(new R1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo", "a");
1663 	}
1664 	@Test void r01b_responses_100_examples_default() throws Exception {
1665 		assertNull(getSwagger(new R1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
1666 		assertMap(getSwaggerWithFile(new R1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo", "a");
1667 	}
1668 
1669 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
1670 	public static class R2 {
1671 		@RestGet(path="/path/{foo}/responses/100")
1672 		public void a(@StatusCode Value<Integer> foo) {/* no-op */}
1673 	}
1674 
1675 	@Test void r02_response_100_examples_swaggerOnClass() throws Exception {
1676 		assertMap(getSwagger(new R2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo{bar}", "{b}");
1677 		assertMap(getSwaggerWithFile(new R2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo{bar}", "{b}");
1678 	}
1679 
1680 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
1681 	public static class R3 {
1682 		@RestGet(path="/path/{foo}/responses/100",swagger=@OpSwagger("responses:{100:{examples:{foo:{bar:'c'}}}}"))
1683 		public void a(@StatusCode Value<Integer> foo) {/* no-op */}
1684 	}
1685 
1686 	@Test void r03_response_100_examples_swaggerOnMethod() throws Exception {
1687 		assertMap(getSwagger(new R3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo{bar}", "{c}");
1688 		assertMap(getSwaggerWithFile(new R3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo{bar}", "{c}");
1689 	}
1690 
1691 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
1692 	public static class R4a {
1693 		@RestGet(path="/path/{foo}/responses/100")
1694 		public void a(Value<R4c> foo) {/* no-op */}
1695 	}
1696 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
1697 	public static class R4b {
1698 		@RestGet(path="/path/{foo}/responses/100")
1699 		public R4c a() {return null;}
1700 	}
1701 	@Response(examples="{foo:{bar:'d'}}") @StatusCode(100)
1702 	public static class R4c {}
1703 
1704 	@Test void r04a_response_100_examples_swaggerOnAnnotation() throws Exception {
1705 		assertMap(getSwagger(new R4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo{bar}", "{d}");
1706 		assertMap(getSwaggerWithFile(new R4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo{bar}", "{d}");
1707 	}
1708 	@Test void r04b_response_100_examples_swaggerOnAnnotation() throws Exception {
1709 		assertMap(getSwagger(new R4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo{bar}", "{d}");
1710 		assertMap(getSwaggerWithFile(new R4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo{bar}", "{d}");
1711 	}
1712 
1713 	@Rest(messages="BasicRestInfoProviderTest", swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
1714 	public static class R5a {
1715 		@RestGet(path="/path/{foo}/responses/100")
1716 		public void a(Value<R5c> foo) {/* no-op */}
1717 	}
1718 	@Rest(messages="BasicRestInfoProviderTest", swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
1719 	public static class R5b {
1720 		@RestGet(path="/path/{foo}/responses/100")
1721 		public R5c a() {return null;}
1722 	}
1723 	@Response(examples="{foo:{bar:'$L{foo}'}}") @StatusCode(100)
1724 	public static class R5c {}
1725 
1726 	@Test void r05a_response_100_examples_swaggerOnAnnotation_lodalized() throws Exception {
1727 		assertMap(getSwagger(new R5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo{bar}", "{l-foo}");
1728 		assertMap(getSwaggerWithFile(new R5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo{bar}", "{l-foo}");
1729 	}
1730 	@Test void r05b_response_100_examples_swaggerOnAnnotation_lodalized() throws Exception {
1731 		assertMap(getSwagger(new R5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo{bar}", "{l-foo}");
1732 		assertMap(getSwaggerWithFile(new R5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples(), "foo{bar}", "{l-foo}");
1733 	}
1734 
1735 	//------------------------------------------------------------------------------------------------------------------
1736 	// /paths/<path>/<method>/responses/<response>/schema
1737 	//------------------------------------------------------------------------------------------------------------------
1738 
1739 	@Rest
1740 	public static class S1a {
1741 		@RestGet(path="/path/{foo}/responses/100")
1742 		public void a(Value<S1c> foo) {/* no-op */}
1743 	}
1744 	@Rest
1745 	public static class S1b {
1746 		@RestGet(path="/path/{foo}/responses/100")
1747 		public S1c a() {return null;}
1748 	}
1749 	@Response @StatusCode(100)
1750 	public static class S1c extends X {}
1751 
1752 	@Test void s01a_responses_100_schema_default() throws Exception {
1753 		assertBean(getSwagger(new S1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "type,properties{a{format,type}}", "object,{{int32,integer}}");
1754 		assertBean(getSwaggerWithFile(new S1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "type,items{ref}", "array,{#/definitions/Foo}");
1755 	}
1756 	@Test void s01b_responses_100_schema_default() throws Exception {
1757 		assertBean(getSwagger(new S1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "type,properties{a{format,type}}", "object,{{int32,integer}}");
1758 		assertBean(getSwaggerWithFile(new S1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "type,items{ref}", "array,{#/definitions/Foo}");
1759 	}
1760 
1761 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
1762 	public static class S2 {
1763 		@RestGet(path="/path/{foo}/responses/100")
1764 		public void a(@StatusCode Value<Integer> foo) {/* no-op */}
1765 	}
1766 
1767 	@Test void s02_response_100_schema_swaggerOnClass() throws Exception {
1768 		assertBean(getSwagger(new S2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "ref", "b");
1769 		assertBean(getSwaggerWithFile(new S2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "ref", "b");
1770 	}
1771 
1772 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
1773 	public static class S3 {
1774 		@RestGet(path="/path/{foo}/responses/100",swagger=@OpSwagger("responses:{100:{schema:{$ref:'c'}}}}"))
1775 		public void a(@StatusCode Value<Integer> foo) {/* no-op */}
1776 	}
1777 
1778 	@Test void s03_response_100_schema_swaggerOnMethoe() throws Exception {
1779 		assertBean(getSwagger(new S3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "ref", "c");
1780 		assertBean(getSwaggerWithFile(new S3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "ref", "c");
1781 	}
1782 
1783 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
1784 	public static class S4a {
1785 		@RestGet(path="/path/{foo}/responses/100")
1786 		public void a(Value<S4c> foo) {/* no-op */}
1787 	}
1788 	@Rest(swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
1789 	public static class S4b {
1790 		@RestGet(path="/path/{foo}/responses/100")
1791 		public S4c a() {return null;}
1792 	}
1793 	@Response(schema=@Schema($ref="d")) @StatusCode(100)
1794 	public static class S4c extends X {}
1795 
1796 	@Test void s04a_response_100_schema_swaggerOnAnnotation() throws Exception {
1797 		assertBean(getSwagger(new S4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "ref", "d");
1798 		assertBean(getSwaggerWithFile(new S4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "ref", "d");
1799 	}
1800 	@Test void s04b_response_100_schema_swaggerOnAnnotation() throws Exception {
1801 		assertBean(getSwagger(new S4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "ref", "d");
1802 		assertBean(getSwaggerWithFile(new S4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "ref", "d");
1803 	}
1804 
1805 	@Rest(messages="BasicRestInfoProviderTest", swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
1806 	public static class S5a {
1807 		@RestGet(path="/path/{foo}/responses/100")
1808 		public void a(Value<S5c> foo) {/* no-op */}
1809 	}
1810 	@Rest(messages="BasicRestInfoProviderTest", swagger=@Swagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
1811 	public static class S5b {
1812 		@RestGet(path="/path/{foo}/responses/100")
1813 		public S5c a() {return null;}
1814 	}
1815 	@Response(schema=@Schema($ref="l-foo")) @StatusCode(100)
1816 	public static class S5c extends X {}
1817 
1818 	@Test void s05a_response_100_schema_swaggerOnAnnotation_loealized() throws Exception {
1819 		assertBean(getSwagger(new S5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "ref", "l-foo");
1820 		assertBean(getSwaggerWithFile(new S5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "ref", "l-foo");
1821 	}
1822 	@Test void s05b_response_100_schema_swaggerOnAnnotation_loealized() throws Exception {
1823 		assertBean(getSwagger(new S5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "ref", "l-foo");
1824 		assertBean(getSwaggerWithFile(new S5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema(), "ref", "l-foo");
1825 	}
1826 
1827 	@Bean(typeName="Foo")
1828 	public static class X {
1829 		public int a;
1830 	}
1831 
1832 	//------------------------------------------------------------------------------------------------------------------
1833 	// Example bean with getter-only property.
1834 	//------------------------------------------------------------------------------------------------------------------
1835 
1836 	@Rest
1837 	public static class T1 extends BasicRestServlet {
1838 		private static final long serialVersionUID = 1L;
1839 
1840 		@RestGet(path="/")
1841 		public T2 a(@Content T2 body) {
1842 			return null;
1843 		}
1844 	}
1845 
1846 	@Bean(sort=true)
1847 	public static class T2 {
1848 		private int f1;
1849 		public int getF1() { return f1; }
1850 		public T2 setF1(int v) { f1 = v; return this; }
1851 
1852 		public int getF2() { return 2; }
1853 
1854 		@Example
1855 		public static T2 example() {
1856 			return new T2().setF1(1);
1857 		}
1858 	}
1859 
1860 	@Test void t01_bodyWithReadOnlyProperty() throws Exception {
1861 		var p = MockRestClient.build(T1.class);
1862 		var s = JsonParser.DEFAULT.parse(p.get("/api").accept("application/json").run().getContent().asString(), org.apache.juneau.bean.swagger.Swagger.class);
1863 		var o = s.getOperation("/", "get");
1864 
1865 		var ri = o.getResponse("200");
1866 		assertMap(ri.getExamples(), "application/json5", "{\n\tf1: 1,\n\tf2: 2\n}");
1867 	}
1868 }