001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.bean.swagger; 018 019import static org.apache.juneau.common.utils.Utils.*; 020import static org.apache.juneau.internal.CollectionUtils.*; 021import static org.apache.juneau.internal.CollectionUtils.map; 022import static org.apache.juneau.internal.ConverterUtils.*; 023 024import java.util.*; 025 026import org.apache.juneau.*; 027import org.apache.juneau.common.utils.*; 028import org.apache.juneau.internal.*; 029 030/** 031 * Describes a single API operation on a path. 032 * 033 * <p> 034 * The Operation Object describes a single operation (such as GET, POST, PUT, DELETE) that can be performed on a path 035 * in Swagger 2.0. Operations define what actions can be taken, what parameters they accept, what they consume/produce, 036 * and what responses they return. 037 * 038 * <h5 class='section'>Swagger Specification:</h5> 039 * <p> 040 * The Operation Object is composed of the following fields: 041 * <ul class='spaced-list'> 042 * <li><c>tags</c> (array of string) - A list of tags for API documentation control 043 * <li><c>summary</c> (string) - A short summary of what the operation does 044 * <li><c>description</c> (string) - A verbose explanation of the operation behavior 045 * <li><c>externalDocs</c> ({@link ExternalDocumentation}) - Additional external documentation for this operation 046 * <li><c>operationId</c> (string) - Unique string used to identify the operation 047 * <li><c>consumes</c> (array of string) - A list of MIME types the operation can consume 048 * <li><c>produces</c> (array of string) - A list of MIME types the operation can produce 049 * <li><c>parameters</c> (array of {@link ParameterInfo}) - A list of parameters that are applicable for this operation 050 * <li><c>responses</c> (map of {@link ResponseInfo}, REQUIRED) - The list of possible responses as they are returned from executing this operation 051 * <li><c>schemes</c> (array of string) - The transfer protocol for the operation (overrides the Swagger-level schemes) 052 * <li><c>deprecated</c> (boolean) - Declares this operation to be deprecated 053 * <li><c>security</c> (array of map) - A declaration of which security schemes are applied for this operation 054 * </ul> 055 * 056 * <h5 class='section'>Example:</h5> 057 * <p class='bjava'> 058 * <jc>// Construct using SwaggerBuilder.</jc> 059 * Operation <jv>operation</jv> = <jsm>operation</jsm>() 060 * .tags(<js>"pet"</js>) 061 * .summary(<js>"Updates a pet in the store with form data"</js>) 062 * .description(<js>""</js>) 063 * .operationId(<js>"updatePetWithForm"</js>) 064 * .consumes(<js>"application/x-www-form-urlencoded"</js>) 065 * .produces(<js>"application/json"</js>, <js>"application/xml"</js>) 066 * .parameters( 067 * <jsm>parameter</jsm>() 068 * .name(<js>"petId"</js>) 069 * .in(<js>"path"</js>) 070 * .description(<js>"ID of pet that needs to be updated"</js>) 071 * .required(<jk>true</jk>) 072 * .type(<js>"string"</js>), 073 * <jsm>parameter</jsm>() 074 * .name(<js>"name"</js>) 075 * .in(<js>"formData"</js>) 076 * .description(<js>"Updated name of the pet"</js>) 077 * .required(<jk>false</jk>) 078 * .type(<js>"string"</js>), 079 * <jsm>parameter</jsm>() 080 * .name(<js>"status"</js>) 081 * .in(<js>"formData"</js>) 082 * .description(<js>"Updated status of the pet"</js>) 083 * .required(<jk>false</jk>) 084 * .type(<js>"string"</js>) 085 * ) 086 * .response(200, <jsm>responseInfo</jsm>(<js>"Pet updated."</js>)) 087 * .response(405, <jsm>responseInfo</jsm>(<js>"Invalid input."</js>)) 088 * .security(<js>"petstore_auth"</js>, <js>"write:pets"</js>, <js>"read:pets"</js>); 089 * 090 * <jc>// Serialize using JsonSerializer.</jc> 091 * String <jv>json</jv> = Json.<jsm>from</jsm>(<jv>operation</jv>); 092 * 093 * <jc>// Or just use toString() which does the same as above.</jc> 094 * <jv>json</jv> = <jv>operation</jv>.toString(); 095 * </p> 096 * <p class='bjson'> 097 * <jc>// Output</jc> 098 * { 099 * <js>"tags"</js>: [ 100 * <js>"pet"</js> 101 * ], 102 * <js>"summary"</js>: <js>"Updates a pet in the store with form data"</js>, 103 * <js>"description"</js>: <js>""</js>, 104 * <js>"operationId"</js>: <js>"updatePetWithForm"</js>, 105 * <js>"consumes"</js>: [ 106 * <js>"application/x-www-form-urlencoded"</js> 107 * ], 108 * <js>"produces"</js>: [ 109 * <js>"application/json"</js>, 110 * <js>"application/xml"</js> 111 * ], 112 * <js>"parameters"</js>: [ 113 * { 114 * <js>"name"</js>: <js>"petId"</js>, 115 * <js>"in"</js>: <js>"path"</js>, 116 * <js>"description"</js>: <js>"ID of pet that needs to be updated"</js>, 117 * <js>"required"</js>: <jk>true</jk>, 118 * <js>"type"</js>: <js>"string"</js> 119 * }, 120 * { 121 * <js>"name"</js>: <js>"name"</js>, 122 * <js>"in"</js>: <js>"formData"</js>, 123 * <js>"description"</js>: <js>"Updated name of the pet"</js>, 124 * <js>"required"</js>: <jk>false</jk>, 125 * <js>"type"</js>: <js>"string"</js> 126 * }, 127 * { 128 * <js>"name"</js>: <js>"status"</js>, 129 * <js>"in"</js>: <js>"formData"</js>, 130 * <js>"description"</js>: <js>"Updated status of the pet"</js>, 131 * <js>"required"</js>: <jk>false</jk>, 132 * <js>"type"</js>: <js>"string"</js> 133 * } 134 * ], 135 * <js>"responses"</js>: { 136 * <js>"200"</js>: { 137 * <js>"description"</js>: <js>"Pet updated."</js> 138 * }, 139 * <js>"405"</js>: { 140 * <js>"description"</js>: <js>"Invalid input"</js> 141 * } 142 * }, 143 * <js>"security"</js>: [ 144 * { 145 * <js>"petstore_auth"</js>: [ 146 * <js>"write:pets"</js>, 147 * <js>"read:pets"</js> 148 * ] 149 * } 150 * ] 151 * } 152 * </p> 153 * 154 * <h5 class='section'>See Also:</h5><ul> 155 * <li class='link'><a class="doclink" href="https://swagger.io/specification/v2/#operation-object">Swagger 2.0 Specification > Operation Object</a> 156 * <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/2-0/paths-and-operations/">Swagger Paths and Operations</a> 157 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanSwagger2">juneau-bean-swagger-v2</a> 158 * </ul> 159 */ 160public class Operation extends SwaggerElement { 161 162 private String 163 summary, 164 description, 165 operationId; 166 private Boolean deprecated; 167 private ExternalDocumentation externalDocs; 168 private Set<String> 169 tags, 170 schemes; 171 private Set<MediaType> 172 consumes, 173 produces; 174 private List<ParameterInfo> parameters; 175 private List<Map<String,List<String>>> security; 176 private Map<String,ResponseInfo> responses; 177 178 /** 179 * Default constructor. 180 */ 181 public Operation() {} 182 183 /** 184 * Copy constructor. 185 * 186 * @param copyFrom The object to copy. 187 */ 188 public Operation(Operation copyFrom) { 189 super(copyFrom); 190 191 this.consumes = copyOf(copyFrom.consumes); 192 this.deprecated = copyFrom.deprecated; 193 this.description = copyFrom.description; 194 this.externalDocs = copyFrom.externalDocs == null ? null : copyFrom.externalDocs.copy(); 195 this.operationId = copyFrom.operationId; 196 this.produces = copyOf(copyFrom.produces); 197 this.schemes = copyOf(copyFrom.schemes); 198 this.summary = copyFrom.summary; 199 this.tags = copyOf(copyFrom.tags); 200 201 if (copyFrom.parameters == null) { 202 this.parameters = null; 203 } else { 204 this.parameters = list(); 205 copyFrom.parameters.forEach(x -> this.parameters.add(x.copy())); 206 } 207 208 if (copyFrom.responses == null) { 209 this.responses = null; 210 } else { 211 this.responses = map(); 212 copyFrom.responses.forEach((k,v) -> this.responses.put(k, v.copy())); 213 } 214 215 if (copyFrom.security == null) { 216 this.security = null; 217 } else { 218 this.security = list(); 219 copyFrom.security.forEach(x -> { 220 Map<String,List<String>> m2 = map(); 221 x.forEach((k,v) -> m2.put(k, copyOf(v))); 222 this.security.add(m2); 223 }); 224 } 225 } 226 227 /** 228 * Make a deep copy of this object. 229 * 230 * @return A deep copy of this object. 231 */ 232 public Operation copy() { 233 return new Operation(this); 234 } 235 236 //----------------------------------------------------------------------------------------------------------------- 237 // Properties 238 //----------------------------------------------------------------------------------------------------------------- 239 240 /** 241 * Bean property getter: <property>consumes</property>. 242 * 243 * <p> 244 * A list of MIME types the operation can consume. 245 * 246 * @return The property value, or <jk>null</jk> if it is not set. 247 */ 248 public Set<MediaType> getConsumes() { 249 return consumes; 250 } 251 252 /** 253 * Bean property setter: <property>consumes</property>. 254 * 255 * <p> 256 * A list of MIME types the operation can consume. 257 * 258 * @param value 259 * The new value for this property. 260 * <br>Values MUST be as described under <a class="doclink" href="https://swagger.io/specification#mimeTypes">Swagger Mime Types</a>. 261 * <br>Can be <jk>null</jk> to unset the property. 262 * @return This object. 263 */ 264 public Operation setConsumes(Collection<MediaType> value) { 265 consumes = setFrom(value); 266 return this; 267 } 268 269 /** 270 * Bean property setter: <property>consumes</property>. 271 * 272 * <p> 273 * A list of MIME types the operation can consume. 274 * 275 * @param value 276 * The new value for this property. 277 * <br>Values MUST be as described under <a class="doclink" href="https://swagger.io/specification#mimeTypes">Swagger Mime Types</a>. 278 * <br>Can be <jk>null</jk> to unset the property. 279 * @return This object. 280 */ 281 public Operation setConsumes(MediaType...value) { 282 return setConsumes(Arrays.asList(value)); 283 } 284 285 /** 286 * Bean property fluent setter: <property>consumes</property>. 287 * 288 * <p> 289 * A list of MIME types the operation can consume. 290 * 291 * @param value 292 * The new value for this property. 293 * @return This object. 294 */ 295 public Operation addConsumes(MediaType...value) { 296 consumes = setBuilder(consumes).sparse().add(value).build(); 297 return this; 298 } 299 300 /** 301 * Bean property appender: <property>consumes</property>. 302 * 303 * <p> 304 * A list of MIME types the operation can consume. 305 * 306 * @param values 307 * The values to add to this property. 308 * <br>Ignored if <jk>null</jk>. 309 * @return This object. 310 */ 311 public Operation addConsumes(Collection<MediaType> values) { 312 consumes = setBuilder(consumes).sparse().addAll(values).build(); 313 return this; 314 } 315 316 /** 317 * Bean property getter: <property>deprecated</property>. 318 * 319 * <p> 320 * Declares this operation to be deprecated. 321 * 322 * @return The property value, or <jk>null</jk> if it is not set. 323 */ 324 public Boolean getDeprecated() { 325 return deprecated; 326 } 327 328 /** 329 * Bean property getter: <property>deprecated</property>. 330 * 331 * <p> 332 * Declares this operation to be deprecated. 333 * 334 * @return The property value, or <jk>false</jk> if it is not set. 335 */ 336 public boolean isDeprecated() { 337 return deprecated != null && deprecated; 338 } 339 340 /** 341 * Bean property setter: <property>deprecated</property>. 342 * 343 * <p> 344 * Declares this operation to be deprecated. 345 * 346 * @param value The new value for this property. 347 * <br>Can be <jk>null</jk> to unset the property. 348 * @return This object. 349 */ 350 public Operation setDeprecated(Boolean value) { 351 deprecated = value; 352 return this; 353 } 354 355 /** 356 * Bean property getter: <property>description</property>. 357 * 358 * <p> 359 * A verbose explanation of the operation behavior. 360 * 361 * @return The property value, or <jk>null</jk> if it is not set. 362 */ 363 public String getDescription() { 364 return description; 365 } 366 367 /** 368 * Bean property setter: <property>description</property>. 369 * 370 * <p> 371 * A verbose explanation of the operation behavior. 372 * 373 * @param value 374 * The new value for this property. 375 * <br><a class="doclink" href="https://help.github.com/articles/github-flavored-markdown">GFM syntax</a> can be used for rich text representation. 376 * <br>Can be <jk>null</jk> to unset the property. 377 * @return This object. 378 */ 379 public Operation setDescription(String value) { 380 description = value; 381 return this; 382 } 383 384 /** 385 * Bean property getter: <property>externalDocs</property>. 386 * 387 * <p> 388 * Additional external documentation for this operation. 389 * 390 * @return The property value, or <jk>null</jk> if it is not set. 391 */ 392 public ExternalDocumentation getExternalDocs() { 393 return externalDocs; 394 } 395 396 /** 397 * Bean property setter: <property>externalDocs</property>. 398 * 399 * <p> 400 * Additional external documentation for this operation. 401 * 402 * @param value 403 * The values to add to this property. 404 * <br>Can be <jk>null</jk> to unset the property. 405 * @return This object. 406 */ 407 public Operation setExternalDocs(ExternalDocumentation value) { 408 externalDocs = value; 409 return this; 410 } 411 412 /** 413 * Bean property getter: <property>operationId</property>. 414 * 415 * <p> 416 * Unique string used to identify the operation. 417 * 418 * @return The property value, or <jk>null</jk> if it is not set. 419 */ 420 public String getOperationId() { 421 return operationId; 422 } 423 424 /** 425 * Bean property setter: <property>operationId</property>. 426 * 427 * <p> 428 * Unique string used to identify the operation. 429 * 430 * @param value 431 * The new value for this property. 432 * <br>The id MUST be unique among all operations described in the API. 433 * <br>Tools and libraries MAY use the operationId to uniquely identify an operation, therefore, it is recommended to 434 * follow common programming naming conventions. 435 * <br>Can be <jk>null</jk> to unset the property. 436 * @return This object. 437 */ 438 public Operation setOperationId(String value) { 439 operationId = value; 440 return this; 441 } 442 443 /** 444 * Bean property getter: <property>parameters</property>. 445 * 446 * <p> 447 * A list of parameters that are applicable for this operation. 448 * 449 * <h5 class='section'>Notes:</h5><ul> 450 * <li class='note'> 451 * If a parameter is already defined at the <a class="doclink" href="https://swagger.io/specification#pathItemObject">Path Item</a>, 452 * the new definition will override it, but can never remove it. 453 * <li class='note'> 454 * The list MUST NOT include duplicated parameters. 455 * <li class='note'> 456 * A unique parameter is defined by a combination of a <c>name</c> and <c>location</c>. 457 * <li class='note'> 458 * The list can use the <a class="doclink" href="https://swagger.io/specification#referenceObject">Swagger Reference Object</a> 459 * to link to parameters that are defined at the <a class='doclink' href='https://swagger.io/specification/v2#parameterObject'>Swagger Object's parameters</a>. 460 * <li class='note'> 461 * There can be one <js>"body"</js> parameter at most. 462 * </ul> 463 * 464 * @return The property value, or <jk>null</jk> if it is not set. 465 */ 466 public List<ParameterInfo> getParameters() { 467 return parameters; 468 } 469 470 /** 471 * Returns the parameter with the specified type and name. 472 * 473 * @param in The parameter in. Must not be <jk>null</jk>. 474 * @param name The parameter name. Can be <jk>null</jk> for parameter type <c>body</c>. 475 * @return The matching parameter info, or <jk>null</jk> if not found. 476 */ 477 public ParameterInfo getParameter(String in, String name) { 478 assertArgNotNull("in", in); 479 // Note: name can be null for "body" parameters 480 if (parameters != null) 481 for (var pi : parameters) 482 if (eq(pi.getIn(), in) && (eq(pi.getName(), name) || "body".equals(pi.getIn()))) 483 return pi; 484 return null; 485 } 486 487 /** 488 * Bean property setter: <property>parameters</property>. 489 * 490 * <p> 491 * A list of parameters that are applicable for this operation. 492 * 493 * @param value 494 * The new value for this property. 495 * <br>Can be <jk>null</jk> to unset the property. 496 * @return This object. 497 */ 498 public Operation setParameters(Collection<ParameterInfo> value) { 499 parameters = listFrom(value); 500 return this; 501 } 502 503 /** 504 * Bean property setter: <property>parameters</property>. 505 * 506 * <p> 507 * A list of parameters that are applicable for this operation. 508 * 509 * @param value 510 * The new value for this property. 511 * <br>Can be <jk>null</jk> to unset the property. 512 * @return This object. 513 */ 514 public Operation setParameters(ParameterInfo...value) { 515 return setParameters(Arrays.asList(value)); 516 } 517 518 /** 519 * Bean property fluent setter: <property>parameters</property>. 520 * 521 * <p> 522 * A list of parameters that are applicable for this operation. 523 * 524 * @param value 525 * The new value for this property. 526 * @return This object. 527 */ 528 public Operation addParameters(ParameterInfo...value) { 529 parameters = listBuilder(parameters).sparse().add(value).build(); 530 return this; 531 } 532 533 /** 534 * Bean property fluent setter: <property>parameters</property>. 535 * 536 * <p> 537 * The parameters needed to send a valid API call. 538 * 539 * @param values 540 * The values to add to this property. 541 * <br>Ignored if <jk>null</jk>. 542 * @return This object. 543 */ 544 public Operation addParameters(Collection<ParameterInfo> values) { 545 parameters = listBuilder(parameters).sparse().addAll(values).build(); 546 return this; 547 } 548 549 //----------------------------------------------------------------------------------------------------------------- 550 // produces 551 //----------------------------------------------------------------------------------------------------------------- 552 553 /** 554 * Bean property getter: <property>produces</property>. 555 * 556 * <p> 557 * A list of MIME types the operation can produce. 558 * 559 * @return The property value, or <jk>null</jk> if it is not set. 560 */ 561 public Set<MediaType> getProduces() { 562 return produces; 563 } 564 565 /** 566 * Bean property setter: <property>produces</property>. 567 * 568 * <p> 569 * A list of MIME types the operation can produce. 570 * 571 * @param value 572 * The new value for this property. 573 * <br>Value MUST be as described under <a class="doclink" href="https://swagger.io/specification#mimeTypes">Swagger Mime Types</a>. 574 * <br>Can be <jk>null</jk> to unset the property. 575 * @return This object. 576 */ 577 public Operation setProduces(Collection<MediaType> value) { 578 produces = setFrom(value); 579 return this; 580 } 581 582 /** 583 * Bean property setter: <property>produces</property>. 584 * 585 * <p> 586 * A list of MIME types the operation can produce. 587 * 588 * @param value 589 * The new value for this property. 590 * <br>Value MUST be as described under <a class="doclink" href="https://swagger.io/specification#mimeTypes">Swagger Mime Types</a>. 591 * <br>Can be <jk>null</jk> to unset the property. 592 * @return This object. 593 */ 594 public Operation setProduces(MediaType...value) { 595 return setProduces(Arrays.asList(value)); 596 } 597 598 /** 599 * Bean property fluent setter: <property>produces</property>. 600 * 601 * <p> 602 * A list of MIME types the operation can produce. 603 * 604 * @param value 605 * The new value for this property. 606 * @return This object. 607 */ 608 public Operation addProduces(MediaType...value) { 609 produces = setBuilder(produces).sparse().add(value).build(); 610 return this; 611 } 612 613 /** 614 * Bean property setter: <property>produces</property>. 615 * 616 * <p> 617 * A list of MIME types the operation can produce. 618 * 619 * @param values 620 * The values to add to this property. 621 * <br>Ignored if <jk>null</jk>. 622 * @return This object. 623 */ 624 public Operation addProduces(Collection<MediaType> values) { 625 produces = setBuilder(produces).sparse().addAll(values).build(); 626 return this; 627 } 628 629 /** 630 * Bean property getter: <property>responses</property>. 631 * 632 * <p> 633 * The list of possible responses as they are returned from executing this operation. 634 * 635 * @return The property value, or <jk>null</jk> if it is not set. 636 */ 637 public Map<String,ResponseInfo> getResponses() { 638 return responses; 639 } 640 641 /** 642 * Returns the response info with the given status code. 643 * 644 * @param status The HTTP status code. Must not be <jk>null</jk>. 645 * @return The response info, or <jk>null</jk> if not found. 646 */ 647 public ResponseInfo getResponse(String status) { 648 assertArgNotNull("status", status); 649 return responses == null ? null : responses.get(status); 650 } 651 652 /** 653 * Returns the response info with the given status code. 654 * 655 * @param status The HTTP status code. 656 * @return The response info, or <jk>null</jk> if not found. 657 */ 658 public ResponseInfo getResponse(int status) { 659 return getResponse(String.valueOf(status)); 660 } 661 662 /** 663 * Bean property setter: <property>responses</property>. 664 * 665 * <p> 666 * The list of possible responses as they are returned from executing this operation. 667 * 668 * @param value 669 * The new value for this property. 670 * <br>Property value is required. 671 * <br>Can be <jk>null</jk> to unset the property. 672 * @return This object. 673 */ 674 public Operation setResponses(Map<String,ResponseInfo> value) { 675 responses = copyOf(value); 676 return this; 677 } 678 679 /** 680 * Adds a single value to the <property>responses</property> property. 681 * 682 * @param statusCode The HTTP status code. Must not be <jk>null</jk>. 683 * @param response The response description. Must not be <jk>null</jk>. 684 * @return This object. 685 */ 686 public Operation addResponse(String statusCode, ResponseInfo response) { 687 assertArgNotNull("statusCode", statusCode); 688 assertArgNotNull("response", response); 689 responses = mapBuilder(responses).add(statusCode, response).build(); 690 return this; 691 } 692 693 /** 694 * Bean property getter: <property>schemes</property>. 695 * 696 * <p> 697 * The transfer protocol for the operation. 698 * 699 * @return The property value, or <jk>null</jk> if it is not set. 700 */ 701 public Set<String> getSchemes() { 702 return schemes; 703 } 704 705 /** 706 * Bean property setter: <property>schemes</property>. 707 * 708 * <p> 709 * The transfer protocol for the operation. 710 * 711 * @param value 712 * The new value for this property. 713 * <br>Valid values: 714 * <ul> 715 * <li><js>"http"</js> 716 * <li><js>"https"</js> 717 * <li><js>"ws"</js> 718 * <li><js>"wss"</js> 719 * </ul> 720 * <br>Can be <jk>null</jk> to unset the property. 721 * @return This object. 722 */ 723 public Operation setSchemes(Collection<String> value) { 724 schemes = setFrom(value); 725 return this; 726 } 727 728 /** 729 * Bean property setter: <property>schemes</property>. 730 * 731 * <p> 732 * The transfer protocol for the operation. 733 * 734 * @param value 735 * The new value for this property. 736 * <br>Can be <jk>null</jk> to unset the property. 737 * @return This object. 738 */ 739 public Operation setSchemes(String...value) { 740 setSchemes(setBuilder(String.class).sparse().add(value).build()); 741 return this; 742 } 743 744 /** 745 * Bean property fluent setter: <property>schemes</property>. 746 * 747 * <p> 748 * The transfer protocol for the operation. 749 * 750 * @param value 751 * The new value for this property. 752 * <br>String values can also be JSON arrays. 753 * @return This object. 754 */ 755 public Operation addSchemes(String...value) { 756 schemes = setBuilder(schemes).sparse().add(value).build(); 757 return this; 758 } 759 760 /** 761 * Bean property setter: <property>schemes</property>. 762 * 763 * <p> 764 * The transfer protocol for the operation. 765 * 766 * @param values 767 * The values to add to this property. 768 * <br>Ignored if <jk>null</jk>. 769 * @return This object. 770 */ 771 public Operation addSchemes(Collection<String> values) { 772 schemes = setBuilder(schemes).sparse().addAll(values).build(); 773 return this; 774 } 775 776 /** 777 * Bean property getter: <property>security</property>. 778 * 779 * <p> 780 * A declaration of which security schemes are applied for this operation. 781 * 782 * @return The property value, or <jk>null</jk> if it is not set. 783 */ 784 public List<Map<String,List<String>>> getSecurity() { 785 return security; 786 } 787 788 /** 789 * Bean property setter: <property>security</property>. 790 * 791 * <p> 792 * A declaration of which security schemes are applied for this operation. 793 * 794 * @param value 795 * The new value for this property. 796 * <br>Can be <jk>null</jk> to unset the property. 797 * @return This object. 798 */ 799 public Operation setSecurity(Collection<Map<String,List<String>>> value) { 800 security = listFrom(value); 801 return this; 802 } 803 804 /** 805 * Bean property setter: <property>security</property>. 806 * 807 * <p> 808 * A declaration of which security schemes are applied for this operation. 809 * 810 * @param value 811 * The new value for this property. 812 * <br>Can be <jk>null</jk> to unset the property. 813 * @return This object. 814 */ 815 @SafeVarargs 816 public final Operation setSecurity(Map<String,List<String>>...value) { 817 security = alist(value); 818 return this; 819 } 820 821 /** 822 * Same as {@link #addSecurity(String, String...)}. 823 * 824 * @param scheme 825 * The scheme name. 826 * <br>Must not be <jk>null</jk>. 827 * @param alternatives 828 * The list of values describes alternative security schemes that can be used (that is, there is a logical OR 829 * between the security requirements). 830 * @return This object. 831 */ 832 public Operation addSecurity(String scheme, String...alternatives) { 833 assertArgNotNull("scheme", scheme); 834 Map<String,List<String>> m = map(); 835 m.put(scheme, alist(alternatives)); 836 security = listBuilder(security).add(m).build(); 837 return this; 838 } 839 840 /** 841 * Bean property adder: <property>security</property>. 842 * 843 * <p> 844 * A declaration of which security schemes are applied for this operation. 845 * 846 * @param value 847 * The values to add to this property. 848 * <br>Must not be <jk>null</jk>. 849 * @return This object. 850 */ 851 @SuppressWarnings("unchecked") 852 public Operation addSecurity(Collection<Map<String,List<String>>> value) { 853 assertArgNotNull("value", value); 854 security = listBuilder(security).addAll(value).build(); 855 return this; 856 } 857 858 /** 859 * Bean property getter: <property>summary</property>. 860 * 861 * <p> 862 * A short summary of what the operation does. 863 * 864 * @return The property value, or <jk>null</jk> if it is not set. 865 */ 866 public String getSummary() { 867 return summary; 868 } 869 870 /** 871 * Bean property setter: <property>summary</property>. 872 * 873 * <p> 874 * A short summary of what the operation does. 875 * 876 * @param value 877 * The new value for this property. 878 * <br>Can be <jk>null</jk> to unset the property. 879 * @return This object. 880 */ 881 public Operation setSummary(String value) { 882 summary = value; 883 return this; 884 } 885 886 /** 887 * Bean property getter: <property>tags</property>. 888 * 889 * <p> 890 * A list of tags for API documentation control. 891 * <br>Tags can be used for logical grouping of operations by resources or any other qualifier. 892 * 893 * @return The property value, or <jk>null</jk> if it is not set. 894 */ 895 public Set<String> getTags() { 896 return tags; 897 } 898 899 /** 900 * Bean property setter: <property>tags</property>. 901 * 902 * <p> 903 * A list of tags for API documentation control. 904 * <br>Tags can be used for logical grouping of operations by resources or any other qualifier. 905 * 906 * @param value 907 * The new value for this property. 908 * <br>Can be <jk>null</jk> to unset the property. 909 * @return This object. 910 */ 911 public Operation setTags(Collection<String> value) { 912 tags = setFrom(value); 913 return this; 914 } 915 916 /** 917 * Bean property fluent setter: <property>tags</property>. 918 * 919 * <p> 920 * A list of tags for API documentation control. 921 * <br>Tags can be used for logical grouping of operations by resources or any other qualifier. 922 * 923 * @param value 924 * The new value for this property. 925 * @return This object. 926 */ 927 public Operation setTags(String...value) { 928 setTags(setBuilder(String.class).sparse().add(value).build()); 929 return this; 930 } 931 932 /** 933 * Bean property fluent adder: <property>tags</property>. 934 * 935 * <p> 936 * A list of tags for API documentation control. 937 * <br>Tags can be used for logical grouping of operations by resources or any other qualifier. 938 * 939 * @param value 940 * The values to add to this property. 941 * @return This object. 942 */ 943 public Operation addTags(String...value) { 944 tags = setBuilder(tags).sparse().add(value).build(); 945 return this; 946 } 947 948 /** 949 * Bean property appender: <property>tags</property>. 950 * 951 * <p> 952 * A list of tags for API documentation control. 953 * 954 * @param values 955 * The values to add to this property. 956 * <br>Ignored if <jk>null</jk>. 957 * @return This object. 958 */ 959 public Operation addTags(Collection<String> values) { 960 tags = setBuilder(tags).sparse().addAll(values).build(); 961 return this; 962 } 963 964 @Override /* Overridden from SwaggerElement */ 965 public <T> T get(String property, Class<T> type) { 966 assertArgNotNull("property", property); 967 return switch (property) { 968 case "consumes" -> toType(getConsumes(), type); 969 case "deprecated" -> toType(getDeprecated(), type); 970 case "description" -> toType(getDescription(), type); 971 case "externalDocs" -> toType(getExternalDocs(), type); 972 case "operationId" -> toType(getOperationId(), type); 973 case "parameters" -> toType(getParameters(), type); 974 case "produces" -> toType(getProduces(), type); 975 case "responses" -> toType(getResponses(), type); 976 case "schemes" -> toType(getSchemes(), type); 977 case "security" -> toType(getSecurity(), type); 978 case "summary" -> toType(getSummary(), type); 979 case "tags" -> toType(getTags(), type); 980 default -> super.get(property, type); 981 }; 982 } 983 984 @SuppressWarnings("rawtypes") 985 @Override /* Overridden from SwaggerElement */ 986 public Operation set(String property, Object value) { 987 assertArgNotNull("property", property); 988 return switch (property) { 989 case "consumes" -> setConsumes(listBuilder(MediaType.class).sparse().addAny(value).build()); 990 case "deprecated" -> setDeprecated(toBoolean(value)); 991 case "description" -> setDescription(Utils.s(value)); 992 case "externalDocs" -> setExternalDocs(toType(value, ExternalDocumentation.class)); 993 case "operationId" -> setOperationId(Utils.s(value)); 994 case "parameters" -> setParameters(listBuilder(ParameterInfo.class).sparse().addAny(value).build()); 995 case "produces" -> setProduces(listBuilder(MediaType.class).sparse().addAny(value).build()); 996 case "responses" -> setResponses(mapBuilder(String.class,ResponseInfo.class).sparse().addAny(value).build()); 997 case "schemes" -> setSchemes(listBuilder(String.class).sparse().addAny(value).build()); 998 case "security" -> setSecurity((List)listBuilder(Map.class,String.class,List.class,String.class).sparse().addAny(value).build()); 999 case "summary" -> setSummary(Utils.s(value)); 1000 case "tags" -> setTags(listBuilder(String.class).sparse().addAny(value).build()); 1001 default -> { 1002 super.set(property, value); 1003 yield this; 1004 } 1005 }; 1006 } 1007 1008 @Override /* Overridden from SwaggerElement */ 1009 public Set<String> keySet() { 1010 var s = setBuilder(String.class) 1011 .addIf(consumes != null, "consumes") 1012 .addIf(deprecated != null, "deprecated") 1013 .addIf(description != null, "description") 1014 .addIf(externalDocs != null, "externalDocs") 1015 .addIf(operationId != null, "operationId") 1016 .addIf(parameters != null, "parameters") 1017 .addIf(produces != null, "produces") 1018 .addIf(responses != null, "responses") 1019 .addIf(schemes != null, "schemes") 1020 .addIf(security != null, "security") 1021 .addIf(summary != null, "summary") 1022 .addIf(tags != null, "tags") 1023 .build(); 1024 return new MultiSet<>(s, super.keySet()); 1025 } 1026 1027 /** 1028 * Sets strict mode on this bean. 1029 * 1030 * @return This object. 1031 */ 1032 @Override 1033 public Operation strict() { 1034 super.strict(); 1035 return this; 1036 } 1037 1038 /** 1039 * Sets strict mode on this bean. 1040 * 1041 * @param value 1042 * The new value for this property. 1043 * <br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>. 1044 * <br>Can be <jk>null</jk> (interpreted as <jk>false</jk>). 1045 * @return This object. 1046 */ 1047 @Override 1048 public Operation strict(Object value) { 1049 super.strict(value); 1050 return this; 1051 } 1052 1053}