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.CollectionUtils.*;
017import static org.apache.juneau.internal.ConverterUtils.*;
018
019import java.util.*;
020
021import org.apache.juneau.annotation.*;
022import org.apache.juneau.internal.*;
023
024/**
025 * The Schema Object allows the definition of input and output data types.
026 *
027 * <p>
028 * These types can be objects, but also primitives and arrays.
029 * This object is based on the JSON Schema Specification Draft 4 and uses a predefined subset of it.
030 * On top of this subset, there are extensions provided by this specification to allow for more complete documentation.
031 *
032 * <p>
033 * Further information about the properties can be found in JSON Schema Core and JSON Schema Validation.
034 * Unless stated otherwise, the property definitions follow the JSON Schema specification as referenced here.
035 *
036 * <h5 class='section'>Example:</h5>
037 * <p class='bjava'>
038 *    <jc>// Construct using SwaggerBuilder.</jc>
039 *    SchemaInfo <jv>info</jv> = <jsm>schemaInfo</jsm>()
040 *       .type(<js>"string"</js>)
041 *       .title(<js>"foo"</js>)
042 *
043 *    <jc>// Serialize using JsonSerializer.</jc>
044 *    String <jv>json</jv> = JsonSerializer.<jsf>DEFAULT</jsf>.toString(<jv>info</jv>);
045 *
046 *    <jc>// Or just use toString() which does the same as above.</jc>
047 *    <jv>json</jv> = <jv>info</jv>.toString();
048 * </p>
049 * <p class='bjson'>
050 *    <jc>// Output</jc>
051 *    {
052 *       <js>"type"</js>: <js>"string"</js>,
053 *       <js>"title"</js>: <js>"foo"</js>
054 *    }
055 * </p>
056 *
057 * <h5 class='section'>See Also:</h5><ul>
058 *    <li class='link'><a class="doclink" href="../../../../../index.html#jrs.Swagger">Overview &gt; juneau-rest-server &gt; Swagger</a>
059 * </ul>
060 */
061@Bean(properties="format,title,description,default,multipleOf,maximum,exclusiveMaximum,minimum,exclusiveMinimum,maxLength,minLength,pattern,maxItems,minItems,uniqueItems,maxProperties,minProperties,required,requiredProperties,enum,type,items,allOf,properties,additionalProperties,discriminator,readOnly,xml,externalDocs,example,$ref,*")
062@FluentSetters
063public class SchemaInfo extends SwaggerElement {
064
065   private String
066      format,
067      title,
068      description,
069      pattern,
070      type,
071      discriminator,
072      ref;
073   private Number
074      multipleOf,
075      maximum,
076      minimum;
077   private Integer
078      maxLength,
079      minLength,
080      maxItems,
081      minItems,
082      maxProperties,
083      minProperties;
084   private Boolean
085      exclusiveMaximum,
086      exclusiveMinimum,
087      uniqueItems,
088      readOnly,
089      required;
090   private Object
091      _default,
092      example;
093   private Items items;
094   private Xml xml;
095   private ExternalDocumentation externalDocs;
096   private Set<Object>
097      _enum,
098      allOf;
099   private Set<String>
100      requiredProperties;
101   private Map<String,SchemaInfo> properties;
102   private SchemaInfo additionalProperties;
103
104   /**
105    * Default constructor.
106    */
107   public SchemaInfo() {}
108
109   /**
110    * Copy constructor.
111    *
112    * @param copyFrom The object to copy.
113    */
114   public SchemaInfo(SchemaInfo copyFrom) {
115      super(copyFrom);
116
117      this.additionalProperties = copyFrom.additionalProperties == null ? null : copyFrom.additionalProperties.copy();
118      this.allOf = copyOf(copyFrom.allOf);
119      this._default = copyFrom._default;
120      this.description = copyFrom.description;
121      this.discriminator = copyFrom.discriminator;
122      this._enum = copyOf(copyFrom._enum);
123      this.example = copyFrom.example;
124      this.exclusiveMaximum = copyFrom.exclusiveMaximum;
125      this.exclusiveMinimum = copyFrom.exclusiveMinimum;
126      this.externalDocs = copyFrom.externalDocs == null ? null : copyFrom.externalDocs.copy();
127      this.format = copyFrom.format;
128      this.items = copyFrom.items == null ? null : copyFrom.items.copy();
129      this.maximum = copyFrom.maximum;
130      this.maxItems = copyFrom.maxItems;
131      this.maxLength = copyFrom.maxLength;
132      this.maxProperties = copyFrom.maxProperties;
133      this.minimum = copyFrom.minimum;
134      this.minItems = copyFrom.minItems;
135      this.minLength = copyFrom.minLength;
136      this.minProperties = copyFrom.minProperties;
137      this.multipleOf = copyFrom.multipleOf;
138      this.pattern = copyFrom.pattern;
139      this.readOnly = copyFrom.readOnly;
140      this.ref = copyFrom.ref;
141      this.required = copyFrom.required;
142      this.requiredProperties = copyOf(copyFrom.requiredProperties);
143      this.title = copyFrom.title;
144      this.type = copyFrom.type;
145      this.uniqueItems = copyFrom.uniqueItems;
146      this.xml = copyFrom.xml == null ? null : copyFrom.xml.copy();
147
148      if (copyFrom.properties == null) {
149         this.properties = null;
150      } else {
151         this.properties = map();
152         copyFrom.properties.forEach((k,v) -> this.properties.put(k, v.copy()));
153      }
154   }
155
156   /**
157    * Make a deep copy of this object.
158    *
159    * @return A deep copy of this object.
160    */
161   public SchemaInfo copy() {
162      return new SchemaInfo(this);
163   }
164
165   //-----------------------------------------------------------------------------------------------------------------
166   // Properties
167   //-----------------------------------------------------------------------------------------------------------------
168
169   /**
170    * Bean property getter:  <property>additionalProperties</property>.
171    *
172    * @return The property value, or <jk>null</jk> if it is not set.
173    */
174   public SchemaInfo getAdditionalProperties() {
175      return additionalProperties;
176   }
177
178   /**
179    * Bean property setter:  <property>additionalProperties</property>.
180    *
181    * @param value
182    *    The new value for this property.
183    *    <br>Can be <jk>null</jk> to unset the property.
184    * @return This object.
185    */
186   public SchemaInfo setAdditionalProperties(SchemaInfo value) {
187      additionalProperties = value;
188      return this;
189   }
190
191   /**
192    * Bean property getter:  <property>allOf</property>.
193    *
194    * @return The property value, or <jk>null</jk> if it is not set.
195    */
196   public Set<Object> getAllOf() {
197      return allOf;
198   }
199
200   /**
201    * Bean property setter:  <property>allOf</property>.
202    *
203    * @param value
204    *    The new value for this property.
205    *    <br>Can be <jk>null</jk> to unset the property.
206    * @return This object.
207    */
208   public SchemaInfo setAllOf(Collection<Object> value) {
209      allOf = setFrom(value);
210      return this;
211   }
212
213   /**
214    * Bean property appender:  <property>allOf</property>.
215    *
216    * @param values
217    *    The values to add to this property.
218    *    <br>Ignored if <jk>null</jk>.
219    * @return This object.
220    */
221   public SchemaInfo addAllOf(Object...values) {
222      allOf = setBuilder(allOf).sparse().add(values).build();
223      return this;
224   }
225
226   /**
227    * Bean property fluent setter:  <property>allOf</property>.
228    *
229    * @param value
230    *    The new value for this property.
231    *    <br>Strings can contains JSON arrays.
232    *    <br>Valid types:
233    * @return This object.
234    */
235   public SchemaInfo setAllOf(Object...value) {
236      setAllOf(setBuilder(Object.class).sparse().addAny(value).build());
237      return this;
238   }
239
240   /**
241    * Bean property getter:  <property>default</property>.
242    *
243    * <p>
244    * Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object.
245    *
246    * @return The property value, or <jk>null</jk> if it is not set.
247    */
248   public Object getDefault() {
249      return _default;
250   }
251
252   /**
253    * Bean property setter:  <property>default</property>.
254    *
255    * <p>
256    * Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object.
257    *
258    * @param value
259    *    The new value for this property.
260    *    <br>Can be <jk>null</jk> to unset the property.
261    * @return This object.
262    */
263   public SchemaInfo setDefault(Object value) {
264      _default = value;
265      return this;
266   }
267
268   /**
269    * Bean property getter:  <property>description</property>.
270    *
271    * @return The property value, or <jk>null</jk> if it is not set.
272    */
273   public String getDescription() {
274      return description;
275   }
276
277   /**
278    * Bean property setter:  <property>description</property>.
279    *
280    * @param value
281    *    The new value for this property.
282    *    <br><a class="doclink" href="https://help.github.com/articles/github-flavored-markdown">GFM syntax</a> can be used for rich text representation.
283    *    <br>Can be <jk>null</jk> to unset the property.
284    * @return This object.
285    */
286   public SchemaInfo setDescription(String value) {
287      description = value;
288      return this;
289   }
290
291   /**
292    * Bean property getter:  <property>discriminator</property>.
293    *
294    * @return The property value, or <jk>null</jk> if it is not set.
295    */
296   public String getDiscriminator() {
297      return discriminator;
298   }
299
300   /**
301    * Bean property setter:  <property>discriminator</property>.
302    *
303    * @param value
304    *    The new value for this property.
305    *    <br>Can be <jk>null</jk> to unset the property.
306    * @return This object.
307    */
308   public SchemaInfo setDiscriminator(String value) {
309      discriminator = value;
310      return this;
311   }
312
313   /**
314    * Bean property getter:  <property>enum</property>.
315    *
316    * @return The property value, or <jk>null</jk> if it is not set.
317    */
318   public Set<Object> getEnum() {
319      return _enum;
320   }
321
322   /**
323    * Bean property setter:  <property>enum</property>.
324    *
325    * @param value
326    *    The new value for this property.
327    *    <br>Can be <jk>null</jk> to unset the property.
328    * @return This object.
329    */
330   public SchemaInfo setEnum(Collection<Object> value) {
331      _enum = setFrom(value);
332      return this;
333   }
334
335   /**
336    * Bean property appender:  <property>enum</property>.
337    *
338    * @param value
339    *    The values to add to this property.
340    *    <br>Ignored if <jk>null</jk>.
341    * @return This object.
342    */
343   public SchemaInfo addEnum(Object...value) {
344      _enum = setBuilder(_enum).sparse().add(value).build();
345      return this;
346   }
347
348   /**
349    * Bean property fluent setter:  <property>enum</property>.
350    *
351    * @param value
352    *    The new value for this property.
353    *    <br>Strings can be JSON arrays.
354    * @return This object.
355    */
356   public SchemaInfo setEnum(Object...value) {
357      setEnum(setBuilder(Object.class).sparse().addAny(value).build());
358      return this;
359   }
360
361   /**
362    * Bean property getter:  <property>example</property>.
363    *
364    * @return The property value, or <jk>null</jk> if it is not set.
365    */
366   public Object getExample() {
367      return example;
368   }
369
370   /**
371    * Bean property setter:  <property>example</property>.
372    *
373    * @param value
374    *    The new value for this property.
375    *    <br>Can be <jk>null</jk> to unset the property.
376    * @return This object.
377    */
378   public SchemaInfo setExample(Object value) {
379      example = value;
380      return this;
381   }
382
383   /**
384    * Bean property getter:  <property>exclusiveMaximum</property>.
385    *
386    * @return The property value, or <jk>null</jk> if it is not set.
387    */
388   public Boolean getExclusiveMaximum() {
389      return exclusiveMaximum;
390   }
391
392   /**
393    * Bean property setter:  <property>exclusiveMaximum</property>.
394    *
395    * @param value
396    *    The new value for this property.
397    *    <br>Can be <jk>null</jk> to unset the property.
398    * @return This object.
399    */
400   public SchemaInfo setExclusiveMaximum(Boolean value) {
401      exclusiveMaximum = value;
402      return this;
403   }
404
405   /**
406    * Bean property getter:  <property>exclusiveMinimum</property>.
407    *
408    * @return The property value, or <jk>null</jk> if it is not set.
409    */
410   public Boolean getExclusiveMinimum() {
411      return exclusiveMinimum;
412   }
413
414   /**
415    * Bean property setter:  <property>exclusiveMinimum</property>.
416    *
417    * @param value
418    *    The new value for this property.
419    *    <br>Can be <jk>null</jk> to unset the property.
420    * @return This object.
421    */
422   public SchemaInfo setExclusiveMinimum(Boolean value) {
423      exclusiveMinimum = value;
424      return this;
425   }
426
427   /**
428    * Bean property getter:  <property>externalDocs</property>.
429    *
430    * @return The property value, or <jk>null</jk> if it is not set.
431    */
432   public ExternalDocumentation getExternalDocs() {
433      return externalDocs;
434   }
435
436   /**
437    * Bean property setter:  <property>externalDocs</property>.
438    *
439    * @param value
440    *    The new value for this property.
441    *    <br>Can be <jk>null</jk> to unset the property.
442    * @return This object.
443    */
444   public SchemaInfo setExternalDocs(ExternalDocumentation value) {
445      externalDocs = value;
446      return this;
447   }
448
449   /**
450    * Bean property getter:  <property>format</property>.
451    *
452    * @return The property value, or <jk>null</jk> if it is not set.
453    */
454   public String getFormat() {
455      return format;
456   }
457
458   /**
459    * Bean property setter:  <property>format</property>.
460    *
461    * @param value
462    *    The new value for this property.
463    *    <br>Can be <jk>null</jk> to unset the property.
464    *    <br>Formats defined by the OAS include:
465    *    <ul>
466    *       <li><js>"int32"</js>
467    *       <li><js>"int64"</js>
468    *       <li><js>"float"</js>
469    *       <li><js>"double"</js>
470    *       <li><js>"byte"</js>
471    *       <li><js>"binary"</js>
472    *       <li><js>"date"</js>
473    *       <li><js>"date-time"</js>
474    *       <li><js>"password"</js>
475    *    </ul>
476    * @return This object.
477    */
478   public SchemaInfo setFormat(String value) {
479      format = value;
480      return this;
481   }
482
483   /**
484    * Bean property getter:  <property>items</property>.
485    *
486    * @return The property value, or <jk>null</jk> if it is not set.
487    */
488   public Items getItems() {
489      return items;
490   }
491
492   /**
493    * Bean property setter:  <property>items</property>.
494    *
495    * @param value
496    *    The new value for this property.
497    *    <br>Can be <jk>null</jk> to unset the property.
498    * @return This object.
499    */
500   public SchemaInfo setItems(Items value) {
501      items = value;
502      return this;
503   }
504
505   /**
506    * Bean property getter:  <property>maximum</property>.
507    *
508    * @return The property value, or <jk>null</jk> if it is not set.
509    */
510   public Number getMaximum() {
511      return maximum;
512   }
513
514   /**
515    * Bean property setter:  <property>maximum</property>.
516    *
517    * @param value
518    *    The new value for this property.
519    *    <br>Can be <jk>null</jk> to unset the property.
520    * @return This object.
521    */
522   public SchemaInfo setMaximum(Number value) {
523      maximum = value;
524      return this;
525   }
526
527   /**
528    * Bean property getter:  <property>maxItems</property>.
529    *
530    * @return The property value, or <jk>null</jk> if it is not set.
531    */
532   public Integer getMaxItems() {
533      return maxItems;
534   }
535
536   /**
537    * Bean property setter:  <property>maxItems</property>.
538    *
539    * @param value
540    *    The new value for this property.
541    *    <br>Can be <jk>null</jk> to unset the property.
542    * @return This object.
543    */
544   public SchemaInfo setMaxItems(Integer value) {
545      maxItems = value;
546      return this;
547   }
548
549   /**
550    * Bean property getter:  <property>maxLength</property>.
551    *
552    * @return The property value, or <jk>null</jk> if it is not set.
553    */
554   public Integer getMaxLength() {
555      return maxLength;
556   }
557
558   /**
559    * Bean property setter:  <property>maxLength</property>.
560    *
561    * @param value
562    *    The new value for this property.
563    *    <br>Can be <jk>null</jk> to unset the property.
564    * @return This object.
565    */
566   public SchemaInfo setMaxLength(Integer value) {
567      maxLength = value;
568      return this;
569   }
570
571   /**
572    * Bean property getter:  <property>maxProperties</property>.
573    *
574    * @return The property value, or <jk>null</jk> if it is not set.
575    */
576   public Integer getMaxProperties() {
577      return maxProperties;
578   }
579
580   /**
581    * Bean property setter:  <property>maxProperties</property>.
582    *
583    * @param value
584    *    The new value for this property.
585    *    <br>Can be <jk>null</jk> to unset the property.
586    * @return This object.
587    */
588   public SchemaInfo setMaxProperties(Integer value) {
589      maxProperties = value;
590      return this;
591   }
592
593   /**
594    * Bean property getter:  <property>minimum</property>.
595    *
596    * @return The property value, or <jk>null</jk> if it is not set.
597    */
598   public Number getMinimum() {
599      return minimum;
600   }
601
602   /**
603    * Bean property setter:  <property>minimum</property>.
604    *
605    * @param value
606    *    The new value for this property.
607    *    <br>Can be <jk>null</jk> to unset the property.
608    * @return This object.
609    */
610   public SchemaInfo setMinimum(Number value) {
611      minimum = value;
612      return this;
613   }
614
615   /**
616    * Bean property getter:  <property>minItems</property>.
617    *
618    * @return The property value, or <jk>null</jk> if it is not set.
619    */
620   public Integer getMinItems() {
621      return minItems;
622   }
623
624   /**
625    * Bean property setter:  <property>minItems</property>.
626    *
627    * @param value
628    *    The new value for this property.
629    *    <br>Can be <jk>null</jk> to unset the property.
630    * @return This object.
631    */
632   public SchemaInfo setMinItems(Integer value) {
633      minItems = value;
634      return this;
635   }
636
637   /**
638    * Bean property getter:  <property>minLength</property>.
639    *
640    * @return The property value, or <jk>null</jk> if it is not set.
641    */
642   public Integer getMinLength() {
643      return minLength;
644   }
645
646   /**
647    * Bean property setter:  <property>minLength</property>.
648    *
649    * @param value
650    *    The new value for this property.
651    *    <br>Can be <jk>null</jk> to unset the property.
652    * @return This object.
653    */
654   public SchemaInfo setMinLength(Integer value) {
655      minLength = value;
656      return this;
657   }
658
659   /**
660    * Bean property getter:  <property>minProperties</property>.
661    *
662    * @return The property value, or <jk>null</jk> if it is not set.
663    */
664   public Integer getMinProperties() {
665      return minProperties;
666   }
667
668   /**
669    * Bean property setter:  <property>minProperties</property>.
670    *
671    * @param value
672    *    The new value for this property.
673    *    <br>Can be <jk>null</jk> to unset the property.
674    * @return This object.
675    */
676   public SchemaInfo setMinProperties(Integer value) {
677      minProperties = value;
678      return this;
679   }
680
681   /**
682    * Bean property getter:  <property>multipleOf</property>.
683    *
684    * @return The property value, or <jk>null</jk> if it is not set.
685    */
686   public Number getMultipleOf() {
687      return multipleOf;
688   }
689
690   /**
691    * Bean property setter:  <property>multipleOf</property>.
692    *
693    * @param value
694    *    The new value for this property.
695    *    <br>Can be <jk>null</jk> to unset the property.
696    * @return This object.
697    */
698   public SchemaInfo setMultipleOf(Number value) {
699      multipleOf = value;
700      return this;
701   }
702
703   /**
704    * Bean property getter:  <property>pattern</property>.
705    *
706    * @return The property value, or <jk>null</jk> if it is not set.
707    */
708   public String getPattern() {
709      return pattern;
710   }
711
712   /**
713    * Bean property setter:  <property>pattern</property>.
714    *
715    * @param value
716    *    The new value for this property.
717    *    <br>This string SHOULD be a valid regular expression.
718    *    <br>Can be <jk>null</jk> to unset the property.
719    * @return This object.
720    */
721   public SchemaInfo setPattern(String value) {
722      pattern = value;
723      return this;
724   }
725
726   /**
727    * Bean property getter:  <property>properties</property>.
728    *
729    * @return The property value, or <jk>null</jk> if it is not set.
730    */
731   public Map<String,SchemaInfo> getProperties() {
732      return properties;
733   }
734
735   /**
736    * Bean property setter:  <property>properties</property>.
737    *
738    * @param value
739    *    The new value for this property.
740    *    <br>Can be <jk>null</jk> to unset the property.
741    * @return This object.
742    */
743   public SchemaInfo setProperties(Map<String,SchemaInfo> value) {
744      properties = copyOf(value);
745      return this;
746   }
747
748   /**
749    * Bean property appender:  <property>properties</property>.
750    *
751    * @param key The property key.
752    * @param value The property value.
753    * @return This object.
754    */
755   public SchemaInfo addProperty(String key, SchemaInfo value) {
756      properties = mapBuilder(properties).sparse().add(key, value).build();
757      return this;
758   }
759
760   /**
761    * Bean property getter:  <property>readOnly</property>.
762    *
763    * @return The property value, or <jk>null</jk> if it is not set.
764    */
765   public Boolean getReadOnly() {
766      return readOnly;
767   }
768
769   /**
770    * Bean property setter:  <property>readOnly</property>.
771    *
772    * @param value
773    *    The new value for this property.
774    *    <br>Can be <jk>null</jk> to unset the property.
775    * @return This object.
776    */
777   public SchemaInfo setReadOnly(Boolean value) {
778      readOnly = value;
779      return this;
780   }
781
782   /**
783    * Bean property getter:  <property>$ref</property>.
784    *
785    * @return The property value, or <jk>null</jk> if it is not set.
786    */
787   @Beanp("$ref")
788   public String getRef() {
789      return ref;
790   }
791
792   /**
793    * Bean property setter:  <property>$ref</property>.
794    *
795    * @param value
796    *    The new value for this property.
797    *    <br>Can be <jk>null</jk> to unset the property.
798    * @return This object.
799    */
800   @Beanp("$ref")
801   public SchemaInfo setRef(String value) {
802      ref = value;
803      return this;
804   }
805
806   /**
807    * Bean property getter:  <property>required</property>.
808    *
809    * @return The property value, or <jk>null</jk> if it is not set.
810    */
811   public Boolean getRequired() {
812      return required;
813   }
814
815   /**
816    * Bean property setter:  <property>required</property>.
817    *
818    * @param value
819    *    The new value for this property.
820    *    <br>Can be <jk>null</jk> to unset the property.
821    * @return This object.
822    */
823   public SchemaInfo setRequired(Boolean value) {
824      required = value;
825      return this;
826   }
827
828   /**
829    * Bean property getter:  <property>requiredProperties</property>.
830    *
831    * <p>
832    * The list of required properties.
833    *
834    * @return The property value, or <jk>null</jk> if it is not set.
835    */
836   public Set<String> getRequiredProperties() {
837      return requiredProperties;
838   }
839
840   /**
841    * Bean property setter:  <property>requiredProperties</property>.
842    *
843    * <p>
844    * The list of required properties.
845    *
846    * @param value
847    *    The new value for this property.
848    *    <br>Valid values:
849    *    <ul>
850    *       <li><js>"http"</js>
851    *       <li><js>"https"</js>
852    *       <li><js>"ws"</js>
853    *       <li><js>"wss"</js>
854    *    </ul>
855    *    <br>Can be <jk>null</jk> to unset the property.
856    * @return This object.
857    */
858   public SchemaInfo setRequiredProperties(Collection<String> value) {
859      requiredProperties = setFrom(value);
860      return this;
861   }
862
863   /**
864    * Bean property appender:  <property>requiredProperties</property>.
865    *
866    * <p>
867    * The list of required properties.
868    *
869    * @param value
870    *    The values to add to this property.
871    *    <br>Ignored if <jk>null</jk>.
872    * @return This object.
873    */
874   public SchemaInfo addRequiredProperties(String...value) {
875      requiredProperties = setBuilder(requiredProperties).sparse().add(value).build();
876      return this;
877   }
878
879   /**
880    * Bean property fluent setter:  <property>requiredProperties</property>.
881    *
882    * @param value
883    *    The new value for this property.
884    * @return This object.
885    */
886   public SchemaInfo setRequiredProperties(String...value) {
887      setRequiredProperties(setBuilder(String.class).sparse().addJson(value).build());
888      return this;
889   }
890
891   /**
892    * Bean property getter:  <property>title</property>.
893    *
894    * @return The property value, or <jk>null</jk> if it is not set.
895    */
896   public String getTitle() {
897      return title;
898   }
899
900   /**
901    * Bean property setter:  <property>title</property>.
902    *
903    * @param value
904    *    The new value for this property.
905    *    <br>Can be <jk>null</jk> to unset the property.
906    * @return This object.
907    */
908   public SchemaInfo setTitle(String value) {
909      title = value;
910      return this;
911   }
912
913   /**
914    * Bean property getter:  <property>type</property>.
915    *
916    * @return The property value, or <jk>null</jk> if it is not set.
917    */
918   public String getType() {
919      return type;
920   }
921
922   /**
923    * Bean property setter:  <property>type</property>.
924    *
925    * @param value
926    *    The new value for this property.
927    *    <br>Can be <jk>null</jk> to unset the property.
928    *    <br>Possible values include:
929    *    <ul>
930    *       <li><js>"object"</js>
931    *       <li><js>"string"</js>
932    *       <li><js>"number"</js>
933    *       <li><js>"integer"</js>
934    *       <li><js>"boolean"</js>
935    *       <li><js>"array"</js>
936    *       <li><js>"file"</js>
937    *    </ul>
938    * @return This object.
939    */
940   public SchemaInfo setType(String value) {
941      type = value;
942      return this;
943   }
944
945   /**
946    * Bean property getter:  <property>uniqueItems</property>.
947    *
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
958    *    The new value for this property.
959    *    <br>Can be <jk>null</jk> to unset the property.
960    * @return This object.
961    */
962   public SchemaInfo setUniqueItems(Boolean value) {
963      uniqueItems = value;
964      return this;
965   }
966
967   /**
968    * Bean property getter:  <property>xml</property>.
969    *
970    * @return The property value, or <jk>null</jk> if it is not set.
971    */
972   public Xml getXml() {
973      return xml;
974   }
975
976   /**
977    * Bean property setter:  <property>xml</property>.
978    *
979    * @param value
980    *    The new value for this property.
981    *    <br>Can be <jk>null</jk> to unset the property.
982    * @return This object.
983    */
984   public SchemaInfo setXml(Xml value) {
985      xml = value;
986      return this;
987   }
988
989   // <FluentSetters>
990
991   // </FluentSetters>
992
993   @Override /* SwaggerElement */
994   public <T> T get(String property, Class<T> type) {
995      if (property == null)
996         return null;
997      switch (property) {
998         case "additionalProperties": return toType(getAdditionalProperties(), type);
999         case "allOf": return toType(getAllOf(), type);
1000         case "default": return toType(getDefault(), type);
1001         case "description": return toType(getDescription(), type);
1002         case "discriminator": return toType(getDiscriminator(), type);
1003         case "enum": return toType(getEnum(), type);
1004         case "example": return toType(getExample(), type);
1005         case "exclusiveMaximum": return toType(getExclusiveMaximum(), type);
1006         case "exclusiveMinimum": return toType(getExclusiveMinimum(), type);
1007         case "externalDocs": return toType(getExternalDocs(), type);
1008         case "format": return toType(getFormat(), type);
1009         case "items": return toType(getItems(), type);
1010         case "maximum": return toType(getMaximum(), type);
1011         case "maxItems": return toType(getMaxItems(), type);
1012         case "maxLength": return toType(getMaxLength(), type);
1013         case "maxProperties": return toType(getMaxProperties(), type);
1014         case "minimum": return toType(getMinimum(), type);
1015         case "minItems": return toType(getMinItems(), type);
1016         case "minLength": return toType(getMinLength(), type);
1017         case "minProperties": return toType(getMinProperties(), type);
1018         case "multipleOf": return toType(getMultipleOf(), type);
1019         case "pattern": return toType(getPattern(), type);
1020         case "properties": return toType(getProperties(), type);
1021         case "readOnly": return toType(getReadOnly(), type);
1022         case "$ref": return toType(getRef(), type);
1023         case "rquired": return toType(getRequired(), type);
1024         case "requiredProperties": return toType(getRequiredProperties(), type);
1025         case "title": return toType(getTitle(), type);
1026         case "type": return toType(getType(), type);
1027         case "uniqueItems": return toType(getUniqueItems(), type);
1028         case "xml": return toType(getXml(), type);
1029         default: return super.get(property, type);
1030      }
1031   }
1032
1033   @Override /* SwaggerElement */
1034   public SchemaInfo set(String property, Object value) {
1035      if (property == null)
1036         return this;
1037      switch (property) {
1038         case "additionalProperties": return setAdditionalProperties(toType(value, SchemaInfo.class));
1039         case "allOf": return setAllOf(value);
1040         case "default": return setDefault(value);
1041         case "description": return setDescription(stringify(value));
1042         case "discriminator": return setDiscriminator(stringify(value));
1043         case "enum": return setEnum(value);
1044         case "example": return setExample(value);
1045         case "exclusiveMaximum": return setExclusiveMaximum(toBoolean(value));
1046         case "exclusiveMinimum": return setExclusiveMinimum(toBoolean(value));
1047         case "externalDocs": return setExternalDocs(toType(value, ExternalDocumentation.class));
1048         case "format": return setFormat(stringify(value));
1049         case "items": return setItems(toType(value, Items.class));
1050         case "maximum": return setMaximum(toNumber(value));
1051         case "maxItems": return setMaxItems(toInteger(value));
1052         case "maxLength": return setMaxLength(toInteger(value));
1053         case "maxProperties": return setMaxProperties(toInteger(value));
1054         case "minimum": return setMinimum(toNumber(value));
1055         case "minItems": return setMinItems(toInteger(value));
1056         case "minLength": return setMinLength(toInteger(value));
1057         case "minProperties": return setMinProperties(toInteger(value));
1058         case "multipleOf": return setMultipleOf(toNumber(value));
1059         case "pattern": return setPattern(stringify(value));
1060         case "properties": return setProperties(mapBuilder(String.class,SchemaInfo.class).sparse().addAny(value).build());
1061         case "readOnly": return setReadOnly(toBoolean(value));
1062         case "$ref": return setRef(stringify(value));
1063         case "required": return setRequired(toBoolean(value));
1064         case "requiredProperties": return setRequiredProperties(listBuilder(String.class).sparse().addAny(value).build());
1065         case "title": return setTitle(stringify(value));
1066         case "type": return setType(stringify(value));
1067         case "uniqueItems": return setUniqueItems(toBoolean(value));
1068         case "xml": return setXml(toType(value, Xml.class));
1069         default:
1070            super.set(property, value);
1071            return this;
1072      }
1073   }
1074
1075   @Override /* SwaggerElement */
1076   public Set<String> keySet() {
1077      Set<String> s = setBuilder(String.class)
1078         .addIf(additionalProperties != null, "additionalProperties")
1079         .addIf(allOf != null, "allOf")
1080         .addIf(_default != null, "default")
1081         .addIf(description != null, "description")
1082         .addIf(discriminator != null, "discriminator")
1083         .addIf(_enum != null, "enum")
1084         .addIf(example != null, "example")
1085         .addIf(exclusiveMaximum != null, "exclusiveMaximum")
1086         .addIf(exclusiveMinimum != null, "exclusiveMinimum")
1087         .addIf(externalDocs != null, "externalDocs")
1088         .addIf(format != null, "format")
1089         .addIf(items != null, "items")
1090         .addIf(maximum != null, "maximum")
1091         .addIf(maxItems != null, "maxItems")
1092         .addIf(maxLength != null, "maxLength")
1093         .addIf(maxProperties != null, "maxProperties")
1094         .addIf(minimum != null, "minimum")
1095         .addIf(minItems != null, "minItems")
1096         .addIf(minLength != null, "minLength")
1097         .addIf(minProperties != null, "minProperties")
1098         .addIf(multipleOf != null, "multipleOf")
1099         .addIf(pattern != null, "pattern")
1100         .addIf(properties != null, "properties")
1101         .addIf(readOnly != null, "readOnly")
1102         .addIf(ref != null, "$ref")
1103         .addIf(required != null, "required")
1104         .addIf(requiredProperties != null, "requiredProperties")
1105         .addIf(title != null, "title")
1106         .addIf(type != null, "type")
1107         .addIf(uniqueItems != null, "uniqueItems")
1108         .addIf(xml != null, "xml")
1109         .build();
1110      return new MultiSet<>(s, super.keySet());
1111   }
1112
1113   /**
1114    * Resolves any <js>"$ref"</js> attributes in this element.
1115    *
1116    * @param swagger The swagger document containing the definitions.
1117    * @param refStack Keeps track of previously-visited references so that we don't cause recursive loops.
1118    * @param maxDepth
1119    *    The maximum depth to resolve references.
1120    *    <br>After that level is reached, <c>$ref</c> references will be left alone.
1121    *    <br>Useful if you have very complex models and you don't want your swagger page to be overly-complex.
1122    * @return
1123    *    This object with references resolved.
1124    *    <br>May or may not be the same object.
1125    */
1126   public SchemaInfo resolveRefs(Swagger swagger, Deque<String> refStack, int maxDepth) {
1127
1128      if (ref != null) {
1129         if (refStack.contains(ref) || refStack.size() >= maxDepth)
1130            return this;
1131         refStack.addLast(ref);
1132         SchemaInfo r = swagger.findRef(ref, SchemaInfo.class).resolveRefs(swagger, refStack, maxDepth);
1133         refStack.removeLast();
1134         return r;
1135      }
1136
1137      if (items != null)
1138         items = items.resolveRefs(swagger, refStack, maxDepth);
1139
1140      if (properties != null)
1141         properties.entrySet().forEach(x -> x.setValue(x.getValue().resolveRefs(swagger, refStack, maxDepth)));
1142
1143      if (additionalProperties != null)
1144         additionalProperties = additionalProperties.resolveRefs(swagger, refStack, maxDepth);
1145
1146      this.example = null;
1147
1148      return this;
1149   }
1150}