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