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