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.CollectionUtils.*;
020import static org.apache.juneau.bean.swagger.SwaggerCopyUtils.*;
021import static org.apache.juneau.commons.utils.Shorts.*;
022import static org.apache.juneau.marshall.internal.ConverterUtils.*;
023
024import java.util.*;
025
026import org.apache.juneau.commons.collections.*;
027import org.apache.juneau.marshall.marshaller.*;
028
029/**
030 * Describes a single operation parameter.
031 *
032 * <p>
033 * The Parameter Object describes a single parameter used in a Swagger 2.0 API operation. A unique parameter is
034 * defined by a combination of a name and location (in). Parameters can be passed in various locations including
035 * the path, query string, headers, body, or form data.
036 *
037 * <h5 class='section'>Swagger Specification:</h5>
038 * <p>
039 * The Parameter Object supports the following fields:
040 * <ul class='spaced-list'>
041 *    <li><c>name</c> (string, REQUIRED) - The name of the parameter
042 *    <li><c>in</c> (string, REQUIRED) - The location of the parameter. Possible values: <js>"path"</js>, <js>"query"</js>, <js>"header"</js>, <js>"body"</js>, or <js>"formData"</js>
043 *    <li><c>description</c> (string) - A brief description of the parameter
044 *    <li><c>required</c> (boolean) - Determines whether this parameter is mandatory (must be <jk>true</jk> if <c>in</c> is <js>"path"</js>)
045 *    <li><c>schema</c> ({@link SchemaInfo}) - The schema defining the type used for the body parameter (only if <c>in</c> is <js>"body"</js>)
046 *    <li><c>type</c> (string) - The type of the parameter (for non-body parameters). Values: <js>"string"</js>, <js>"number"</js>, <js>"integer"</js>, <js>"boolean"</js>, <js>"array"</js>, <js>"file"</js>
047 *    <li><c>format</c> (string) - The format modifier (e.g., <js>"int32"</js>, <js>"int64"</js>, <js>"float"</js>, <js>"double"</js>, <js>"date"</js>, <js>"date-time"</js>)
048 *    <li><c>allowEmptyValue</c> (boolean) - Sets the ability to pass empty-valued parameters (valid only for <js>"query"</js> or <js>"formData"</js> parameters)
049 *    <li><c>items</c> ({@link Items}) - Required if type is <js>"array"</js>. Describes the type of items in the array
050 *    <li><c>collectionFormat</c> (string) - How multiple values are formatted. Values: <js>"csv"</js>, <js>"ssv"</js>, <js>"tsv"</js>, <js>"pipes"</js>, <js>"multi"</js>
051 *    <li><c>default</c> (any) - The default value
052 *    <li><c>maximum</c> (number), <c>exclusiveMaximum</c> (boolean), <c>minimum</c> (number), <c>exclusiveMinimum</c> (boolean) - Numeric constraints
053 *    <li><c>maxLength</c> (integer), <c>minLength</c> (integer), <c>pattern</c> (string) - String constraints
054 *    <li><c>maxItems</c> (integer), <c>minItems</c> (integer), <c>uniqueItems</c> (boolean) - Array constraints
055 *    <li><c>enum</c> (array) - Possible values for this parameter
056 *    <li><c>multipleOf</c> (number) - Must be a multiple of this value
057 * </ul>
058 *
059 * <p>
060 * There are five possible parameter types (determined by the <c>in</c> field):
061 * <ul class='spaced-list'>
062 *    <li><js>"path"</js> - Used together with Path Templating, where the parameter value is actually part of the
063 *       operation's URL.
064 *       This does not include the host or base path of the API.
065 *       For example, in <c>/items/{itemId}</c>, the path parameter is <c>itemId</c>.
066 *    <li><js>"query"</js> - Parameters that are appended to the URL.
067 *       For example, in <c>/items?id=###</c>, the query parameter is <c>id</c>.
068 *    <li><js>"header"</js> - Custom headers that are expected as part of the request.
069 *    <li><js>"body"</js> - The payload that's appended to the HTTP request.
070 *       Since there can only be one payload, there can only be one body parameter.
071 *       The name of the body parameter has no effect on the parameter itself and is used for documentation purposes
072 *       only.
073 *       Since Form parameters are also in the payload, body and form parameters cannot exist together for the same
074 *       operation.
075 *    <li><js>"formData"</js> - Used to describe the payload of an HTTP request when either
076 *       <c>application/x-www-form-urlencoded</c>, <c>multipart/form-data</c> or both are used as the
077 *       content type of the request (in Swagger's definition, the consumes property of an operation).
078 *       This is the only parameter type that can be used to send files, thus supporting the file type.
079 *       Since form parameters are sent in the payload, they cannot be declared together with a body parameter for the
080 *       same operation.
081 *       Form parameters have a different format based on the content-type used (for further details, consult
082 *       <c>http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4</c>):
083 *       <ul>
084 *          <li><js>"application/x-www-form-urlencoded"</js> - Similar to the format of Query parameters but as a
085 *             payload.
086 *             For example, <c>foo=1&amp;bar=swagger</c> - both <c>foo</c> and <c>bar</c> are form
087 *             parameters.
088 *             This is normally used for simple parameters that are being transferred.
089 *          <li><js>"multipart/form-data"</js> - each parameter takes a section in the payload with an internal header.
090 *             For example, for the header <c>Content-Disposition: form-data; name="submit-name"</c> the name of
091 *             the parameter is <c>submit-name</c>.
092 *             This type of form parameters is more commonly used for file transfers.
093 *       </ul>
094 *    </li>
095 * </ul>
096 *
097 * <h5 class='section'>Example:</h5>
098 * <p class='bjava'>
099 *    <jc>// Construct using SwaggerBuilder.</jc>
100 *    ParameterInfo <jv>info</jv> = <jsm>parameterInfo</jsm>(<js>"query"</js>, <js>"foo"</js>);
101 *
102 *    <jc>// Serialize using JsonSerializer.</jc>
103 *    String <jv>json</jv> = Json.<jsm>from</jsm>(<jv>info</jv>);
104 *
105 *    <jc>// Or just use toString() which does the same as above.</jc>
106 *    <jv>json</jv> = <jv>info</jv>.toString();
107 * </p>
108 * <p class='bjson'>
109 *    <jc>// Output</jc>
110 *    {
111 *       <js>"in"</js>: <js>"query"</js>,
112 *       <js>"name"</js>: <js>"foo"</js>
113 *    }
114 * </p>
115 *
116 * <h5 class='section'>See Also:</h5><ul>
117 *    <li class='link'><a class="doclink" href="https://swagger.io/specification/v2/#parameter-object">Swagger 2.0 Specification &gt; Parameter Object</a>
118 *    <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/2-0/describing-parameters/">Swagger Describing Parameters</a>
119 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanSwagger2">juneau-bean-swagger-v2</a>
120 * </ul>
121 */
122@SuppressWarnings({
123   "java:S116", // Field names use trailing underscore (default_, enum_) to avoid Java keyword conflicts
124   "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants
125})
126public class ParameterInfo extends SwaggerElement {
127
128   private static final String[] VALID_IN = { "query", "header", "path", "formData", "body" };
129   private static final String[] VALID_TYPES = { "string", "number", "integer", "boolean", "array", "file" };
130   private static final String[] VALID_COLLECTION_FORMATS = { "csv", "ssv", "tsv", "pipes", "multi" };
131
132   private String name;
133   private String in;
134   private String description;
135   private String type;
136   private String format;
137   private String pattern;
138   private String collectionFormat;
139   private Number maximum;
140   private Number minimum;
141   private Number multipleOf;
142   private Integer maxLength;
143   private Integer minLength;
144   private Integer maxItems;
145   private Integer minItems;
146   private Boolean required;
147   private Boolean allowEmptyValue;
148   private Boolean exclusiveMaximum;
149   private Boolean exclusiveMinimum;
150   private Boolean uniqueItems;
151   private SchemaInfo schema;
152   private Items items;
153   private Object default_;
154   private Set<Object> enum_ = st();
155   private Object example;
156   private Map<String,String> examples;
157
158   /**
159    * Default constructor.
160    */
161   public ParameterInfo() {}
162
163   /**
164    * Copy constructor.
165    *
166    * @param copyFrom The object to copy.
167    */
168   public ParameterInfo(ParameterInfo copyFrom) {
169      super(copyFrom);
170
171      this.allowEmptyValue = copyFrom.allowEmptyValue;
172      this.collectionFormat = copyFrom.collectionFormat;
173      this.default_ = copyFrom.default_;
174      this.description = copyFrom.description;
175      this.enum_.addAll(copyOf(copyFrom.enum_));
176      this.example = copyFrom.example;
177      this.exclusiveMaximum = copyFrom.exclusiveMaximum;
178      this.exclusiveMinimum = copyFrom.exclusiveMinimum;
179      this.format = copyFrom.format;
180      this.in = copyFrom.in;
181      this.items = copyOf(copyFrom.items);
182      this.maximum = copyFrom.maximum;
183      this.maxItems = copyFrom.maxItems;
184      this.maxLength = copyFrom.maxLength;
185      this.minimum = copyFrom.minimum;
186      this.minItems = copyFrom.minItems;
187      this.minLength = copyFrom.minLength;
188      this.multipleOf = copyFrom.multipleOf;
189      this.name = copyFrom.name;
190      this.pattern = copyFrom.pattern;
191      this.required = copyFrom.required;
192      this.schema = copyOf(copyFrom.schema);
193      this.type = copyFrom.type;
194      this.uniqueItems = copyFrom.uniqueItems;
195
196      this.examples = copyOf(copyFrom.examples);
197   }
198
199   /**
200    * Bean property appender:  <property>enum</property>.
201    *
202    * @param value
203    *    The values to add to this property.
204    *    <br>Ignored if <jk>null</jk>.
205    * @return This object.
206    */
207   public ParameterInfo addEnum(Object...value) {
208      addAllNn(enum_, value);
209      return this;
210   }
211
212   /**
213    * Make a deep copy of this object.
214    *
215    * @return A deep copy of this object.
216    */
217   public ParameterInfo copy() {
218      return new ParameterInfo(this);
219   }
220
221   /**
222    * Copies any non-null fields from the specified object to this object.
223    *
224    * @param p
225    *    The object to copy fields from.
226    *    <br>Can be <jk>null</jk> (no-op).
227    * @return This object.
228    */
229   @SuppressWarnings({
230      "java:S3776" // Cognitive complexity acceptable for this logic
231   })
232   public ParameterInfo copyFrom(ParameterInfo p) {
233      if (nn(p)) {
234         if (nn(p.name))
235            name = p.name;
236         if (nn(p.in))
237            in = p.in;
238         if (nn(p.description))
239            description = p.description;
240         if (nn(p.type))
241            type = p.type;
242         if (nn(p.format))
243            format = p.format;
244         if (nn(p.pattern))
245            pattern = p.pattern;
246         if (nn(p.collectionFormat))
247            collectionFormat = p.collectionFormat;
248         if (nn(p.maximum))
249            maximum = p.maximum;
250         if (nn(p.minimum))
251            minimum = p.minimum;
252         if (nn(p.multipleOf))
253            multipleOf = p.multipleOf;
254         if (nn(p.maxLength))
255            maxLength = p.maxLength;
256         if (nn(p.minLength))
257            minLength = p.minLength;
258         if (nn(p.maxItems))
259            maxItems = p.maxItems;
260         if (nn(p.minItems))
261            minItems = p.minItems;
262         if (nn(p.required))
263            required = p.required;
264         if (nn(p.allowEmptyValue))
265            allowEmptyValue = p.allowEmptyValue;
266         if (nn(p.exclusiveMaximum))
267            exclusiveMaximum = p.exclusiveMaximum;
268         if (nn(p.exclusiveMinimum))
269            exclusiveMinimum = p.exclusiveMinimum;
270         if (nn(p.uniqueItems))
271            uniqueItems = p.uniqueItems;
272         if (nn(p.schema))
273            schema = p.schema;
274         if (nn(p.items))
275            items = p.items;
276         if (nn(p.default_))
277            default_ = p.default_;
278         enum_ = p.enum_;
279         if (nn(p.example))
280            example = p.example;
281         if (nn(p.examples))
282            examples = p.examples;
283      }
284      return this;
285   }
286
287   @Override /* Overridden from SwaggerElement */
288   public <T> T get(String property, Class<T> type) {
289      reqnn("property", property);
290      return switch (property) {
291         case "allowEmptyValue" -> toType(getAllowEmptyValue(), type);
292         case "collectionFormat" -> toType(getCollectionFormat(), type);
293         case "default" -> toType(getDefault(), type);
294         case "description" -> toType(getDescription(), type);
295         case "enum" -> toType(getEnum(), type);
296         case "example" -> toType(getExample(), type);
297         case "examples" -> toType(getExamples(), type);
298         case "exclusiveMaximum" -> toType(getExclusiveMaximum(), type);
299         case "exclusiveMinimum" -> toType(getExclusiveMinimum(), type);
300         case "format" -> toType(getFormat(), type);
301         case "in" -> toType(getIn(), type);
302         case "items" -> toType(getItems(), type);
303         case "maximum" -> toType(getMaximum(), type);
304         case "maxItems" -> toType(getMaxItems(), type);
305         case "maxLength" -> toType(getMaxLength(), type);
306         case "minimum" -> toType(getMinimum(), type);
307         case "minItems" -> toType(getMinItems(), type);
308         case "minLength" -> toType(getMinLength(), type);
309         case "multipleOf" -> toType(getMultipleOf(), type);
310         case "name" -> toType(getName(), type);
311         case "pattern" -> toType(getPattern(), type);
312         case "required" -> toType(getRequired(), type);
313         case "schema" -> toType(getSchema(), type);
314         case "type" -> toType(getType(), type);
315         case "uniqueItems" -> toType(getUniqueItems(), type);
316         default -> super.get(property, type);
317      };
318   }
319
320   /**
321    * Bean property getter:  <property>allowEmptyValue</property>.
322    *
323    * <p>
324    * Sets the ability to pass empty-valued parameters.
325    *
326    * <p>
327    * This is valid only for either <c>query</c> or <c>formData</c> parameters and allows you to send a
328    * parameter with a name only or an empty value.
329    *
330    * @return The property value, or <jk>null</jk> if it is not set.
331    */
332   public Boolean getAllowEmptyValue() { return allowEmptyValue; }
333
334   /**
335    * Bean property getter:  <property>collectionFormat</property>.
336    *
337    * <p>
338    * Determines the format of the array if type array is used.
339    *
340    * @return The property value, or <jk>null</jk> if it is not set.
341    */
342   public String getCollectionFormat() { return collectionFormat; }
343
344   /**
345    * Bean property getter:  <property>default</property>.
346    *
347    * <p>
348    * Declares the value of the parameter that the server will use if none is provided, for example a <js>"count"</js>
349    * to control the number of results per page might default to 100 if not supplied by the client in the request.
350    *
351    * (Note: <js>"default"</js> has no meaning for required parameters.)
352    * Unlike JSON Schema this value MUST conform to the defined <c>type</c> for this parameter.
353    *
354    * @return The property value, or <jk>null</jk> if it is not set.
355    */
356   public Object getDefault() { return default_; }
357
358   /**
359    * Bean property getter:  <property>description</property>.
360    *
361    * <p>
362    * A brief description of the parameter.
363    *
364    * @return The property value, or <jk>null</jk> if it is not set.
365    */
366   public String getDescription() { return description; }
367
368   /**
369    * Bean property getter:  <property>enum</property>.
370    *
371    * @return The property value, or <jk>null</jk> if it is not set.
372    */
373   public Set<Object> getEnum() { return u(nie(enum_)); }
374
375   /**
376    * Bean property getter:  <property>example</property>.
377    *
378    * <p>
379    * An example of the parameter. This is useful for documentation purposes.
380    *
381    * @return The property value, or <jk>null</jk> if it is not set.
382    */
383   public Object getExample() { return example; }
384
385   /**
386    * Bean property getter:  <property>examples</property>.
387    *
388    * <p>
389    * Examples of the parameter. This is useful for documentation purposes.
390    *
391    * @return The property value, or <jk>null</jk> if it is not set.
392    */
393   public Map<String,String> getExamples() { return u(examples); }
394
395   /**
396    * Bean property getter:  <property>exclusiveMaximum</property>.
397    *
398    * @return The property value, or <jk>null</jk> if it is not set.
399    */
400   public Boolean getExclusiveMaximum() { return exclusiveMaximum; }
401
402   /**
403    * Bean property getter:  <property>exclusiveMinimum</property>.
404    *
405    * @return The property value, or <jk>null</jk> if it is not set.
406    */
407   public Boolean getExclusiveMinimum() { return exclusiveMinimum; }
408
409   /**
410    * Bean property getter:  <property>format</property>.
411    *
412    * <p>
413    * The extending format for the previously mentioned type.
414    *
415    * @return The property value, or <jk>null</jk> if it is not set.
416    */
417   public String getFormat() { return format; }
418
419   /**
420    * Bean property getter:  <property>in</property>.
421    *
422    * <p>
423    * The location of the parameter.
424    *
425    * @return The property value, or <jk>null</jk> if it is not set.
426    */
427   public String getIn() { return in; }
428
429   /**
430    * Bean property getter:  <property>items</property>.
431    *
432    * <p>
433    * Describes the type of items in the array.
434    *
435    * @return The property value, or <jk>null</jk> if it is not set.
436    */
437   public Items getItems() { return items; }
438
439   /**
440    * Bean property getter:  <property>maximum</property>.
441    *
442    * @return The property value, or <jk>null</jk> if it is not set.
443    */
444   public Number getMaximum() { return maximum; }
445
446   /**
447    * Bean property getter:  <property>maxItems</property>.
448    *
449    * @return The property value, or <jk>null</jk> if it is not set.
450    */
451   public Integer getMaxItems() { return maxItems; }
452
453   /**
454    * Bean property getter:  <property>maxLength</property>.
455    *
456    * @return The property value, or <jk>null</jk> if it is not set.
457    */
458   public Integer getMaxLength() { return maxLength; }
459
460   /**
461    * Bean property getter:  <property>minimum</property>.
462    *
463    * @return The property value, or <jk>null</jk> if it is not set.
464    */
465   public Number getMinimum() { return minimum; }
466
467   /**
468    * Bean property getter:  <property>minItems</property>.
469    *
470    * @return The property value, or <jk>null</jk> if it is not set.
471    */
472   public Integer getMinItems() { return minItems; }
473
474   /**
475    * Bean property getter:  <property>minLength</property>.
476    *
477    * @return The property value, or <jk>null</jk> if it is not set.
478    */
479   public Integer getMinLength() { return minLength; }
480
481   /**
482    * Bean property getter:  <property>multipleOf</property>.
483    *
484    * @return The property value, or <jk>null</jk> if it is not set.
485    */
486   public Number getMultipleOf() { return multipleOf; }
487
488   /**
489    * Bean property getter:  <property>name</property>.
490    *
491    * <p>
492    * The name of the parameter.
493    *
494    * <h5 class='section'>Notes:</h5><ul>
495    *    <li class='note'>
496    *       Parameter names are case sensitive.
497    *    <li class='note'>
498    *       If <c>in</c> is <js>"path"</js>, the <c>name</c> field MUST correspond to the associated path segment
499    *       from the <c>path</c> field in the <a class="doclink" href="https://swagger.io/specification/v2#pathsObject">Paths Object</a>.
500    *    <li class='note'>
501    *       For all other cases, the name corresponds to the parameter name used based on the <c>in</c> property.
502    * </ul>
503    *
504    * @return The property value, or <jk>null</jk> if it is not set.
505    */
506   public String getName() { return name; }
507
508   /**
509    * Bean property getter:  <property>pattern</property>.
510    *
511    * @return The property value, or <jk>null</jk> if it is not set.
512    */
513   public String getPattern() { return pattern; }
514
515   /**
516    * Bean property getter:  <property>required</property>.
517    *
518    * <p>
519    * Determines whether this parameter is mandatory.
520    *
521    * @return The property value, or <jk>null</jk> if it is not set.
522    */
523   public Boolean getRequired() { return required; }
524
525   /**
526    * Bean property getter:  <property>schema</property>.
527    *
528    * <p>
529    * The schema defining the type used for the body parameter.
530    *
531    * @return The property value, or <jk>null</jk> if it is not set.
532    */
533   public SchemaInfo getSchema() { return schema; }
534
535   /**
536    * Bean property getter:  <property>type</property>.
537    *
538    * <p>
539    * The type of the parameter.
540    *
541    * @return The property value, or <jk>null</jk> if it is not set.
542    */
543   public String getType() { return type; }
544
545   /**
546    * Bean property getter:  <property>uniqueItems</property>.
547    *
548    * @return The property value, or <jk>null</jk> if it is not set.
549    */
550   public Boolean getUniqueItems() { return uniqueItems; }
551
552   @Override /* Overridden from SwaggerElement */
553   public Set<String> keySet() {
554      // @formatter:off
555      var s = stb(String.class)
556         .addIf(nn(allowEmptyValue), "allowEmptyValue")
557         .addIf(nn(collectionFormat), "collectionFormat")
558         .addIf(nn(default_), "default")
559         .addIf(nn(description), "description")
560         .addIf(ine(enum_), "enum")
561         .addIf(nn(example), "example")
562         .addIf(nn(examples), "examples")
563         .addIf(nn(exclusiveMaximum), "exclusiveMaximum")
564         .addIf(nn(exclusiveMinimum), "exclusiveMinimum")
565         .addIf(nn(format), "format")
566         .addIf(nn(in), "in")
567         .addIf(nn(items), "items")
568         .addIf(nn(maxItems), "maxItems")
569         .addIf(nn(maxLength), "maxLength")
570         .addIf(nn(maximum), "maximum")
571         .addIf(nn(minItems), "minItems")
572         .addIf(nn(minLength), "minLength")
573         .addIf(nn(minimum), "minimum")
574         .addIf(nn(multipleOf), "multipleOf")
575         .addIf(nn(name), "name")
576         .addIf(nn(pattern), "pattern")
577         .addIf(nn(required), "required")
578         .addIf(nn(schema), "schema")
579         .addIf(nn(type), "type")
580         .addIf(nn(uniqueItems), "uniqueItems")
581         .build();
582      // @formatter:on
583      return new MultiSet<>(s, super.keySet());
584   }
585
586   /**
587    * Resolves any <js>"$ref"</js> attributes in this element.
588    *
589    * @param swagger The swagger document containing the definitions.
590    * @param refStack Keeps track of previously-visited references so that we don't cause recursive loops.
591    * @param maxDepth
592    *    The maximum depth to resolve references.
593    *    <br>After that level is reached, <c>$ref</c> references will be left alone.
594    *    <br>Useful if you have very complex models and you don't want your swagger page to be overly-complex.
595    * @return
596    *    This object with references resolved.
597    *    <br>May or may not be the same object.
598    */
599   public ParameterInfo resolveRefs(Swagger swagger, Deque<String> refStack, int maxDepth) {
600
601      if (nn(schema))
602         schema = schema.resolveRefs(swagger, refStack, maxDepth);
603
604      if (nn(items))
605         items = items.resolveRefs(swagger, refStack, maxDepth);
606
607      return this;
608   }
609
610   @SuppressWarnings({
611      "unchecked" // Type erasure requires cast for Swagger operations
612   })
613   @Override /* Overridden from SwaggerElement */
614   public ParameterInfo set(String property, Object value) {
615      reqnn("property", property);
616      return switch (property) {
617         case "allowEmptyValue" -> setAllowEmptyValue(toBoolean(value));
618         case "collectionFormat" -> setCollectionFormat(s(value));
619         case "default" -> setDefault(value);
620         case "description" -> setDescription(s(value));
621         case "enum" -> setEnum(value);
622         case "example" -> setExample(value);
623         case "examples" -> setExamples(toType(value, Map.class));
624         case "exclusiveMaximum" -> setExclusiveMaximum(toBoolean(value));
625         case "exclusiveMinimum" -> setExclusiveMinimum(toBoolean(value));
626         case "format" -> setFormat(s(value));
627         case "in" -> setIn(s(value));
628         case "items" -> setItems(toType(value, Items.class));
629         case "maximum" -> setMaximum(toNumber(value));
630         case "maxItems" -> setMaxItems(toInteger(value));
631         case "maxLength" -> setMaxLength(toInteger(value));
632         case "minimum" -> setMinimum(toNumber(value));
633         case "minItems" -> setMinItems(toInteger(value));
634         case "minLength" -> setMinLength(toInteger(value));
635         case "multipleOf" -> setMultipleOf(toNumber(value));
636         case "name" -> setName(s(value));
637         case "pattern" -> setPattern(s(value));
638         case "required" -> setRequired(toBoolean(value));
639         case "schema" -> setSchema(toType(value, SchemaInfo.class));
640         case "type" -> setType(s(value));
641         case "uniqueItems" -> setUniqueItems(toBoolean(value));
642         default -> {
643            super.set(property, value);
644            yield this;
645         }
646      };
647   }
648
649   /**
650    * Bean property setter:  <property>allowEmptyValue</property>.
651    *
652    * <p>
653    * Sets the ability to pass empty-valued parameters.
654    *
655    * @param value
656    *    The new value for this property.
657    *    <br>Can be <jk>null</jk> to unset the property.
658    *    <br>Default is <jk>false</jk>.
659    * @return This object.
660    */
661   public ParameterInfo setAllowEmptyValue(Boolean value) {
662      allowEmptyValue = value;
663      return this;
664   }
665
666   /**
667    * Bean property setter:  <property>collectionFormat</property>.
668    *
669    * <p>
670    * Determines the format of the array if type array is used.
671    *
672    * @param value
673    *    The new value for this property.
674    *    <br>Valid values:
675    *    <ul>
676    *       <li><js>"csv"</js> (default) - comma separated values <c>foo,bar</c>.
677    *       <li><js>"ssv"</js> - space separated values <c>foo bar</c>.
678    *       <li><js>"tsv"</js> - tab separated values <c>foo\tbar</c>.
679    *       <li><js>"pipes"</js> - pipe separated values <c>foo|bar</c>.
680    *       <li><js>"multi"</js> - corresponds to multiple parameter instances instead of multiple values for a single
681    *          instance <c>foo=bar&amp;foo=baz</c>.
682    *          <br>This is valid only for parameters <c>in</c> <js>"query"</js> or <js>"formData"</js>.
683    *    </ul>
684    *    <br>Can be <jk>null</jk> to unset the property.
685    * @return This object.
686    */
687   public ParameterInfo setCollectionFormat(String value) {
688      if (isStrict() && ! contains(value, VALID_COLLECTION_FORMATS))
689         throw rex("Invalid value passed in to setCollectionFormat(String).  Value='%s', valid values=%s", value, Json5.of(VALID_COLLECTION_FORMATS));
690      collectionFormat = value;
691      return this;
692   }
693
694   /**
695    * Bean property setter:  <property>default</property>.
696    *
697    * <p>
698    * Declares the value of the parameter that the server will use if none is provided, for example a <js>"count"</js>
699    * to control the number of results per page might default to 100 if not supplied by the client in the request.
700    * (Note: <js>"default"</js> has no meaning for required parameters.)
701    * Unlike JSON Schema this value MUST conform to the defined <c>type</c> for this parameter.
702    *
703    * @param value The new value for this property.
704    *    <br>Can be <jk>null</jk> to unset the property.
705    * @return This object.
706    */
707   public ParameterInfo setDefault(Object value) {
708      default_ = value;
709      return this;
710   }
711
712   /**
713    * Bean property setter:  <property>description</property>.
714    *
715    * <p>
716    * A brief description of the parameter.
717    *
718    * @param value
719    *    The new value for this property.
720    *    <br><a class="doclink" href="https://help.github.com/articles/github-flavored-markdown">GFM syntax</a> can be used for rich text representation.
721    *    <br>Can be <jk>null</jk> to unset the property.
722    * @return This object.
723    */
724   public ParameterInfo setDescription(String value) {
725      description = value;
726      return this;
727   }
728
729   /**
730    * Bean property setter:  <property>enum</property>.
731    *
732    * @param value
733    *    The new value for this property.
734    *    <br>Can be <jk>null</jk> to unset the property.
735    * @return This object.
736    */
737   public ParameterInfo setEnum(Collection<Object> value) {
738      enum_.clear();
739      if (nn(value))
740         enum_.addAll(value);
741      return this;
742   }
743
744   /**
745    * Bean property fluent setter:  <property>enum</property>.
746    *
747    * @param value
748    *    The new value for this property.
749    *    <br>Strings can be JSON arrays.
750    * @return This object.
751    */
752   public ParameterInfo setEnum(Object...value) {
753      setEnum(stb(Object.class).sparse().addAny(value).build());
754      return this;
755   }
756
757   /**
758    * Bean property setter:  <property>example</property>.
759    *
760    * <p>
761    * An example of the parameter. This is useful for documentation purposes.
762    *
763    * @param value
764    *    The new value for this property.
765    *    <br>Can be <jk>null</jk> to unset the property.
766    * @return This object.
767    */
768   public ParameterInfo setExample(Object value) {
769      example = value;
770      return this;
771   }
772
773   /**
774    * Bean property setter:  <property>examples</property>.
775    *
776    * <p>
777    * Examples of the parameter. This is useful for documentation purposes.
778    *
779    * @param value
780    *    The new value for this property.
781    *    <br>Can be <jk>null</jk> to unset the property.
782    * @return This object.
783    */
784   public ParameterInfo setExamples(Map<String,String> value) {
785      examples = value;
786      return this;
787   }
788
789   /**
790    * Bean property setter:  <property>exclusiveMaximum</property>.
791    *
792    * @param value The new value for this property.
793    *    <br>Can be <jk>null</jk> to unset the property.
794    * @return This object.
795    */
796   public ParameterInfo setExclusiveMaximum(Boolean value) {
797      exclusiveMaximum = value;
798      return this;
799   }
800
801   /**
802    * Bean property setter:  <property>exclusiveMinimum</property>.
803    *
804    * @param value The new value for this property.
805    *    <br>Can be <jk>null</jk> to unset the property.
806    * @return This object.
807    */
808   public ParameterInfo setExclusiveMinimum(Boolean value) {
809      exclusiveMinimum = value;
810      return this;
811   }
812
813   /**
814    * Bean property setter:  <property>format</property>.
815    *
816    * <p>
817    * The extending format for the previously mentioned type.
818    *
819    * @param value The new value for this property.
820    *    <br>Can be <jk>null</jk> to unset the property.
821    * @return This object.
822    */
823   public ParameterInfo setFormat(String value) {
824      format = value;
825      return this;
826   }
827
828   /**
829    * Bean property setter:  <property>in</property>.
830    *
831    * <p>
832    * The location of the parameter.
833    *
834    * @param value
835    *    The new value for this property.
836    *    <br>Valid values:
837    *    <ul>
838    *       <li><js>"query"</js>
839    *       <li><js>"header"</js>
840    *       <li><js>"path"</js>
841    *       <li><js>"formData"</js>
842    *       <li><js>"body"</js>
843    *    </ul>
844    *    <br>Property value is required.
845    *    <br>Can be <jk>null</jk> to unset the property.
846    * @return This object.
847    */
848   public ParameterInfo setIn(String value) {
849      if (isStrict() && ! contains(value, VALID_IN))
850         throw rex("Invalid value passed in to setIn(String).  Value='%s', valid values=%s", value, Json5.of(VALID_IN));
851      in = value;
852      if (eq(value, "path"))
853         required = true;
854      return this;
855   }
856
857   /**
858    * Bean property setter:  <property>items</property>.
859    *
860    * <p>
861    * Describes the type of items in the array.
862    *
863    * @param value
864    *    The new value for this property.
865    *    <br>Property value is required if <c>type</c> is <js>"array"</js>.
866    *    <br>Can be <jk>null</jk> to unset the property.
867    * @return This object.
868    */
869   public ParameterInfo setItems(Items value) {
870      items = value;
871      return this;
872   }
873
874   /**
875    * Bean property setter:  <property>maximum</property>.
876    *
877    * @param value The new value for this property.
878    *    <br>Can be <jk>null</jk> to unset the property.
879    * @return This object.
880    */
881   public ParameterInfo setMaximum(Number value) {
882      maximum = value;
883      return this;
884   }
885
886   /**
887    * Bean property setter:  <property>maxItems</property>.
888    *
889    * @param value The new value for this property.
890    *    <br>Can be <jk>null</jk> to unset the property.
891    * @return This object.
892    */
893   public ParameterInfo setMaxItems(Integer value) {
894      maxItems = value;
895      return this;
896   }
897
898   /**
899    * Bean property setter:  <property>maxLength</property>.
900    *
901    * @param value The new value for this property.
902    *    <br>Can be <jk>null</jk> to unset the property.
903    * @return This object.
904    */
905   public ParameterInfo setMaxLength(Integer value) {
906      maxLength = value;
907      return this;
908   }
909
910   /**
911    * Bean property setter:  <property>minimum</property>.
912    *
913    * @param value The new value for this property.
914    *    <br>Can be <jk>null</jk> to unset the property.
915    * @return This object.
916    */
917   public ParameterInfo setMinimum(Number value) {
918      minimum = value;
919      return this;
920   }
921
922   /**
923    * Bean property setter:  <property>minItems</property>.
924    *
925    * @param value The new value for this property.
926    *    <br>Can be <jk>null</jk> to unset the property.
927    * @return This object.
928    */
929   public ParameterInfo setMinItems(Integer value) {
930      minItems = value;
931      return this;
932   }
933
934   /**
935    * Bean property setter:  <property>minLength</property>.
936    *
937    * @param value The new value for this property.
938    *    <br>Can be <jk>null</jk> to unset the property.
939    * @return This object.
940    */
941   public ParameterInfo setMinLength(Integer value) {
942      minLength = value;
943      return this;
944   }
945
946   /**
947    * Bean property setter:  <property>multipleOf</property>.
948    *
949    * @param value
950    *    The new value for this property.
951    *    <br>Can be <jk>null</jk> to unset the property.
952    * @return This object.
953    */
954   public ParameterInfo setMultipleOf(Number value) {
955      multipleOf = value;
956      return this;
957   }
958
959   /**
960    * Bean property setter:  <property>name</property>.
961    *
962    * <p>
963    * The name of the parameter.
964    *
965    * @param value
966    *    The new value for this property.
967    *    <br>Property value is required.
968    *    <br>Can be <jk>null</jk> to unset the property.
969    * @return This object.
970    */
971   public ParameterInfo setName(String value) {
972      if (neq(in, "body"))
973         name = value;
974      return this;
975   }
976
977   /**
978    * Bean property setter:  <property>pattern</property>.
979    *
980    * @param value
981    *    The new value for this property.
982    *    <br>This string SHOULD be a valid regular expression.
983    *    <br>Can be <jk>null</jk> to unset the property.
984    * @return This object.
985    */
986   public ParameterInfo setPattern(String value) {
987      pattern = value;
988      return this;
989   }
990
991   /**
992    * Bean property setter:  <property>required</property>.
993    *
994    * <p>
995    * Determines whether this parameter is mandatory.
996    *
997    * @param value
998    *    The new value for this property.
999    *    <br>If the parameter is <c>in</c> <js>"path"</js>, this property is required and its value MUST be <jk>true</jk>.
1000    *    <br>Otherwise, the property MAY be included and its default value is <jk>false</jk>.
1001    *    <br>Can be <jk>null</jk> to unset the property.
1002    * @return This object.
1003    */
1004   public ParameterInfo setRequired(Boolean value) {
1005      required = value;
1006      return this;
1007   }
1008
1009   /**
1010    * Bean property setter:  <property>schema</property>.
1011    *
1012    * <p>
1013    * The schema defining the type used for the body parameter.
1014    *
1015    * @param value
1016    *    The new value for this property.
1017    *    <br>Property value is required.
1018    *    <br>Can be <jk>null</jk> to unset the property.
1019    * @return This object.
1020    */
1021   public ParameterInfo setSchema(SchemaInfo value) {
1022      schema = value;
1023      return this;
1024   }
1025
1026   /**
1027    * Bean property setter:  <property>type</property>.
1028    *
1029    * <p>
1030    * The type of the parameter.
1031    *
1032    * @param value
1033    *    The new value for this property.
1034    *    <br>Valid values:
1035    *    <ul>
1036    *       <li><js>"string"</js>
1037    *       <li><js>"number"</js>
1038    *       <li><js>"integer"</js>
1039    *       <li><js>"boolean"</js>
1040    *       <li><js>"array"</js>
1041    *       <li><js>"file"</js>
1042    *    </ul>
1043    *    <br>If type is <js>"file"</js>, the <c>consumes</c> MUST be either <js>"multipart/form-data"</js>, <js>"application/x-www-form-urlencoded"</js>
1044    *       or both and the parameter MUST be <c>in</c> <js>"formData"</js>.
1045    *    <br>Property value is required.
1046    *    <br>Can be <jk>null</jk> to unset the property.
1047    * @return This object.
1048    */
1049   public ParameterInfo setType(String value) {
1050      if (isStrict() && ! contains(value, VALID_TYPES))
1051         throw rex("Invalid value passed in to setType(String).  Value='%s', valid values=%s", value, Json5.of(VALID_TYPES));
1052      type = value;
1053      return this;
1054   }
1055
1056   /**
1057    * Bean property setter:  <property>uniqueItems</property>.
1058    *
1059    * @param value The new value for this property.
1060    * @return This object.
1061    */
1062   public ParameterInfo setUniqueItems(Boolean value) {
1063      uniqueItems = value;
1064      return this;
1065   }
1066
1067   @Override /* Overridden from SwaggerElement */
1068   public ParameterInfo strict() {
1069      super.strict();
1070      return this;
1071   }
1072
1073   /**
1074    * Sets strict mode on this bean.
1075    *
1076    * @param value
1077    *    The new value for this property.
1078    *    <br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
1079    *    <br>Can be <jk>null</jk> (interpreted as <jk>false</jk>).
1080    * @return This object.
1081    */
1082   @Override
1083   public ParameterInfo strict(Object value) {
1084      super.strict(value);
1085      return this;
1086   }
1087}