001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.dto.swagger; 014 015import static org.apache.juneau.internal.StringUtils.*; 016import static org.apache.juneau.internal.CollectionUtils.*; 017import static org.apache.juneau.internal.ObjectUtils.*; 018 019import java.util.*; 020 021import org.apache.juneau.*; 022import org.apache.juneau.annotation.*; 023import org.apache.juneau.http.*; 024import org.apache.juneau.internal.*; 025import org.apache.juneau.json.*; 026import org.apache.juneau.utils.*; 027 028/** 029 * This is the root document object for the API specification. 030 * 031 * <ul class='seealso'> 032 * <li class='link'>{@doc juneau-dto.Swagger} 033 * </ul> 034 */ 035@Bean(bpi="swagger,info,tags,externalDocs,basePath,schemes,consumes,produces,paths,definitions,parameters,responses,securityDefinitions,security,*") 036public class Swagger extends SwaggerElement { 037 038 /** Represents a null swagger */ 039 public static final Swagger NULL = new Swagger(); 040 041 private static final Comparator<String> PATH_COMPARATOR = new Comparator<String>() { 042 @Override /* Comparator */ 043 public int compare(String o1, String o2) { 044 return o1.replace('{', '@').compareTo(o2.replace('{', '@')); 045 } 046 }; 047 048 private String 049 swagger = "2.0", 050 host, 051 basePath; 052 private Info info; 053 private ExternalDocumentation externalDocs; 054 private List<String> schemes; 055 private List<MediaType> 056 consumes, 057 produces; 058 private List<Tag> tags; 059 private List<Map<String,List<String>>> security; 060 private Map<String,ObjectMap> definitions; 061 private Map<String,ParameterInfo> parameters; 062 private Map<String,ResponseInfo> responses; 063 private Map<String,SecurityScheme> securityDefinitions; 064 private Map<String,OperationMap> paths; 065 066 /** 067 * Default constructor. 068 */ 069 public Swagger() {} 070 071 /** 072 * Copy constructor. 073 * 074 * @param copyFrom The object to copy. 075 */ 076 public Swagger(Swagger copyFrom) { 077 super(copyFrom); 078 079 this.swagger = copyFrom.swagger; 080 this.host = copyFrom.host; 081 this.basePath = copyFrom.basePath; 082 this.info = copyFrom.info == null ? null : copyFrom.info.copy(); 083 this.externalDocs = copyFrom.externalDocs == null ? null : copyFrom.externalDocs.copy(); 084 this.schemes = newList(copyFrom.schemes); 085 this.consumes = newList(copyFrom.consumes); 086 this.produces = newList(copyFrom.produces); 087 088 if (copyFrom.tags == null) { 089 this.tags = null; 090 } else { 091 this.tags = new ArrayList<>(); 092 for (Tag t : copyFrom.tags) 093 this.tags.add(t.copy()); 094 } 095 096 if (copyFrom.security == null) { 097 this.security = null; 098 } else { 099 this.security = new ArrayList<>(); 100 for (Map<String,List<String>> m : copyFrom.security) { 101 Map<String,List<String>> m2 = new LinkedHashMap<>(); 102 for (Map.Entry<String,List<String>> e : m.entrySet()) 103 m2.put(e.getKey(), newList(e.getValue())); 104 this.security.add(m2); 105 } 106 } 107 108 // TODO - Definitions are not deep copied, so they should not contain references. 109 if (copyFrom.definitions == null) { 110 this.definitions = null; 111 } else { 112 this.definitions = new LinkedHashMap<>(); 113 for (Map.Entry<String,ObjectMap> e : copyFrom.definitions.entrySet()) 114 this.definitions.put(e.getKey(), new ObjectMap(e.getValue())); 115 } 116 117 if (copyFrom.parameters == null) { 118 this.parameters = null; 119 } else { 120 this.parameters = new LinkedHashMap<>(); 121 for (Map.Entry<String,ParameterInfo> e : copyFrom.parameters.entrySet()) 122 this.parameters.put(e.getKey(), e.getValue().copy()); 123 } 124 125 if (copyFrom.responses == null) { 126 this.responses = null; 127 } else { 128 this.responses = new LinkedHashMap<>(); 129 for (Map.Entry<String,ResponseInfo> e : copyFrom.responses.entrySet()) 130 this.responses.put(e.getKey(), e.getValue().copy()); 131 } 132 133 if (copyFrom.securityDefinitions == null) { 134 this.securityDefinitions = null; 135 } else { 136 this.securityDefinitions = new LinkedHashMap<>(); 137 for (Map.Entry<String,SecurityScheme> e : copyFrom.securityDefinitions.entrySet()) 138 this.securityDefinitions.put(e.getKey(), e.getValue().copy()); 139 } 140 141 if (copyFrom.paths == null) { 142 this.paths = null; 143 } else { 144 this.paths = new LinkedHashMap<>(); 145 for (Map.Entry<String,OperationMap> e : copyFrom.paths.entrySet()) { 146 OperationMap m = new OperationMap(); 147 for (Map.Entry<String,Operation> e2 : e.getValue().entrySet()) 148 m.put(e2.getKey(), e2.getValue().copy()); 149 this.paths.put(e.getKey(), m); 150 } 151 } 152 } 153 154 /** 155 * Make a deep copy of this object. 156 * 157 * @return A deep copy of this object. 158 */ 159 public Swagger copy() { 160 return new Swagger(this); 161 } 162 163 /** 164 * Bean property getter: <property>swagger</property>. 165 * 166 * <p> 167 * Specifies the Swagger Specification version being used. 168 * 169 * <p> 170 * It can be used by the Swagger UI and other clients to interpret the API listing. 171 * 172 * @return The property value, or <jk>null</jk> if it is not set. 173 */ 174 public String getSwagger() { 175 return swagger; 176 } 177 178 /** 179 * Bean property setter: <property>swagger</property>. 180 * 181 * <p> 182 * Specifies the Swagger Specification version being used. 183 * 184 * <p> 185 * It can be used by the Swagger UI and other clients to interpret the API listing. 186 * 187 * @param value 188 * The new value for this property. 189 * <br>Property value is required. 190 * @return This object (for method chaining). 191 */ 192 public Swagger setSwagger(String value) { 193 swagger = value; 194 return this; 195 } 196 197 /** 198 * Same as {@link #setSwagger(String)}. 199 * 200 * @param value 201 * The new value for this property. 202 * <br>Non-String values will be converted to String using <c>toString()</c>. 203 * <br>Can be <jk>null</jk> to unset the property. 204 * @return This object (for method chaining). 205 */ 206 public Swagger swagger(Object value) { 207 return setSwagger(stringify(value)); 208 } 209 210 /** 211 * Bean property getter: <property>info</property>. 212 * 213 * <p> 214 * Provides metadata about the API. 215 * 216 * <p> 217 * The metadata can be used by the clients if needed. 218 * 219 * @return The property value, or <jk>null</jk> if it is not set. 220 */ 221 public Info getInfo() { 222 return info; 223 } 224 225 /** 226 * Bean property setter: <property>info</property>. 227 * 228 * <p> 229 * Provides metadata about the API. 230 * 231 * <p> 232 * The metadata can be used by the clients if needed. 233 * 234 * @param value 235 * The new value for this property. 236 * <br>Property value is required. 237 * @return This object (for method chaining). 238 */ 239 public Swagger setInfo(Info value) { 240 info = value; 241 return this; 242 } 243 244 /** 245 * Same as {@link #setInfo(Info)}. 246 * 247 * @param value 248 * The new value for this property. 249 * <br>Valid types: 250 * <ul> 251 * <li>{@link Info} 252 * <li><c>String</c> - JSON object representation of {@link Info} 253 * <p class='bcode w800'> 254 * <jc>// Example </jc> 255 * info(<js>"{title:'title',description:'description',...}"</js>); 256 * </p> 257 * </ul> 258 * <br>Property value is required. 259 * @return This object (for method chaining). 260 */ 261 public Swagger info(Object value) { 262 return setInfo(toType(value, Info.class)); 263 } 264 265 /** 266 * Bean property getter: <property>host</property>. 267 * 268 * <p> 269 * The host (name or IP) serving the API. 270 * 271 * @return The property value, or <jk>null</jk> if it is not set. 272 */ 273 public String getHost() { 274 return host; 275 } 276 277 /** 278 * Bean property setter: <property>host</property>. 279 * 280 * <p> 281 * The host (name or IP) serving the API. 282 * 283 * @param value 284 * The new value for this property. 285 * <br>This MUST be the host only and does not include the scheme nor sub-paths. 286 * <br>It MAY include a port. 287 * <br>If the host is not included, the host serving the documentation is to be used (including the port). 288 * <br>The host does not support {@doc SwaggerPathTemplating path templating} 289 * <br>Can be <jk>null</jk> to unset the property. 290 * @return This object (for method chaining). 291 */ 292 public Swagger setHost(String value) { 293 host = value; 294 return this; 295 } 296 297 /** 298 * Same as {@link #setHost(String)}. 299 * 300 * @param value 301 * The new value for this property. 302 * <br>Non-String values will be converted to String using <c>toString()</c>. 303 * <br>This MUST be the host only and does not include the scheme nor sub-paths. 304 * <br>It MAY include a port. 305 * <br>If the host is not included, the host serving the documentation is to be used (including the port). 306 * <br>The host does not support {@doc SwaggerPathTemplating path templating} 307 * <br>Can be <jk>null</jk> to unset the property. 308 * @return This object (for method chaining). 309 */ 310 public Swagger host(Object value) { 311 return setHost(stringify(value)); 312 } 313 314 /** 315 * Bean property getter: <property>basePath</property>. 316 * 317 * <p> 318 * The base path on which the API is served, which is relative to the <c>host</c>. 319 * 320 * @return The property value, or <jk>null</jk> if it is not set. 321 */ 322 public String getBasePath() { 323 return basePath; 324 } 325 326 /** 327 * Bean property setter: <property>basePath</property>. 328 * 329 * <p> 330 * The base path on which the API is served, which is relative to the <c>host</c>. 331 * 332 * @param value 333 * The new value for this property. 334 * <br>If it is not included, the API is served directly under the <c>host</c>. 335 * <br>The value MUST start with a leading slash (/). 336 * <br>The <c>basePath</c> does not support {@doc SwaggerPathTemplating path templating}. 337 * <br>Can be <jk>null</jk> to unset the property. 338 * @return This object (for method chaining). 339 */ 340 public Swagger setBasePath(String value) { 341 basePath = value; 342 return this; 343 } 344 345 /** 346 * Same as {@link #setBasePath(String)}. 347 * 348 * @param value 349 * The new value for this property. 350 * <br>Non-String values will be converted to String using <c>toString()</c>. 351 * <br>If it is not included, the API is served directly under the <c>host</c>. 352 * <br>The value MUST start with a leading slash (/). 353 * <br>The <c>basePath</c> does not support {@doc SwaggerPathTemplating path templating}. 354 * <br>Can be <jk>null</jk> to unset the property. 355 * @return This object (for method chaining). 356 */ 357 public Swagger basePath(Object value) { 358 return setBasePath(stringify(value)); 359 } 360 361 /** 362 * Bean property getter: <property>schemes</property>. 363 * 364 * <p> 365 * The transfer protocol of the API. 366 * 367 * <p> 368 * If the <c>schemes</c> is not included, the default scheme to be used is the one used to access the Swagger 369 * definition itself. 370 * 371 * @return The property value, or <jk>null</jk> if it is not set. 372 */ 373 public List<String> getSchemes() { 374 return schemes; 375 } 376 377 /** 378 * Bean property setter: <property>schemes</property>. 379 * 380 * <p> 381 * The transfer protocol of the API. 382 * 383 * <p> 384 * If the <c>schemes</c> is not included, the default scheme to be used is the one used to access the Swagger 385 * definition itself. 386 * 387 * @param value 388 * The new value for this property. 389 * <br>Valid values: 390 * <ul> 391 * <li><js>"http"</js> 392 * <li><js>"https"</js> 393 * <li><js>"ws"</js> 394 * <li><js>"wss"</js> 395 * </ul> 396 * <br>Can be <jk>null</jk> to unset the property. 397 * @return This object (for method chaining). 398 */ 399 public Swagger setSchemes(Collection<String> value) { 400 schemes = newList(value); 401 return this; 402 } 403 404 /** 405 * Adds one or more values to the <property>schemes</property> property. 406 * 407 * <p> 408 * The transfer protocol of the API. 409 * 410 * <p> 411 * Values MUST be from the list: <js>"http"</js>, <js>"https"</js>, <js>"ws"</js>, <js>"wss"</js>. 412 * If the <c>schemes</c> is not included, the default scheme to be used is the one used to access the Swagger 413 * definition itself. 414 * 415 * @param values 416 * The values to add to this property. 417 * <br>Valid values: 418 * <ul> 419 * <li><js>"http"</js> 420 * <li><js>"https"</js> 421 * <li><js>"ws"</js> 422 * <li><js>"wss"</js> 423 * </ul> 424 * <br>Ignored if <jk>null</jk>. 425 * @return This object (for method chaining). 426 */ 427 public Swagger addSchemes(Collection<String> values) { 428 schemes = addToList(schemes, values); 429 return this; 430 } 431 432 /** 433 * Same as {@link #addSchemes(Collection)}. 434 * 435 * @param values 436 * The values to add to this property. 437 * <br>Valid types: 438 * <ul> 439 * <li><c>Collection<String></c> 440 * <li><c>String</c> - JSON array representation of <c>Collection<String></c> 441 * <p class='bcode w800'> 442 * <jc>// Example </jc> 443 * schemes(<js>"['scheme1','scheme2']"</js>); 444 * </p> 445 * <li><c>String</c> - Individual values 446 * <p class='bcode w800'> 447 * <jc>// Example </jc> 448 * schemes(<js>"scheme1"</js>, <js>"scheme2"</js>); 449 * </p> 450 * </ul> 451 * @return This object (for method chaining). 452 */ 453 public Swagger schemes(Object...values) { 454 schemes = addToList(schemes, values, String.class); 455 return this; 456 } 457 458 /** 459 * Bean property getter: <property>consumes</property>. 460 * 461 * <p> 462 * A list of MIME types the APIs can consume. 463 * 464 * <p> 465 * This is global to all APIs but can be overridden on specific API calls. 466 * 467 * @return The property value, or <jk>null</jk> if it is not set. 468 */ 469 public List<MediaType> getConsumes() { 470 return consumes; 471 } 472 473 /** 474 * Bean property setter: <property>consumes</property>. 475 * 476 * <p> 477 * A list of MIME types the APIs can consume. 478 * 479 * <p> 480 * This is global to all APIs but can be overridden on specific API calls. 481 * 482 * @param value 483 * The new value for this property. 484 * <br>Value MUST be as described under {@doc SwaggerMimeTypes}. 485 * <br>Can be <jk>null</jk> to unset the property. 486 * @return This object (for method chaining). 487 */ 488 public Swagger setConsumes(Collection<MediaType> value) { 489 consumes = newList(value); 490 return this; 491 } 492 493 /** 494 * Adds one or more values to the <property>consumes</property> property. 495 * 496 * <p> 497 * A list of MIME types the operation can consume. 498 * This overrides the <c>consumes</c> definition at the Swagger Object. 499 * An empty value MAY be used to clear the global definition. 500 * Value MUST be as described under {@doc SwaggerMimeTypes}. 501 * 502 * @param values 503 * The values to add to this property. 504 * <br>Values MUST be as described under {@doc SwaggerMimeTypes}. 505 * <br>Ignored if <jk>null</jk>. 506 * @return This object (for method chaining). 507 */ 508 public Swagger addConsumes(Collection<MediaType> values) { 509 consumes = addToList(consumes, values); 510 return this; 511 } 512 513 /** 514 * Adds one or more values to the <property>consumes</property> property. 515 * 516 * @param values 517 * The values to add to this property. 518 * <br>Valid types: 519 * <ul> 520 * <li>{@link MediaType} 521 * <li><c>Collection<{@link MediaType}|String></c> 522 * <li><c>String</c> - JSON array representation of <c>Collection<{@link MediaType}></c> 523 * <p class='bcode w800'> 524 * <jc>// Example </jc> 525 * consumes(<js>"['text/json']"</js>); 526 * </p> 527 * <li><c>String</c> - Individual values 528 * <p class='bcode w800'> 529 * <jc>// Example </jc> 530 * consumes(<js>"text/json"</js>); 531 * </p> 532 * </ul> 533 * <br>Ignored if <jk>null</jk>. 534 * @return This object (for method chaining). 535 */ 536 public Swagger consumes(Object...values) { 537 consumes = addToList(consumes, values, MediaType.class); 538 return this; 539 } 540 541 /** 542 * Bean property getter: <property>produces</property>. 543 * 544 * <p> 545 * A list of MIME types the APIs can produce. 546 * 547 * <p> 548 * This is global to all APIs but can be overridden on specific API calls. 549 * 550 * @return The property value, or <jk>null</jk> if it is not set. 551 */ 552 public List<MediaType> getProduces() { 553 return produces; 554 } 555 556 /** 557 * Bean property setter: <property>produces</property>. 558 * 559 * <p> 560 * A list of MIME types the APIs can produce. 561 * 562 * <p> 563 * This is global to all APIs but can be overridden on specific API calls. 564 * 565 * @param value 566 * The new value for this property. 567 * <br>Value MUST be as described under {@doc SwaggerMimeTypes}. 568 * <br>Can be <jk>null</jk> to unset the property. 569 * @return This object (for method chaining). 570 */ 571 public Swagger setProduces(Collection<MediaType> value) { 572 produces = newList(value); 573 return this; 574 } 575 576 /** 577 * Adds one or more values to the <property>produces</property> property. 578 * 579 * <p> 580 * A list of MIME types the APIs can produce. 581 * 582 * <p> 583 * This is global to all APIs but can be overridden on specific API calls. 584 * 585 * @param values 586 * The values to add to this property. 587 * <br>Value MUST be as described under {@doc SwaggerMimeTypes}. 588 * <br>Can be <jk>null</jk> to unset the property. 589 * @return This object (for method chaining). 590 */ 591 public Swagger addProduces(Collection<MediaType> values) { 592 produces = addToList(produces, values); 593 return this; 594 } 595 596 /** 597 * Adds one or more values to the <property>produces</property> property. 598 * 599 * @param values 600 * The values to add to this property. 601 * <br>Valid types: 602 * <ul> 603 * <li>{@link MediaType} 604 * <li><c>Collection<{@link MediaType}|String></c> 605 * <li><c>String</c> - JSON array representation of <c>Collection<{@link MediaType}></c> 606 * <p class='bcode w800'> 607 * <jc>// Example </jc> 608 * consumes(<js>"['text/json']"</js>); 609 * </p> 610 * <li><c>String</c> - Individual values 611 * <p class='bcode w800'> 612 * <jc>// Example </jc> 613 * consumes(<js>"text/json"</js>); 614 * </p> 615 * </ul> 616 * <br>Ignored if <jk>null</jk>. 617 * @return This object (for method chaining). 618 */ 619 public Swagger produces(Object...values) { 620 produces = addToList(produces, values, MediaType.class); 621 return this; 622 } 623 624 /** 625 * Bean property getter: <property>paths</property>. 626 * 627 * <p> 628 * The available paths and operations for the API. 629 * 630 * @return The property value, or <jk>null</jk> if it is not set. 631 */ 632 public Map<String,OperationMap> getPaths() { 633 return paths; 634 } 635 636 /** 637 * Shortcut for calling <c>getPaths().get(path);</c> 638 * 639 * @param path The path (e.g. <js>"/foo"</js>). 640 * @return The operation map for the specified path, or <jk>null</jk> if it doesn't exist. 641 */ 642 public OperationMap getPath(String path) { 643 return getPaths().get(path); 644 } 645 646 /** 647 * Shortcut for calling <c>getPaths().get(path).get(operation);</c> 648 * 649 * @param path The path (e.g. <js>"/foo"</js>). 650 * @param operation The HTTP operation (e.g. <js>"get"</js>). 651 * @return The operation for the specified path and operation id, or <jk>null</jk> if it doesn't exist. 652 */ 653 public Operation getOperation(String path, String operation) { 654 OperationMap om = getPath(path); 655 if (om == null) 656 return null; 657 return om.get(operation); 658 } 659 660 /** 661 * Shortcut for calling <c>getPaths().get(path).get(operation).getResponse(status);</c> 662 * 663 * @param path The path (e.g. <js>"/foo"</js>). 664 * @param operation The HTTP operation (e.g. <js>"get"</js>). 665 * @param status The HTTP response status (e.g. <js>"200"</js>). 666 * @return The operation for the specified path and operation id, or <jk>null</jk> if it doesn't exist. 667 */ 668 public ResponseInfo getResponseInfo(String path, String operation, Object status) { 669 OperationMap om = getPath(path); 670 if (om == null) 671 return null; 672 Operation op = om.get(operation); 673 if (op == null) 674 return null; 675 return op.getResponse(status); 676 } 677 678 /** 679 * Bean property setter: <property>paths</property>. 680 * 681 * <p> 682 * The available paths and operations for the API. 683 * 684 * @param value 685 * The new value for this property. 686 * <br>Property value is required. 687 * @return This object (for method chaining). 688 */ 689 public Swagger setPaths(Map<String,OperationMap> value) { 690 paths = newSortedMap(value, PATH_COMPARATOR); 691 return this; 692 } 693 694 /** 695 * Adds one or more values to the <property>produces</property> property. 696 * 697 * <p> 698 * A list of MIME types the APIs can produce. 699 * 700 * <p> 701 * This is global to all APIs but can be overridden on specific API calls. 702 * 703 * @param values 704 * The values to add to this property. 705 * <br>Ignored if <jk>null</jk>. 706 * @return This object (for method chaining). 707 */ 708 public Swagger addPaths(Map<String,OperationMap> values) { 709 paths = addToSortedMap(paths, values, PATH_COMPARATOR); 710 return this; 711 } 712 713 /** 714 * Adds a single value to the <property>paths</property> property. 715 * 716 * @param path The path template. 717 * @param methodName The HTTP method name. 718 * @param operation The operation that describes the path. 719 * @return This object (for method chaining). 720 */ 721 public Swagger path(String path, String methodName, Operation operation) { 722 if (paths == null) 723 paths = new TreeMap<>(PATH_COMPARATOR); 724 OperationMap p = paths.get(path); 725 if (p == null) { 726 p = new OperationMap(); 727 paths.put(path, p); 728 } 729 p.put(methodName, operation); 730 return this; 731 } 732 733 /** 734 * Adds one or more values to the <property>paths</property> property. 735 * 736 * @param values 737 * The values to add to this property. 738 * <br>Valid types: 739 * <ul> 740 * <li><c>Map<String,Map<String,{@link Operation}>|String></c> 741 * <li><c>String</c> - JSON object representation of <c>Map<String,Map<String,{@link Operation}>></c> 742 * <p class='bcode w800'> 743 * <jc>// Example </jc> 744 * paths(<js>"{'foo':{'get':{operationId:'operationId',...}}}"</js>); 745 * </p> 746 * </ul> 747 * <br>Ignored if <jk>null</jk>. 748 * @return This object (for method chaining). 749 */ 750 @SuppressWarnings({ "unchecked", "rawtypes" }) 751 public Swagger paths(Object...values) { 752 if (paths == null) 753 paths = new TreeMap<>(PATH_COMPARATOR); 754 paths = addToMap((Map)paths, values, String.class, Map.class, String.class, Operation.class); 755 return this; 756 } 757 758 /** 759 * Bean property getter: <property>definitions</property>. 760 * 761 * <p> 762 * An object to hold data types produced and consumed by operations. 763 * 764 * @return The property value, or <jk>null</jk> if it is not set. 765 */ 766 public Map<String,ObjectMap> getDefinitions() { 767 return definitions; 768 } 769 770 /** 771 * Bean property setter: <property>definitions</property>. 772 * 773 * <p> 774 * An object to hold data types produced and consumed by operations. 775 * 776 * @param value 777 * The new value for this property. 778 * <br>Can be <jk>null</jk> to unset the property. 779 * @return This object (for method chaining). 780 */ 781 public Swagger setDefinitions(Map<String,ObjectMap> value) { 782 definitions = newMap(value); 783 return this; 784 } 785 786 /** 787 * Adds one or more values to the <property>definitions</property> property. 788 * 789 * <p> 790 * An object to hold data types produced and consumed by operations. 791 * 792 * @param values 793 * The values to add to this property. 794 * <br>Ignored if <jk>null</jk>. 795 * @return This object (for method chaining). 796 */ 797 public Swagger addDefinitions(Map<String,ObjectMap> values) { 798 definitions = addToMap(definitions, values); 799 return this; 800 } 801 802 /** 803 * Adds a single value to the <property>definitions</property> property. 804 * 805 * @param name A definition name. 806 * @param schema The schema that the name defines. 807 * @return This object (for method chaining). 808 */ 809 public Swagger definition(String name, ObjectMap schema) { 810 definitions = addToMap(definitions, name, schema); 811 return this; 812 } 813 814 /** 815 * Adds one or more values to the <property>definitions</property> property. 816 * 817 * @param values 818 * The values to add to this property. 819 * <br>Valid types: 820 * <ul> 821 * <li><c>Map<String,Map<String,{@link SchemaInfo}>|String></c> 822 * <li><c>String</c> - JSON object representation of <c>Map<String,Map<String,{@link SchemaInfo}>></c> 823 * <p class='bcode w800'> 824 * <jc>// Example </jc> 825 * definitions(<js>"{'foo':{'bar':{format:'format',...}}}"</js>); 826 * </p> 827 * </ul> 828 * <br>Ignored if <jk>null</jk>. 829 * @return This object (for method chaining). 830 */ 831 public Swagger definitions(Object...values) { 832 definitions = addToMap(definitions, values, String.class, ObjectMap.class); 833 return this; 834 } 835 836 /** 837 * Convenience method for testing whether this Swagger has one or more definitions defined. 838 * 839 * @return <jk>true</jk> if this Swagger has one or more definitions defined. 840 */ 841 public boolean hasDefinitions() { 842 return definitions != null && ! definitions.isEmpty(); 843 } 844 845 /** 846 * Bean property getter: <property>parameters</property>. 847 * 848 * <p> 849 * An object to hold parameters that can be used across operations. 850 * 851 * <p> 852 * This property does not define global parameters for all operations. 853 * 854 * @return The property value, or <jk>null</jk> if it is not set. 855 */ 856 public Map<String,ParameterInfo> getParameters() { 857 return parameters; 858 } 859 860 /** 861 * Bean property setter: <property>parameters</property>. 862 * 863 * <p> 864 * An object to hold parameters that can be used across operations. 865 * 866 * <p> 867 * This property does not define global parameters for all operations. 868 * 869 * @param value 870 * The new value for this property. 871 * <br>Can be <jk>null</jk> to unset the property. 872 * @return This object (for method chaining). 873 */ 874 public Swagger setParameters(Map<String,ParameterInfo> value) { 875 parameters = newMap(value); 876 return this; 877 } 878 879 /** 880 * Adds one or more values to the <property>parameters</property> property. 881 * 882 * <p> 883 * An object to hold parameters that can be used across operations. 884 * 885 * <p> 886 * This property does not define global parameters for all operations. 887 * 888 * @param values 889 * The values to add to this property. 890 * <br>Ignored if <jk>null</jk>. 891 * @return This object (for method chaining). 892 */ 893 public Swagger addParameters(Map<String,ParameterInfo> values) { 894 parameters = addToMap(parameters, values); 895 return this; 896 } 897 898 /** 899 * Adds a single value to the <property>parameter</property> property. 900 * 901 * @param name The parameter name. 902 * @param parameter The parameter definition. 903 * @return This object (for method chaining). 904 */ 905 public Swagger parameter(String name, ParameterInfo parameter) { 906 parameters = addToMap(parameters, name, parameter); 907 return this; 908 } 909 910 /** 911 * Adds one or more values to the <property>properties</property> property. 912 * 913 * @param values 914 * The values to add to this property. 915 * <br>Valid types: 916 * <ul> 917 * <li><c>Map<String,{@link ParameterInfo}|String></c> 918 * <li><c>String</c> - JSON object representation of <c>Map<String,{@link ParameterInfo}></c> 919 * <p class='bcode w800'> 920 * <jc>// Example </jc> 921 * parameters(<js>"{'foo':{name:'name',...}}"</js>); 922 * </p> 923 * </ul> 924 * <br>Ignored if <jk>null</jk>. 925 * @return This object (for method chaining). 926 */ 927 public Swagger parameters(Object...values) { 928 parameters = addToMap(parameters, values, String.class, ParameterInfo.class); 929 return this; 930 } 931 932 /** 933 * Convenience method for calling <c>getPath(path).get(method).getParameter(in,name);</c> 934 * 935 * @param path The HTTP path. 936 * @param method The HTTP method. 937 * @param in The parameter type. 938 * @param name The parameter name. 939 * @return The parameter information or <jk>null</jk> if not found. 940 */ 941 public ParameterInfo getParameterInfo(String path, String method, String in, String name) { 942 OperationMap om = getPath(path); 943 if (om != null) { 944 Operation o = om.get(method); 945 if (o != null) { 946 return o.getParameter(in, name); 947 } 948 } 949 return null; 950 } 951 952 /** 953 * Bean property getter: <property>responses</property>. 954 * 955 * <p> 956 * An object to hold responses that can be used across operations. 957 * 958 * <p> 959 * This property does not define global responses for all operations. 960 * 961 * @return The property value, or <jk>null</jk> if it is not set. 962 */ 963 public Map<String,ResponseInfo> getResponses() { 964 return responses; 965 } 966 967 /** 968 * Bean property setter: <property>responses</property>. 969 * 970 * <p> 971 * An object to hold responses that can be used across operations. 972 * 973 * <p> 974 * This property does not define global responses for all operations. 975 * 976 * @param value 977 * The new value for this property. 978 * <br>Can be <jk>null</jk> to unset the property. 979 * @return This object (for method chaining). 980 */ 981 public Swagger setResponses(Map<String,ResponseInfo> value) { 982 responses = newMap(value); 983 return this; 984 } 985 986 /** 987 * Adds one or more values to the <property>responses</property> property. 988 * 989 * <p> 990 * An object to hold responses that can be used across operations. 991 * 992 * <p> 993 * This property does not define global responses for all operations. 994 * 995 * @param values 996 * The values to add to this property. 997 * <br>Ignored if <jk>null</jk>. 998 * @return This object (for method chaining). 999 */ 1000 public Swagger addResponses(Map<String,ResponseInfo> values) { 1001 responses = addToMap(responses, values); 1002 return this; 1003 } 1004 1005 /** 1006 * Adds a single value to the <property>responses</property> property. 1007 * 1008 * @param name The response name. 1009 * @param response The response definition. 1010 * @return This object (for method chaining). 1011 */ 1012 public Swagger response(String name, ResponseInfo response) { 1013 responses = addToMap(responses, name, response); 1014 return this; 1015 } 1016 1017 /** 1018 * Adds one or more values to the <property>properties</property> property. 1019 * 1020 * @param values 1021 * The values to add to this property. 1022 * <br>Valid types: 1023 * <ul> 1024 * <li><c>Map<String,{@link ResponseInfo}|String></c> 1025 * <li><c>String</c> - JSON object representation of <c>Map<String,{@link ResponseInfo}></c> 1026 * <p class='bcode w800'> 1027 * <jc>// Example </jc> 1028 * responses(<js>"{'foo':{description:'description',...}}"</js>); 1029 * </p> 1030 * </ul> 1031 * <br>Ignored if <jk>null</jk>. 1032 * @return This object (for method chaining). 1033 */ 1034 public Swagger responses(Object...values) { 1035 responses = addToMap(responses, values, String.class, ResponseInfo.class); 1036 return this; 1037 } 1038 1039 /** 1040 * Bean property getter: <property>securityDefinitions</property>. 1041 * 1042 * <p> 1043 * Security scheme definitions that can be used across the specification. 1044 * 1045 * @return The property value, or <jk>null</jk> if it is not set. 1046 */ 1047 public Map<String,SecurityScheme> getSecurityDefinitions() { 1048 return securityDefinitions; 1049 } 1050 1051 /** 1052 * Bean property setter: <property>securityDefinitions</property>. 1053 * 1054 * <p> 1055 * Security scheme definitions that can be used across the specification. 1056 * 1057 * @param value 1058 * The new value for this property. 1059 * <br>Can be <jk>null</jk> to unset the property. 1060 * @return This object (for method chaining). 1061 */ 1062 public Swagger setSecurityDefinitions(Map<String,SecurityScheme> value) { 1063 securityDefinitions = newMap(value); 1064 return this; 1065 } 1066 1067 /** 1068 * Adds one or more values to the <property>securityDefinitions</property> property. 1069 * 1070 * <p> 1071 * Security scheme definitions that can be used across the specification. 1072 * 1073 * @param values 1074 * The values to add to this property. 1075 * <br>Ignored if <jk>null</jk>. 1076 * @return This object (for method chaining). 1077 */ 1078 public Swagger addSecurityDefinitions(Map<String,SecurityScheme> values) { 1079 securityDefinitions = addToMap(securityDefinitions, values); 1080 return this; 1081 } 1082 1083 /** 1084 * Adds a single value to the <property>securityDefinitions</property> property. 1085 * 1086 * @param name A security name. 1087 * @param securityScheme A security schema. 1088 * @return This object (for method chaining). 1089 */ 1090 public Swagger securityDefinition(String name, SecurityScheme securityScheme) { 1091 securityDefinitions = addToMap(securityDefinitions, name, securityScheme); 1092 return this; 1093 } 1094 1095 /** 1096 * Adds one or more values to the <property>securityDefinitions</property> property. 1097 * 1098 * @param values 1099 * The values to add to this property. 1100 * <br>Valid types: 1101 * <ul> 1102 * <li><c>Map<String,{@link SecurityScheme}|String></c> 1103 * <li><c>String</c> - JSON object representation of <c>Map<String,{@link SecurityScheme}></c> 1104 * <p class='bcode w800'> 1105 * <jc>// Example </jc> 1106 * securityDefinitions(<js>"{'foo':{name:'name',...}}"</js>); 1107 * </p> 1108 * </ul> 1109 * <br>Ignored if <jk>null</jk>. 1110 * @return This object (for method chaining). 1111 */ 1112 public Swagger securityDefinitions(Object...values) { 1113 securityDefinitions = addToMap(securityDefinitions, values, String.class, SecurityScheme.class); 1114 return this; 1115 } 1116 1117 /** 1118 * Bean property getter: <property>security</property>. 1119 * 1120 * <p> 1121 * A declaration of which security schemes are applied for the API as a whole. 1122 * 1123 * <p> 1124 * The list of values describes alternative security schemes that can be used (that is, there is a logical OR 1125 * between the security requirements). 1126 * <br>Individual operations can override this definition. 1127 * 1128 * @return The property value, or <jk>null</jk> if it is not set. 1129 */ 1130 public List<Map<String,List<String>>> getSecurity() { 1131 return security; 1132 } 1133 1134 /** 1135 * Bean property setter: <property>security</property>. 1136 * 1137 * <p> 1138 * A declaration of which security schemes are applied for the API as a whole. 1139 * 1140 * <p> 1141 * The list of values describes alternative security schemes that can be used (that is, there is a logical OR 1142 * between the security requirements). 1143 * <br>Individual operations can override this definition. 1144 * 1145 * @param value 1146 * The new value for this property. 1147 * <br>Can be <jk>null</jk> to unset the property. 1148 * @return This object (for method chaining). 1149 */ 1150 public Swagger setSecurity(Collection<Map<String,List<String>>> value) { 1151 security = newList(value); 1152 return this; 1153 } 1154 1155 /** 1156 * Adds one or more values to the <property>security</property> property. 1157 * 1158 * <p> 1159 * A declaration of which security schemes are applied for the API as a whole. 1160 * 1161 * <p> 1162 * The list of values describes alternative security schemes that can be used (that is, there is a logical OR 1163 * between the security requirements). 1164 * <br>Individual operations can override this definition. 1165 * 1166 * @param values 1167 * The values to add to this property. 1168 * <br>Ignored if <jk>null</jk>. 1169 * @return This object (for method chaining). 1170 */ 1171 public Swagger addSecurity(Collection<Map<String,List<String>>> values) { 1172 security = addToList(security, values); 1173 return this; 1174 } 1175 1176 1177 /** 1178 * Adds a single value to the <property>securityDefinitions</property> property. 1179 * 1180 * @param scheme The security scheme that applies to this operation 1181 * @param alternatives 1182 * The list of values describes alternative security schemes that can be used (that is, there is a logical OR between the security requirements). 1183 * @return This object (for method chaining). 1184 */ 1185 public Swagger security(String scheme, String...alternatives) { 1186 Map<String,List<String>> m = new LinkedHashMap<>(); 1187 m.put(scheme, Arrays.asList(alternatives)); 1188 return addSecurity(Collections.singleton(m)); 1189 } 1190 1191 /** 1192 * Adds one or more values to the <property>securityDefinitions</property> property. 1193 * 1194 * @param values 1195 * The values to add to this property. 1196 * <br>Valid types: 1197 * <ul> 1198 * <li><c>Collection<Map<String,List<String>>></c> 1199 * <li><c>String</c> - JSON array representation of <c>Collection<Map<String,List<String>>></c> 1200 * <p class='bcode w800'> 1201 * <jc>// Example </jc> 1202 * securities(<js>"[{...}]"</js>); 1203 * </p> 1204 * <li><c>String</c> - JSON object representation of <c>Map<String,List<String>></c> 1205 * <p class='bcode w800'> 1206 * <jc>// Example </jc> 1207 * securities(<js>"{...}"</js>); 1208 * </p> 1209 * </ul> 1210 * <br>Ignored if <jk>null</jk>. 1211 * @return This object (for method chaining). 1212 */ 1213 @SuppressWarnings({ "unchecked", "rawtypes" }) 1214 public Swagger securities(Object...values) { 1215 security = addToList((List)security, values, Map.class, String.class, List.class, String.class); 1216 return this; 1217 } 1218 1219 /** 1220 * Bean property getter: <property>tags</property>. 1221 * 1222 * <p> 1223 * A list of tags used by the specification with additional metadata. 1224 * 1225 * @return The property value, or <jk>null</jk> if it is not set. 1226 */ 1227 public List<Tag> getTags() { 1228 return tags; 1229 } 1230 1231 /** 1232 * Bean property setter: <property>tags</property>. 1233 * 1234 * <p> 1235 * A list of tags used by the specification with additional metadata. 1236 * 1237 * @param value 1238 * The new value for this property. 1239 * <br>The order of the tags can be used to reflect on their order by the parsing tools. 1240 * <br>Not all tags that are used by the {@doc SwaggerOperationObject Operation Object} must be declared. 1241 * <br>The tags that are not declared may be organized randomly or based on the tools' logic. 1242 * <br>Each tag name in the list MUST be unique. 1243 * <br>Can be <jk>null</jk> to unset the property. 1244 * @return This object (for method chaining). 1245 */ 1246 public Swagger setTags(Collection<Tag> value) { 1247 tags = newList(value); 1248 return this; 1249 } 1250 1251 /** 1252 * Adds one or more values to the <property>security</property> property. 1253 * 1254 * <p> 1255 * A list of tags used by the specification with additional metadata. 1256 * 1257 * @param values 1258 * The values to add to this property. 1259 * <br>The order of the tags can be used to reflect on their order by the parsing tools. 1260 * <br>Not all tags that are used by the {@doc SwaggerOperationObject Operation Object} must be declared. 1261 * <br>The tags that are not declared may be organized randomly or based on the tools' logic. 1262 * <br>Each tag name in the list MUST be unique. 1263 * <br>Ignored if <jk>null</jk>. 1264 * @return This object (for method chaining). 1265 */ 1266 public Swagger addTags(Collection<Tag> values) { 1267 tags = addToList(tags, values); 1268 return this; 1269 } 1270 1271 1272 /** 1273 * Adds one or more values to the <property>tags</property> property. 1274 * 1275 * @param values 1276 * The values to add to this property. 1277 * <br>Valid types: 1278 * <ul> 1279 * <li>{@link Tag} 1280 * <li><c>Collection<{@link Tag}|String></c> 1281 * <li><c>{@link Tag}[]</c> 1282 * <li><c>String</c> - JSON array representation of <c>Collection<{@link Tag}></c> 1283 * <p class='bcode w800'> 1284 * <jc>// Example </jc> 1285 * tags(<js>"[{name:'name',description:'description',...}]"</js>); 1286 * </p> 1287 * <li><c>String</c> - JSON object representation of <c>{@link Tag}</c> 1288 * <p class='bcode w800'> 1289 * <jc>// Example </jc> 1290 * tags(<js>"{name:'name',description:'description',...}"</js>); 1291 * </p> 1292 * </ul> 1293 * <br>Ignored if <jk>null</jk>. 1294 * @return This object (for method chaining). 1295 */ 1296 public Swagger tags(Object...values) { 1297 tags = addToList(tags, values, Tag.class); 1298 return this; 1299 } 1300 1301 /** 1302 * Convenience method for testing whether this Swagger has one or more tags defined. 1303 * 1304 * @return <jk>true</jk> if this Swagger has one or more tags defined. 1305 */ 1306 public boolean hasTags() { 1307 return tags != null && ! tags.isEmpty(); 1308 } 1309 1310 /** 1311 * Bean property getter: <property>externalDocs</property>. 1312 * 1313 * <p> 1314 * Additional external documentation. 1315 * 1316 * @return The property value, or <jk>null</jk> if it is not set. 1317 */ 1318 public ExternalDocumentation getExternalDocs() { 1319 return externalDocs; 1320 } 1321 1322 /** 1323 * Bean property setter: <property>externalDocs</property>. 1324 * 1325 * <p> 1326 * Additional external documentation. 1327 * 1328 * @param value 1329 * The new value for this property. 1330 * <br>Can be <jk>null</jk> to unset the property. 1331 * @return This object (for method chaining). 1332 */ 1333 public Swagger setExternalDocs(ExternalDocumentation value) { 1334 externalDocs = value; 1335 return this; 1336 } 1337 1338 /** 1339 * Same as {@link #setExternalDocs(ExternalDocumentation)}. 1340 * 1341 * @param value 1342 * The new value for this property. 1343 * <br>Valid types: 1344 * <ul> 1345 * <li>{@link ExternalDocumentation} 1346 * <li><c>String</c> - JSON object representation of {@link ExternalDocumentation} 1347 * <p class='bcode w800'> 1348 * <jc>// Example </jc> 1349 * externalDocs(<js>"{description:'description',url:'url'}"</js>); 1350 * </p> 1351 * </ul> 1352 * <br>Can be <jk>null</jk> to unset the property. 1353 * @return This object (for method chaining). 1354 */ 1355 public Swagger externalDocs(Object value) { 1356 return setExternalDocs(toType(value, ExternalDocumentation.class)); 1357 } 1358 1359 @Override /* SwaggerElement */ 1360 public <T> T get(String property, Class<T> type) { 1361 if (property == null) 1362 return null; 1363 switch (property) { 1364 case "swagger": return toType(getSwagger(), type); 1365 case "info": return toType(getInfo(), type); 1366 case "host": return toType(getHost(), type); 1367 case "basePath": return toType(getBasePath(), type); 1368 case "schemes": return toType(getSchemes(), type); 1369 case "consumes": return toType(getConsumes(), type); 1370 case "produces": return toType(getProduces(), type); 1371 case "paths": return toType(getPaths(), type); 1372 case "definitions": return toType(getDefinitions(), type); 1373 case "parameters": return toType(getParameters(), type); 1374 case "responses": return toType(getResponses(), type); 1375 case "securityDefinitions": return toType(getSecurityDefinitions(), type); 1376 case "security": return toType(getSecurity(), type); 1377 case "tags": return toType(getTags(), type); 1378 case "externalDocs": return toType(getExternalDocs(), type); 1379 default: return super.get(property, type); 1380 } 1381 } 1382 1383 @Override /* SwaggerElement */ 1384 public Swagger set(String property, Object value) { 1385 if (property == null) 1386 return this; 1387 switch (property) { 1388 case "swagger": return swagger(value); 1389 case "info": return info(value); 1390 case "host": return host(value); 1391 case "basePath": return basePath(value); 1392 case "schemes": return setSchemes(null).schemes(value); 1393 case "consumes": return setConsumes(null).consumes(value); 1394 case "produces": return setProduces(null).produces(value); 1395 case "paths": return setPaths(null).paths(value); 1396 case "definitions": return setDefinitions(null).definitions(value); 1397 case "parameters": return setParameters(null).parameters(value); 1398 case "responses": return setResponses(null).responses(value); 1399 case "securityDefinitions": return setSecurityDefinitions(null).securityDefinitions(value); 1400 case "security": return setSecurity(null).securities(value); 1401 case "tags": return setTags(null).tags(value); 1402 case "externalDocs": return externalDocs(value); 1403 default: 1404 super.set(property, value); 1405 return this; 1406 } 1407 } 1408 1409 @Override /* SwaggerElement */ 1410 public Set<String> keySet() { 1411 ASet<String> s = new ASet<String>() 1412 .appendIf(swagger != null, "swagger") 1413 .appendIf(info != null, "info") 1414 .appendIf(host != null, "host") 1415 .appendIf(basePath != null, "basePath") 1416 .appendIf(schemes != null, "schemes") 1417 .appendIf(consumes != null, "consumes") 1418 .appendIf(produces != null, "produces") 1419 .appendIf(paths != null, "paths") 1420 .appendIf(definitions != null, "definitions") 1421 .appendIf(parameters != null, "parameters") 1422 .appendIf(responses != null, "responses") 1423 .appendIf(securityDefinitions != null, "securityDefinitions") 1424 .appendIf(security != null, "security") 1425 .appendIf(tags != null, "tags") 1426 .appendIf(externalDocs != null, "externalDocs"); 1427 return new MultiSet<>(s, super.keySet()); 1428 } 1429 1430 @Override /* Object */ 1431 public String toString() { 1432 return JsonSerializer.DEFAULT.toString(this); 1433 } 1434 1435 /** 1436 * Resolves a <js>"$ref"</js> tags to nodes in this swagger document. 1437 * 1438 * @param ref The ref tag value. 1439 * @param c The class to convert the reference to. 1440 * @return The referenced node, or <jk>null</jk> if the ref was <jk>null</jk> or empty or not found. 1441 */ 1442 public <T> T findRef(String ref, Class<T> c) { 1443 if (isEmpty(ref)) 1444 return null; 1445 if (! ref.startsWith("#/")) 1446 throw new RuntimeException("Unsupported reference: '" + ref + '"'); 1447 try { 1448 return new PojoRest(this).get(ref.substring(1), c); 1449 } catch (Exception e) { 1450 throw new BeanRuntimeException(e, c, "Reference ''{0}'' could not be converted to type ''{1}''.", ref, c.getName()); 1451 } 1452 } 1453}