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.BeanPropertyUtils.*; 016import static org.apache.juneau.internal.StringUtils.*; 017 018import java.util.*; 019 020import org.apache.juneau.annotation.*; 021import org.apache.juneau.http.*; 022import org.apache.juneau.internal.*; 023import org.apache.juneau.utils.*; 024 025/** 026 * Describes a single API operation on a path. 027 * 028 * <h5 class='section'>Example:</h5> 029 * <p class='bcode w800'> 030 * <jc>// Construct using SwaggerBuilder.</jc> 031 * Operation x = <jsm>operation</jsm>() 032 * .tags(<js>"pet"</js>) 033 * .summary(<js>"Updates a pet in the store with form data"</js>) 034 * .description(<js>""</js>) 035 * .operationId(<js>"updatePetWithForm"</js>) 036 * .consumes(<js>"application/x-www-form-urlencoded"</js>) 037 * .produces(<js>"application/json"</js>, <js>"application/xml"</js>) 038 * .parameters( 039 * <jsm>parameter</jsm>() 040 * .name(<js>"petId"</js>) 041 * .in(<js>"path"</js>) 042 * .description(<js>"ID of pet that needs to be updated"</js>) 043 * .required(<jk>true</jk>) 044 * .type(<js>"string"</js>), 045 * <jsm>parameter</jsm>() 046 * .name(<js>"name"</js>) 047 * .in(<js>"formData"</js>) 048 * .description(<js>"Updated name of the pet"</js>) 049 * .required(<jk>false</jk>) 050 * .type(<js>"string"</js>), 051 * <jsm>parameter</jsm>() 052 * .name(<js>"status"</js>) 053 * .in(<js>"formData"</js>) 054 * .description(<js>"Updated status of the pet"</js>) 055 * .required(<jk>false</jk>) 056 * .type(<js>"string"</js>) 057 * ) 058 * .response(200, <jsm>responseInfo</jsm>(<js>"Pet updated."</js>)) 059 * .response(405, <jsm>responseInfo</jsm>(<js>"Invalid input."</js>)) 060 * .security(<js>"petstore_auth"</js>, <js>"write:pets"</js>, <js>"read:pets"</js>); 061 * 062 * <jc>// Serialize using JsonSerializer.</jc> 063 * String json = JsonSerializer.<jsf>DEFAULT</jsf>.toString(x); 064 * 065 * <jc>// Or just use toString() which does the same as above.</jc> 066 * String json = x.toString(); 067 * </p> 068 * <p class='bcode w800'> 069 * <jc>// Output</jc> 070 * { 071 * <js>"tags"</js>: [ 072 * <js>"pet"</js> 073 * ], 074 * <js>"summary"</js>: <js>"Updates a pet in the store with form data"</js>, 075 * <js>"description"</js>: <js>""</js>, 076 * <js>"operationId"</js>: <js>"updatePetWithForm"</js>, 077 * <js>"consumes"</js>: [ 078 * <js>"application/x-www-form-urlencoded"</js> 079 * ], 080 * <js>"produces"</js>: [ 081 * <js>"application/json"</js>, 082 * <js>"application/xml"</js> 083 * ], 084 * <js>"parameters"</js>: [ 085 * { 086 * <js>"name"</js>: <js>"petId"</js>, 087 * <js>"in"</js>: <js>"path"</js>, 088 * <js>"description"</js>: <js>"ID of pet that needs to be updated"</js>, 089 * <js>"required"</js>: <jk>true</jk>, 090 * <js>"type"</js>: <js>"string"</js> 091 * }, 092 * { 093 * <js>"name"</js>: <js>"name"</js>, 094 * <js>"in"</js>: <js>"formData"</js>, 095 * <js>"description"</js>: <js>"Updated name of the pet"</js>, 096 * <js>"required"</js>: <jk>false</jk>, 097 * <js>"type"</js>: <js>"string"</js> 098 * }, 099 * { 100 * <js>"name"</js>: <js>"status"</js>, 101 * <js>"in"</js>: <js>"formData"</js>, 102 * <js>"description"</js>: <js>"Updated status of the pet"</js>, 103 * <js>"required"</js>: <jk>false</jk>, 104 * <js>"type"</js>: <js>"string"</js> 105 * } 106 * ], 107 * <js>"responses"</js>: { 108 * <js>"200"</js>: { 109 * <js>"description"</js>: <js>"Pet updated."</js> 110 * }, 111 * <js>"405"</js>: { 112 * <js>"description"</js>: <js>"Invalid input"</js> 113 * } 114 * }, 115 * <js>"security"</js>: [ 116 * { 117 * <js>"petstore_auth"</js>: [ 118 * <js>"write:pets"</js>, 119 * <js>"read:pets"</js> 120 * ] 121 * } 122 * ] 123 * } 124 * </p> 125 * 126 * <h5 class='section'>See Also:</h5> 127 * <ul class='doctree'> 128 * <li class='link'>{@doc juneau-dto.Swagger} 129 * </ul> 130 */ 131@Bean(properties="operationId,summary,description,tags,externalDocs,consumes,produces,parameters,responses,schemes,deprecated,security,*") 132public class Operation extends SwaggerElement { 133 134 private String 135 summary, 136 description, 137 operationId; 138 private Boolean deprecated; 139 private ExternalDocumentation externalDocs; 140 private List<String> 141 tags, 142 schemes; 143 private List<MediaType> 144 consumes, 145 produces; 146 private List<ParameterInfo> parameters; 147 private List<Map<String,List<String>>> security; 148 private Map<String,ResponseInfo> responses; 149 150 /** 151 * Default constructor. 152 */ 153 public Operation() {} 154 155 /** 156 * Copy constructor. 157 * 158 * @param copyFrom The object to copy. 159 */ 160 public Operation(Operation copyFrom) { 161 super(copyFrom); 162 163 this.summary = copyFrom.summary; 164 this.description = copyFrom.description; 165 this.operationId = copyFrom.operationId; 166 this.deprecated = copyFrom.deprecated; 167 this.externalDocs = copyFrom.externalDocs == null ? null : copyFrom.externalDocs.copy(); 168 this.tags = newList(copyFrom.tags); 169 this.schemes = newList(copyFrom.schemes); 170 this.consumes = newList(copyFrom.consumes); 171 this.produces = newList(copyFrom.produces); 172 173 if (copyFrom.parameters == null) { 174 this.parameters = null; 175 } else { 176 this.parameters = new ArrayList<>(); 177 for (ParameterInfo p : copyFrom.parameters) 178 this.parameters.add(p.copy()); 179 } 180 181 if (copyFrom.security == null) { 182 this.security = null; 183 } else { 184 this.security = new ArrayList<>(); 185 for (Map<String,List<String>> m : copyFrom.security) { 186 Map<String,List<String>> m2 = new LinkedHashMap<>(); 187 for (Map.Entry<String,List<String>> e : m.entrySet()) 188 m2.put(e.getKey(), newList(e.getValue())); 189 this.security.add(m2); 190 } 191 } 192 193 if (copyFrom.responses == null) { 194 this.responses = null; 195 } else { 196 this.responses = new LinkedHashMap<>(); 197 for (Map.Entry<String,ResponseInfo> e : copyFrom.responses.entrySet()) 198 this.responses.put(e.getKey(), e.getValue().copy()); 199 } 200 } 201 202 /** 203 * Make a deep copy of this object. 204 * 205 * @return A deep copy of this object. 206 */ 207 public Operation copy() { 208 return new Operation(this); 209 } 210 211 /** 212 * Bean property getter: <property>tags</property>. 213 * 214 * <p> 215 * A list of tags for API documentation control. 216 * <br>Tags can be used for logical grouping of operations by resources or any other qualifier. 217 * 218 * @return The property value, or <jk>null</jk> if it is not set. 219 */ 220 public List<String> getTags() { 221 return tags; 222 } 223 224 /** 225 * Bean property setter: <property>tags</property>. 226 * 227 * <p> 228 * A list of tags for API documentation control. 229 * <br>Tags can be used for logical grouping of operations by resources or any other qualifier. 230 * 231 * @param value 232 * The new value for this property. 233 * <br>Can be <jk>null</jk> to unset the property. 234 * @return This object (for method chaining). 235 */ 236 public Operation setTags(Collection<String> value) { 237 tags = newList(value); 238 return this; 239 } 240 241 /** 242 * Adds one or more values to the <property>tags</property> property. 243 * 244 * <p> 245 * A list of tags for API documentation control. 246 * <br>Tags can be used for logical grouping of operations by resources or any other qualifier. 247 * 248 * @param value 249 * The values to add to this property. 250 * <br>Ignored if <jk>null</jk>. 251 * @return This object (for method chaining). 252 */ 253 public Operation addTags(Collection<String> value) { 254 tags = addToList(tags, value); 255 return this; 256 } 257 258 /** 259 * Same as {@link #addTags(Collection)}. 260 * 261 * @param values 262 * The values to add to this property. 263 * <br>Valid types: 264 * <ul> 265 * <li><code>Collection<String></code> 266 * <li><code>String</code> - JSON array representation of <code>Collection<String></code> 267 * <h5 class='figure'>Example:</h5> 268 * <p class='bcode w800'> 269 * tags(<js>"['foo','bar']"</js>); 270 * </p> 271 * <li><code>String</code> - Individual values 272 * <h5 class='figure'>Example:</h5> 273 * <p class='bcode w800'> 274 * tags(<js>"foo"</js>, <js>"bar"</js>); 275 * </p> 276 * </ul> 277 * @return This object (for method chaining). 278 */ 279 public Operation tags(Object...values) { 280 tags = addToList(tags, values, String.class); 281 return this; 282 } 283 284 /** 285 * Bean property getter: <property>summary</property>. 286 * 287 * <p> 288 * A short summary of what the operation does. 289 * 290 * @return The property value, or <jk>null</jk> if it is not set. 291 */ 292 public String getSummary() { 293 return summary; 294 } 295 296 /** 297 * Bean property setter: <property>summary</property>. 298 * 299 * <p> 300 * A short summary of what the operation does. 301 * 302 * @param value 303 * The new value for this property. 304 * <br>Can be <jk>null</jk> to unset the property. 305 * @return This object (for method chaining). 306 */ 307 public Operation setSummary(String value) { 308 summary = value; 309 return this; 310 } 311 312 /** 313 * Same as {@link #setSummary(String)}. 314 * 315 * @param value 316 * The new value for this property. 317 * <br>Non-String values will be converted to String using <code>toString()</code>. 318 * <br>Can be <jk>null</jk> to unset the property. 319 * @return This object (for method chaining). 320 */ 321 public Operation summary(Object value) { 322 return setSummary(toStringVal(value)); 323 } 324 325 /** 326 * Bean property getter: <property>description</property>. 327 * 328 * <p> 329 * A verbose explanation of the operation behavior. 330 * 331 * @return The property value, or <jk>null</jk> if it is not set. 332 */ 333 public String getDescription() { 334 return description; 335 } 336 337 /** 338 * Bean property setter: <property>description</property>. 339 * 340 * <p> 341 * A verbose explanation of the operation behavior. 342 * 343 * @param value 344 * The new value for this property. 345 * <br>{@doc GFM} can be used for rich text representation. 346 * <br>Can be <jk>null</jk> to unset the property. 347 * @return This object (for method chaining). 348 */ 349 public Operation setDescription(String value) { 350 description = value; 351 return this; 352 } 353 354 /** 355 * Same as {@link #setDescription(String)}. 356 * 357 * @param value 358 * The new value for this property. 359 * <br>Non-String values will be converted to String using <code>toString()</code>. 360 * <br>{@doc GFM} can be used for rich text representation. 361 * <br>Can be <jk>null</jk> to unset the property. 362 * @return This object (for method chaining). 363 */ 364 public Operation description(Object value) { 365 return setDescription(toStringVal(value)); 366 } 367 368 /** 369 * Bean property getter: <property>externalDocs</property>. 370 * 371 * <p> 372 * Additional external documentation for this operation. 373 * 374 * @return The property value, or <jk>null</jk> if it is not set. 375 */ 376 public ExternalDocumentation getExternalDocs() { 377 return externalDocs; 378 } 379 380 /** 381 * Bean property setter: <property>externalDocs</property>. 382 * 383 * <p> 384 * Additional external documentation for this operation. 385 * 386 * @param value 387 * The values to add to this property. 388 * <br>Can be <jk>null</jk> to unset the property. 389 * @return This object (for method chaining). 390 */ 391 public Operation setExternalDocs(ExternalDocumentation value) { 392 externalDocs = value; 393 return this; 394 } 395 396 /** 397 * Same as {@link #setExternalDocs(ExternalDocumentation)}. 398 * 399 * @param value 400 * The new value for this property. 401 * <br>Valid types: 402 * <ul> 403 * <li>{@link ExternalDocumentation} 404 * <li><code>String</code> - JSON object representation of {@link ExternalDocumentation} 405 * <h5 class='figure'>Example:</h5> 406 * <p class='bcode w800'> 407 * externalDocs(<js>"{description:'description',url:'url'}"</js>); 408 * </p> 409 * </ul> 410 * <br>Can be <jk>null</jk> to unset the property. 411 * @return This object (for method chaining). 412 */ 413 public Operation externalDocs(Object value) { 414 return setExternalDocs(toType(value, ExternalDocumentation.class)); 415 } 416 417 /** 418 * Bean property getter: <property>operationId</property>. 419 * 420 * <p> 421 * Unique string used to identify the operation. 422 * 423 * @return The property value, or <jk>null</jk> if it is not set. 424 */ 425 public String getOperationId() { 426 return operationId; 427 } 428 429 /** 430 * Bean property setter: <property>operationId</property>. 431 * 432 * <p> 433 * Unique string used to identify the operation. 434 * 435 * @param value 436 * The new value for this property. 437 * <br>The id MUST be unique among all operations described in the API. 438 * <br>Tools and libraries MAY use the operationId to uniquely identify an operation, therefore, it is recommended to 439 * follow common programming naming conventions. 440 * <br>Can be <jk>null</jk> to unset the property. 441 * @return This object (for method chaining). 442 */ 443 public Operation setOperationId(String value) { 444 operationId = value; 445 return this; 446 } 447 448 /** 449 * Same as {@link #setOperationId(String)}. 450 * 451 * @param value 452 * The new value for this property. 453 * <br>The id MUST be unique among all operations described in the API. 454 * <br>Tools and libraries MAY use the operationId to uniquely identify an operation, therefore, it is recommended to 455 * follow common programming naming conventions. 456 * <br>Non-String values will be converted to String using <code>toString()</code>. 457 * <br>Can be <jk>null</jk> to unset the property. 458 * @return This object (for method chaining). 459 */ 460 public Operation operationId(Object value) { 461 return setOperationId(toStringVal(value)); 462 } 463 464 /** 465 * Bean property getter: <property>consumes</property>. 466 * 467 * <p> 468 * A list of MIME types the operation can consume. 469 * 470 * <p> 471 * This overrides the <code>consumes</code> definition at the Swagger Object. 472 * <br>An empty value MAY be used to clear the global definition. 473 * 474 * @return The property value, or <jk>null</jk> if it is not set. 475 */ 476 public List<MediaType> getConsumes() { 477 return consumes; 478 } 479 480 /** 481 * Bean property setter: <property>consumes</property>. 482 * 483 * <p> 484 * A list of MIME types the operation can consume. 485 * 486 * <p> 487 * This overrides the <code>consumes</code> definition at the Swagger Object. 488 * <br>An empty value MAY be used to clear the global definition. 489 * 490 * @param value 491 * The new value for this property. 492 * <br>Values MUST be as described under {@doc SwaggerMimeTypes}. 493 * <br>Can be <jk>null</jk> to unset the property. 494 * @return This object (for method chaining). 495 */ 496 public Operation setConsumes(Collection<MediaType> value) { 497 consumes = newList(value); 498 return this; 499 } 500 501 /** 502 * Adds one or more values to the <property>consumes</property> property. 503 * 504 * <p> 505 * A list of MIME types the operation can consume. 506 * 507 * <p> 508 * This overrides the <code>consumes</code> definition at the Swagger Object. 509 * <br>An empty value MAY be used to clear the global definition. 510 * 511 * @param value 512 * The values to add to this property. 513 * <br>Values MUST be as described under {@doc SwaggerMimeTypes}. 514 * <br>Ignored if <jk>null</jk>. 515 * @return This object (for method chaining). 516 */ 517 public Operation addConsumes(Collection<MediaType> value) { 518 consumes = addToList(consumes, value); 519 return this; 520 } 521 522 /** 523 * Adds one or more values to the <property>consumes</property> property. 524 * 525 * @param values 526 * The values to add to this property. 527 * <br>Valid types: 528 * <ul> 529 * <li>{@link MediaType} 530 * <li><code>Collection<{@link MediaType}|String></code> 531 * <li><code>{@link MediaType}[]</code> 532 * <li><code>String</code> - JSON array representation of <code>Collection<{@link MediaType}></code> 533 * <h5 class='figure'>Example:</h5> 534 * <p class='bcode w800'> 535 * consumes(<js>"['text/json']"</js>); 536 * </p> 537 * <li><code>String</code> - Individual values 538 * <h5 class='figure'>Example:</h5> 539 * <p class='bcode w800'> 540 * consumes(<js>"text/json"</js>); 541 * </p> 542 * </ul> 543 * <br>Ignored if <jk>null</jk>. 544 * @return This object (for method chaining). 545 */ 546 public Operation consumes(Object...values) { 547 consumes = addToList(consumes, values, MediaType.class); 548 return this; 549 } 550 551 /** 552 * Bean property getter: <property>produces</property>. 553 * 554 * <p> 555 * A list of MIME types the operation can produce. 556 * 557 * <p> 558 * This overrides the <code>produces</code> definition at the Swagger Object. 559 * <br>An empty value MAY be used to clear the global definition. 560 * 561 * @return The property value, or <jk>null</jk> if it is not set. 562 */ 563 public List<MediaType> getProduces() { 564 return produces; 565 } 566 567 /** 568 * Bean property setter: <property>produces</property>. 569 * 570 * <p> 571 * A list of MIME types the operation can produce. 572 * 573 * <p> 574 * This overrides the <code>produces</code> definition at the Swagger Object. 575 * <br>An empty value MAY be used to clear the global definition. 576 * 577 * @param value 578 * The values to add to this property. 579 * <br>Value MUST be as described under {@doc SwaggerMimeTypes}. 580 * <br>Can be <jk>null</jk> to unset the property. 581 * @return This object (for method chaining). 582 */ 583 public Operation setProduces(Collection<MediaType> value) { 584 produces = newList(value); 585 return this; 586 } 587 588 /** 589 * Adds one or more values to the <property>produces</property> property. 590 * 591 * <p> 592 * A list of MIME types the operation can produces. 593 * 594 * <p> 595 * This overrides the <code>produces</code> definition at the Swagger Object. 596 * <br>An empty value MAY be used to clear the global definition. 597 * 598 * @param value 599 * The values to add to this property. 600 * <br>Ignored if <jk>null</jk>. 601 * @return This object (for method chaining). 602 */ 603 public Operation addProduces(Collection<MediaType> value) { 604 produces = addToList(produces, value); 605 return this; 606 } 607 608 /** 609 * Same as {@link #addProduces(Collection)}. 610 * 611 * @param values 612 * The values to add to this property. 613 * <br>Valid types: 614 * <ul> 615 * <li>{@link MediaType} 616 * <li><code>Collection<{@link MediaType}|String></code> 617 * <li><code>{@link MediaType}[]</code> 618 * <li><code>String</code> - JSON array representation of <code>Collection<{@link MediaType}></code> 619 * <h5 class='figure'>Example:</h5> 620 * <p class='bcode w800'> 621 * produces(<js>"['text/json']"</js>); 622 * </p> 623 * <li><code>String</code> - Individual values 624 * <h5 class='figure'>Example:</h5> 625 * <p class='bcode w800'> 626 * produces(<js>"text/json"</js>); 627 * </p> 628 * </ul> 629 * <br>Ignored if <jk>null</jk>. 630 * @return This object (for method chaining). 631 */ 632 public Operation produces(Object...values) { 633 produces = addToList(produces, values, MediaType.class); 634 return this; 635 } 636 637 /** 638 * Bean property getter: <property>parameters</property>. 639 * 640 * <p> 641 * A list of parameters that are applicable for this operation. 642 * 643 * <h5 class='section'>Notes:</h5> 644 * <ul class='spaced-list'> 645 * <li> 646 * If a parameter is already defined at the {@doc SwaggerPathItemObject Path Item}, 647 * the new definition will override it, but can never remove it. 648 * <li> 649 * The list MUST NOT include duplicated parameters. 650 * <li> 651 * A unique parameter is defined by a combination of a <code>name</code> and <code>location</code>. 652 * <li> 653 * The list can use the {@doc SwaggerReferenceObject} 654 * to link to parameters that are defined at the {@doc SwaggerParameterObject Swagger Object's parameters}. 655 * <li> 656 * There can be one <js>"body"</js> parameter at most. 657 * </ul> 658 * 659 * @return The property value, or <jk>null</jk> if it is not set. 660 */ 661 public List<ParameterInfo> getParameters() { 662 return parameters; 663 } 664 665 /** 666 * Returns the parameter with the specified type and name. 667 * 668 * @param in The parameter in. 669 * @param name The parameter name. Can be <jk>null</jk> for parameter type <code>body</code>. 670 * @return The matching parameter info, or <jk>null</jk> if not found. 671 */ 672 public ParameterInfo getParameter(String in, String name) { 673 if (parameters != null) 674 for (ParameterInfo pi : parameters) 675 if (StringUtils.isEquals(pi.getIn(), in)) 676 if (StringUtils.isEquals(pi.getName(), name) || "body".equals(pi.getIn())) 677 return pi; 678 return null; 679 } 680 681 /** 682 * Bean property setter: <property>parameters</property>. 683 * 684 * <p> 685 * A list of parameters that are applicable for this operation. 686 * 687 * <h5 class='section'>Notes:</h5> 688 * <ul class='spaced-list'> 689 * <li> 690 * If a parameter is already defined at the {@doc SwaggerPathItemObject Path Item}, 691 * the new definition will override it, but can never remove it. 692 * <li> 693 * The list MUST NOT include duplicated parameters. 694 * <li> 695 * A unique parameter is defined by a combination of a <code>name</code> and <code>location</code>. 696 * <li> 697 * The list can use the {@doc SwaggerReferenceObject} 698 * to link to parameters that are defined at the {@doc SwaggerParameterObject Swagger Object's parameters}. 699 * <li> 700 * There can be one <js>"body"</js> parameter at most. 701 * </ul> 702 * 703 * @param value 704 * The new value for this property. 705 * <br>Can be <jk>null</jk> to unset the property. 706 * @return This object (for method chaining). 707 */ 708 public Operation setParameters(Collection<ParameterInfo> value) { 709 parameters = newList(value); 710 return this; 711 } 712 713 /** 714 * Adds one or more values to the <property>parameters</property> property. 715 * 716 * <p> 717 * A list of parameters that are applicable for this operation. 718 * 719 * <h5 class='section'>Notes:</h5> 720 * <ul class='spaced-list'> 721 * <li> 722 * If a parameter is already defined at the {@doc SwaggerPathItemObject Path Item}, 723 * the new definition will override it, but can never remove it. 724 * <li> 725 * The list MUST NOT include duplicated parameters. 726 * <li> 727 * A unique parameter is defined by a combination of a <code>name</code> and <code>location</code>. 728 * <li> 729 * The list can use the {@doc SwaggerReferenceObject} 730 * to link to parameters that are defined at the {@doc SwaggerParameterObject Swagger Object's parameters}. 731 * <li> 732 * There can be one <js>"body"</js> parameter at most. 733 * </ul> 734 * 735 * @param value 736 * The values to add to this property. 737 * <br>Ignored if <jk>null</jk>. 738 * @return This object (for method chaining). 739 */ 740 public Operation addParameters(Collection<ParameterInfo> value) { 741 parameters = addToList(parameters, value); 742 return this; 743 } 744 745 /** 746 * Same as {@link #addParameters(Collection)}. 747 * 748 * @param values 749 * The values to add to this property. 750 * <br>Valid types: 751 * <ul> 752 * <li>{@link ParameterInfo} 753 * <li><code>Collection<{@link ParameterInfo}|String></code> 754 * <li><code>String</code> - JSON array representation of <code>Collection<{@link ParameterInfo}></code> 755 * <h5 class='figure'>Example:</h5> 756 * <p class='bcode w800'> 757 * parameters(<js>"[{path:'path',id:'id'}]"</js>); 758 * </p> 759 * <li><code>String</code> - JSON object representation of {@link ParameterInfo} 760 * <h5 class='figure'>Example:</h5> 761 * <p class='bcode w800'> 762 * parameters(<js>"{path:'path',id:'id'}"</js>); 763 * </p> 764 * </ul> 765 * <br>Ignored if <jk>null</jk>. 766 * @return This object (for method chaining). 767 */ 768 public Operation parameters(Object...values) { 769 parameters = addToList(parameters, values, ParameterInfo.class); 770 return this; 771 } 772 773 /** 774 * Bean property getter: <property>responses</property>. 775 * 776 * <p> 777 * The list of possible responses as they are returned from executing this operation. 778 * 779 * @return The property value, or <jk>null</jk> if it is not set. 780 */ 781 public Map<String,ResponseInfo> getResponses() { 782 return responses; 783 } 784 785 786 /** 787 * Returns the response info with the given status code. 788 * 789 * @param status The HTTP status code. 790 * @return The response info, or <jk>null</jk> if not found. 791 */ 792 public ResponseInfo getResponse(Object status) { 793 if (responses != null) 794 return responses.get(String.valueOf(status)); 795 return null; 796 } 797 798 /** 799 * Bean property setter: <property>responses</property>. 800 * 801 * <p> 802 * The list of possible responses as they are returned from executing this operation. 803 * 804 * @param value 805 * The new value for this property. 806 * <br>Property value is required. 807 * @return This object (for method chaining). 808 */ 809 public Operation setResponses(Map<String,ResponseInfo> value) { 810 responses = newMap(value); 811 return this; 812 } 813 814 /** 815 * Adds one or more values to the <property>responses</property> property. 816 * 817 * <p> 818 * The list of possible responses as they are returned from executing this operation. 819 * 820 * @param values 821 * The values to add to this property. 822 * <br>Ignored if <jk>null</jk>. 823 * @return This object (for method chaining). 824 */ 825 public Operation addResponses(Map<String,ResponseInfo> values) { 826 responses = addToMap(responses, values); 827 return this; 828 } 829 830 /** 831 * Adds a single value to the <property>responses</property> property. 832 * 833 * @param statusCode The HTTP status code. 834 * @param response The response description. 835 * @return This object (for method chaining). 836 */ 837 public Operation response(String statusCode, ResponseInfo response) { 838 return addResponses(Collections.singletonMap(statusCode, response)); 839 } 840 841 /** 842 * Same as {@link #addResponses(Map)}. 843 * 844 * @param value 845 * The new value for this property. 846 * <br>Valid types: 847 * <ul> 848 * <li><code>Map<Integer,{@link ResponseInfo}|String></code> 849 * <li><code>String</code> - JSON object representation of <code>Map<Integer,{@link ResponseInfo}></code> 850 * <h5 class='figure'>Example:</h5> 851 * <p class='bcode w800'> 852 * responses(<js>"{'404':{description:'description',...}}"</js>); 853 * </p> 854 * </ul> 855 * @return This object (for method chaining). 856 */ 857 public Operation responses(Object...value) { 858 responses = addToMap(responses, value, String.class, ResponseInfo.class); 859 return this; 860 } 861 862 /** 863 * Bean property getter: <property>schemes</property>. 864 * 865 * <p> 866 * The transfer protocol for the operation. 867 * <br>The value overrides the Swagger Object <code>schemes</code> definition. 868 * 869 * @return The property value, or <jk>null</jk> if it is not set. 870 */ 871 public List<String> getSchemes() { 872 return schemes; 873 } 874 875 /** 876 * Bean property setter: <property>schemes</property>. 877 * 878 * <p> 879 * The transfer protocol for the operation. 880 * <br>The value overrides the Swagger Object <code>schemes</code> definition. 881 * 882 * @param value 883 * The new value for this property. 884 * <br>Valid values: 885 * <ul> 886 * <li><js>"http"</js> 887 * <li><js>"https"</js> 888 * <li><js>"ws"</js> 889 * <li><js>"wss"</js> 890 * </ul> 891 * <br>Can be <jk>null</jk> to unset the property. 892 * @return This object (for method chaining). 893 */ 894 public Operation setSchemes(Collection<String> value) { 895 schemes = newList(value); 896 return this; 897 } 898 899 /** 900 * Adds one or more values to the <property>schemes</property> property. 901 * 902 * <p> 903 * The transfer protocol for the operation. 904 * <br>The value overrides the Swagger Object <code>schemes</code> definition. 905 * 906 * @param value 907 * The values to add to this property. 908 * <br>Ignored if <jk>null</jk>. 909 * @return This object (for method chaining). 910 */ 911 public Operation addSchemes(Collection<String> value) { 912 schemes = addToList(schemes, value); 913 return this; 914 } 915 916 /** 917 * Same as {@link #addSchemes(Collection)}. 918 * 919 * @param values 920 * The new value for this property. 921 * <br>Valid types: 922 * <ul> 923 * <li><code>Collection<String></code> 924 * <li><code>String</code> - JSON array representation of <code>Collection<String></code> 925 * <h5 class='figure'>Example:</h5> 926 * <p class='bcode w800'> 927 * schemes(<js>"['scheme1','scheme2']"</js>); 928 * </p> 929 * <li><code>String</code> - Individual values 930 * <h5 class='figure'>Example:</h5> 931 * <p class='bcode w800'> 932 * schemes(<js>"scheme1</js>, <js>"scheme2"</js>); 933 * </p> 934 * </ul> 935 * @return This object (for method chaining). 936 */ 937 public Operation schemes(Object...values) { 938 schemes = addToList(schemes, values, String.class); 939 return this; 940 } 941 942 /** 943 * Bean property getter: <property>deprecated</property>. 944 * 945 * <p> 946 * Declares this operation to be deprecated. 947 * 948 * @return The property value, or <jk>null</jk> if it is not set. 949 */ 950 public Boolean getDeprecated() { 951 return deprecated; 952 } 953 954 /** 955 * Bean property getter: <property>deprecated</property>. 956 * 957 * <p> 958 * Declares this operation to be deprecated. 959 * 960 * @return The property value, or <jk>false</jk> if it is not set. 961 */ 962 public boolean isDeprecated() { 963 return deprecated != null && deprecated == true; 964 } 965 966 /** 967 * Bean property setter: <property>deprecated</property>. 968 * 969 * <p> 970 * Declares this operation to be deprecated. 971 * 972 * @param value T 973 * The new value for this property. 974 * @return This object (for method chaining). 975 */ 976 public Operation setDeprecated(Boolean value) { 977 deprecated = value; 978 return this; 979 } 980 981 /** 982 * Same as {@link #setDeprecated(Boolean)}. 983 * 984 * @param value 985 * The new value for this property. 986 * <br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>. 987 * <br>Can be <jk>null</jk> to unset the property. 988 * @return This object (for method chaining). 989 */ 990 public Operation deprecated(Object value) { 991 return setDeprecated(toBoolean(value)); 992 } 993 994 /** 995 * Bean property getter: <property>security</property>. 996 * 997 * <p> 998 * A declaration of which security schemes are applied for this operation. 999 * <br>The list of values describes alternative security schemes that can be used (that is, there is a logical OR 1000 * between the security requirements). 1001 * 1002 * <p> 1003 * This definition overrides any declared top-level security. 1004 * <br>To remove a top-level <code>security</code> declaration, an empty array can be used. 1005 * 1006 * @return The property value, or <jk>null</jk> if it is not set. 1007 */ 1008 public List<Map<String,List<String>>> getSecurity() { 1009 return security; 1010 } 1011 1012 /** 1013 * Bean property setter: <property>security</property>. 1014 * 1015 * <p> 1016 * A declaration of which security schemes are applied for this operation. 1017 * <br>The list of values describes alternative security schemes that can be used (that is, there is a logical OR 1018 * between the security requirements). 1019 * 1020 * <p> 1021 * This definition overrides any declared top-level security. 1022 * <br>To remove a top-level <code>security</code> declaration, an empty array can be used. 1023 * 1024 * @param value 1025 * The new value for this property. 1026 * <br>Can be <jk>null</jk> to unset the property. 1027 * @return This object (for method chaining). 1028 */ 1029 public Operation setSecurity(Collection<Map<String,List<String>>> value) { 1030 security = newList(value); 1031 return this; 1032 } 1033 1034 /** 1035 * Adds one or more values to the <property>security</property> property. 1036 * 1037 * <p> 1038 * A declaration of which security schemes are applied for this operation. 1039 * <br>The list of values describes alternative security schemes that can be used (that is, there is a logical OR 1040 * between the security requirements). 1041 * 1042 * <p> 1043 * This definition overrides any declared top-level security. 1044 * <br>To remove a top-level <code>security</code> declaration, an empty array can be used. 1045 * 1046 * @param values 1047 * The values to add to this property. 1048 * <br>Ignored if <jk>null</jk>. 1049 * The new value for this property. 1050 * @return This object (for method chaining). 1051 */ 1052 public Operation addSecurity(Collection<Map<String,List<String>>> values) { 1053 security = addToList(security, values); 1054 return this; 1055 } 1056 1057 /** 1058 * Same as {@link #addSecurity(Collection)}. 1059 * 1060 * @param scheme 1061 * The scheme name. 1062 * @param alternatives 1063 * The list of values describes alternative security schemes that can be used (that is, there is a logical OR 1064 * between the security requirements). 1065 * @return This object (for method chaining). 1066 */ 1067 public Operation security(String scheme, String...alternatives) { 1068 Map<String,List<String>> m = new LinkedHashMap<>(); 1069 m.put(scheme, Arrays.asList(alternatives)); 1070 return addSecurity(Collections.singletonList(m)); 1071 } 1072 1073 /** 1074 * Same as {@link #addSecurity(Collection)}. 1075 * 1076 * @param value 1077 * The new value for this property. 1078 * <br>Valid types: 1079 * <ul> 1080 * <li><code>Map<String,List<String>></code> 1081 * <li><code>String</code> - JSON object representation of a <code>Map<String,List<String>></code> 1082 * <h5 class='figure'>Example:</h5> 1083 * <p class='bcode w800'> 1084 * securities(<js>"{key:['val1','val2']}"</js>); 1085 * </p> 1086 * </ul> 1087 * @return This object (for method chaining). 1088 */ 1089 @SuppressWarnings({ "unchecked", "rawtypes" }) 1090 public Operation securities(Object...value) { 1091 security = addToList((List)security, value, Map.class, String.class, List.class, String.class); 1092 return this; 1093 } 1094 1095 /** 1096 * Returns <jk>true</jk> if the summary property is not null or empty. 1097 * 1098 * @return <jk>true</jk> if the summary property is not null or empty. 1099 */ 1100 public boolean hasSummary() { 1101 return isNotEmpty(summary); 1102 } 1103 1104 /** 1105 * Returns <jk>true</jk> if the description property is not null or empty. 1106 * 1107 * @return <jk>true</jk> if the description property is not null or empty. 1108 */ 1109 public boolean hasDescription() { 1110 return isNotEmpty(description); 1111 } 1112 1113 /** 1114 * Returns <jk>true</jk> if this operation has the specified tag associated with it. 1115 * 1116 * @param name The tag name. 1117 * @return <jk>true</jk> if this operation has the specified tag associated with it. 1118 */ 1119 public boolean hasTag(String name) { 1120 return tags != null && tags.contains(name); 1121 } 1122 1123 /** 1124 * Returns <jk>true</jk> if this operation has no tags associated with it. 1125 * 1126 * @return <jk>true</jk> if this operation has no tags associated with it. 1127 */ 1128 public boolean hasNoTags() { 1129 return tags == null || tags.isEmpty(); 1130 } 1131 1132 /** 1133 * Returns <jk>true</jk> if this operation has parameters associated with it. 1134 * 1135 * @return <jk>true</jk> if this operation has parameters associated with it. 1136 */ 1137 public boolean hasParameters() { 1138 return parameters != null && ! parameters.isEmpty(); 1139 } 1140 1141 /** 1142 * Returns <jk>true</jk> if this operation has responses associated with it. 1143 * 1144 * @return <jk>true</jk> if this operation has responses associated with it. 1145 */ 1146 public boolean hasResponses() { 1147 return responses != null && ! responses.isEmpty(); 1148 } 1149 1150 @Override /* SwaggerElement */ 1151 public <T> T get(String property, Class<T> type) { 1152 if (property == null) 1153 return null; 1154 switch (property) { 1155 case "tags": return toType(getTags(), type); 1156 case "summary": return toType(getSummary(), type); 1157 case "description": return toType(getDescription(), type); 1158 case "externalDocs": return toType(getExternalDocs(), type); 1159 case "operationId": return toType(getOperationId(), type); 1160 case "consumes": return toType(getConsumes(), type); 1161 case "produces": return toType(getProduces(), type); 1162 case "parameters": return toType(getParameters(), type); 1163 case "responses": return toType(getResponses(), type); 1164 case "schemes": return toType(getSchemes(), type); 1165 case "deprecated": return toType(getDeprecated(), type); 1166 case "security": return toType(getSecurity(), type); 1167 default: return super.get(property, type); 1168 } 1169 } 1170 1171 @Override /* SwaggerElement */ 1172 public Operation set(String property, Object value) { 1173 if (property == null) 1174 return this; 1175 switch (property) { 1176 case "tags": return setTags(null).tags(value); 1177 case "summary": return summary(value); 1178 case "description": return description(value); 1179 case "externalDocs": return externalDocs(value); 1180 case "operationId": return operationId(value); 1181 case "consumes": return setConsumes(null).consumes(value); 1182 case "produces": return setProduces(null).produces(value); 1183 case "parameters": return setParameters(null).parameters(value); 1184 case "responses": return setResponses(null).responses(value); 1185 case "schemes": return setSchemes(null).schemes(value); 1186 case "deprecated": return deprecated(value); 1187 case "security": return setSecurity(null).securities(value); 1188 default: 1189 super.set(property, value); 1190 return this; 1191 } 1192 } 1193 1194 @Override /* SwaggerElement */ 1195 public Set<String> keySet() { 1196 ASet<String> s = new ASet<String>() 1197 .appendIf(tags != null, "tags") 1198 .appendIf(summary != null, "summary") 1199 .appendIf(description != null, "description") 1200 .appendIf(externalDocs != null, "externalDocs") 1201 .appendIf(operationId != null, "operationId") 1202 .appendIf(consumes != null, "consumes") 1203 .appendIf(produces != null, "produces") 1204 .appendIf(parameters != null, "parameters") 1205 .appendIf(responses != null, "responses") 1206 .appendIf(schemes != null, "schemes") 1207 .appendIf(deprecated != null, "deprecated") 1208 .appendIf(security != null, "security"); 1209 return new MultiSet<>(s, super.keySet()); 1210 } 1211}