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