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