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