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