001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.marshall;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020import static org.apache.juneau.marshall.jsonschema.SchemaUtils.*;
021
022import java.lang.annotation.*;
023import java.util.*;
024import java.util.function.*;
025
026import org.apache.juneau.commons.*;
027import org.apache.juneau.commons.utils.*;
028import org.apache.juneau.marshall.collections.*;
029import org.apache.juneau.marshall.parser.*;
030
031/**
032 * Utility classes and methods for the {@link Schema @Schema} annotation.
033 *
034 */
035@SuppressWarnings({
036   "java:S100", // Builder methods const_/default_/else_/enum_/if_ etc. are named after JSON Schema keywords that are Java reserved words, hence the trailing underscore
037   "java:S116", // Field names intentionally match JSON property names
038   "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants
039})
040public class SchemaAnnotation {
041
042   /**
043    * Prevents instantiation.
044    */
045   private SchemaAnnotation() {}
046
047   /**
048    * Builder class.
049    *
050    * <h5 class='section'>See Also:</h5><ul>
051    *    <li class='jm'>{@link MarshallingContext.Builder#annotations(Annotation...)}
052    * </ul>
053    */
054   public static class Builder extends AnnotationObject.Builder {
055
056      private boolean aev;
057      private boolean allowEmptyValue;
058      private boolean emax;
059      private boolean emin;
060      private boolean ignore;
061      private boolean r;
062      private boolean readOnly;
063      private boolean required;
064      private boolean ro;
065      private boolean sie;
066      private boolean skipIfEmpty;
067      private boolean ui;
068      private boolean uniqueItems;
069      private ExternalDocs externalDocs = ExternalDocsAnnotation.DEFAULT;
070      private Items items = ItemsAnnotation.DEFAULT;
071      private long maxi = -1;
072      private long maxItems = -1;
073      private long maxl = -1;
074      private long maxLength = -1;
075      private long maxp = -1;
076      private long maxProperties = -1;
077      private long mini = -1;
078      private long minItems = -1;
079      private long minl = -1;
080      private long minLength = -1;
081      private long minp = -1;
082      private long minProperties = -1;
083      private String $ref = "";
084      private String cf = "";
085      private String collectionFormat = "";
086      private String discriminator = "";
087      private String f = "";
088      private String format = "";
089      private String max = "";
090      private String maximum = "";
091      private String min = "";
092      private String minimum = "";
093      private String mo = "";
094      private String multipleOf = "";
095      private String p = "";
096      private String pattern = "";
097      private String su = "";
098      private String summary = "";
099      private String t = "";
100      private String title = "";
101      private String type = "";
102      private String[] default_ = {};
103      private String[] enum_ = {};
104      private String[] allOf = {};
105      private String[] d = {};
106      private String[] description = {};
107      private String[] df = {};
108      private String[] e = {};
109      private String[] xml = {};
110      private boolean deprecatedProperty;
111      private String $id = "";
112      private String contentMediaType = "";
113      private String contentEncoding = "";
114      private String exclusiveMaximumValue = "";
115      private String exclusiveMinimumValue = "";
116      private String[] const_ = {};
117      private String[] examples = {};
118      private String[] $comment = {};
119      private String[] prefixItems = {};
120      private String[] unevaluatedItems = {};
121      private String[] unevaluatedProperties = {};
122      private String[] dependentSchemas = {};
123      private String[] dependentRequired = {};
124      private String[] if_ = {};
125      private String[] then_ = {};
126      private String[] else_ = {};
127      private String[] $defs = {};
128
129      /**
130       * Constructor.
131       */
132      protected Builder() {
133         super(Schema.class);
134      }
135
136      /**
137       * Sets the {@link Schema#const_} property on this annotation.
138       *
139       * @param value The new value for this property.
140       * @return This object.
141       */
142      public Builder const_(String...value) {
143         const_ = value;
144         return this;
145      }
146
147      /**
148       * Sets the {@link Schema#default_} property on this annotation.
149       *
150       * @param value The new value for this property.
151       * @return This object.
152       */
153      public Builder default_(String...value) {
154         default_ = value;
155         return this;
156      }
157
158      /**
159       * Sets the {@link Schema#else_} property on this annotation.
160       *
161       * @param value The new value for this property.
162       * @return This object.
163       */
164      public Builder else_(String...value) {
165         else_ = value;
166         return this;
167      }
168
169      /**
170       * Sets the {@link Schema#enum_} property on this annotation.
171       *
172       * @param value The new value for this property.
173       * @return This object.
174       */
175      public Builder enum_(String...value) {
176         enum_ = value;
177         return this;
178      }
179
180      /**
181       * Sets the {@link Schema#if_} property on this annotation.
182       *
183       * @param value The new value for this property.
184       * @return This object.
185       */
186      public Builder if_(String...value) {
187         if_ = value;
188         return this;
189      }
190
191      /**
192       * Sets the {@link Schema#then_} property on this annotation.
193       *
194       * @param value The new value for this property.
195       * @return This object.
196       */
197      public Builder then_(String...value) {
198         then_ = value;
199         return this;
200      }
201
202      /**
203       * Sets the {@link Schema#$comment} property on this annotation.
204       *
205       * @param value The new value for this property.
206       * @return This object.
207       */
208      public Builder $comment(String...value) {
209         this.$comment = value;
210         return this;
211      }
212
213      /**
214       * Sets the {@link Schema#$defs} property on this annotation.
215       *
216       * @param value The new value for this property.
217       * @return This object.
218       */
219      public Builder $defs(String...value) {
220         this.$defs = value;
221         return this;
222      }
223
224      /**
225       * Sets the {@link Schema#$id} property on this annotation.
226       *
227       * @param value The new value for this property.
228       * @return This object.
229       */
230      public Builder $id(String value) {
231         this.$id = value;
232         return this;
233      }
234
235      /**
236       * Sets the {@link Schema#$ref} property on this annotation.
237       *
238       * @param value The new value for this property.
239       * @return This object.
240       */
241      public Builder $ref(String value) {
242         this.$ref = value;
243         return this;
244      }
245
246      /**
247       * Sets the {@link Schema#aev} property on this annotation.
248       *
249       * @param value The new value for this property.
250       * @return This object.
251       */
252      public Builder aev(boolean value) {
253         aev = value;
254         return this;
255      }
256
257      /**
258       * Sets the {@link Schema#allOf} property on this annotation.
259       *
260       * @param value The new value for this property.
261       * @return This object.
262       */
263      public Builder allOf(String...value) {
264         allOf = value;
265         return this;
266      }
267
268      /**
269       * Sets the {@link Schema#allowEmptyValue} property on this annotation.
270       *
271       * @param value The new value for this property.
272       * @return This object.
273       */
274      public Builder allowEmptyValue(boolean value) {
275         allowEmptyValue = value;
276         return this;
277      }
278
279      /**
280       * Instantiates a new {@link Schema @Schema} object initialized with this builder.
281       *
282       * @return A new {@link Schema @Schema} object.
283       */
284      public Schema build() {
285         return new Object(this);
286      }
287
288      /**
289       * Sets the description property on this annotation.
290       *
291       * @param value The new value for this property.
292       * @return This object.
293       */
294      public Builder description(String...value) {
295         description = value;
296         return this;
297      }
298
299      /**
300       * Sets the {@link Schema#cf} property on this annotation.
301       *
302       * @param value The new value for this property.
303       * @return This object.
304       */
305      public Builder cf(String value) {
306         cf = value;
307         return this;
308      }
309
310      /**
311       * Sets the {@link Schema#collectionFormat} property on this annotation.
312       *
313       * @param value The new value for this property.
314       * @return This object.
315       */
316      public Builder collectionFormat(String value) {
317         collectionFormat = value;
318         return this;
319      }
320
321      /**
322       * Sets the {@link Schema#contentEncoding} property on this annotation.
323       *
324       * @param value The new value for this property.
325       * @return This object.
326       */
327      public Builder contentEncoding(String value) {
328         contentEncoding = value;
329         return this;
330      }
331
332      /**
333       * Sets the {@link Schema#contentMediaType} property on this annotation.
334       *
335       * @param value The new value for this property.
336       * @return This object.
337       */
338      public Builder contentMediaType(String value) {
339         contentMediaType = value;
340         return this;
341      }
342
343      /**
344       * Sets the {@link Schema#d} property on this annotation.
345       *
346       * @param value The new value for this property.
347       * @return This object.
348       */
349      public Builder d(String...value) {
350         d = value;
351         return this;
352      }
353
354      /**
355       * Sets the {@link Schema#dependentRequired} property on this annotation.
356       *
357       * @param value The new value for this property.
358       * @return This object.
359       */
360      public Builder dependentRequired(String...value) {
361         dependentRequired = value;
362         return this;
363      }
364
365      /**
366       * Sets the {@link Schema#dependentSchemas} property on this annotation.
367       *
368       * @param value The new value for this property.
369       * @return This object.
370       */
371      public Builder dependentSchemas(String...value) {
372         dependentSchemas = value;
373         return this;
374      }
375
376      /**
377       * Sets the {@link Schema#deprecated_()} property on this annotation.
378       *
379       * @param value The new value for this property.
380       * @return This object.
381       */
382      public Builder deprecatedProperty(boolean value) {
383         deprecatedProperty = value;
384         return this;
385      }
386
387      /**
388       * Sets the {@link Schema#df} property on this annotation.
389       *
390       * @param value The new value for this property.
391       * @return This object.
392       */
393      public Builder df(String...value) {
394         df = value;
395         return this;
396      }
397
398      /**
399       * Sets the {@link Schema#discriminator} property on this annotation.
400       *
401       * @param value The new value for this property.
402       * @return This object.
403       */
404      public Builder discriminator(String value) {
405         discriminator = value;
406         return this;
407      }
408
409      /**
410       * Sets the {@link Schema#e} property on this annotation.
411       *
412       * @param value The new value for this property.
413       * @return This object.
414       */
415      public Builder e(String...value) {
416         e = value;
417         return this;
418      }
419
420      /**
421       * Sets the {@link Schema#emax} property on this annotation.
422       *
423       * @param value The new value for this property.
424       * @return This object.
425       */
426      public Builder emax(boolean value) {
427         emax = value;
428         return this;
429      }
430
431      /**
432       * Sets the {@link Schema#emin} property on this annotation.
433       *
434       * @param value The new value for this property.
435       * @return This object.
436       */
437      public Builder emin(boolean value) {
438         emin = value;
439         return this;
440      }
441
442      /**
443       * Sets the {@link Schema#examples} property on this annotation.
444       *
445       * @param value The new value for this property.
446       * @return This object.
447       */
448      public Builder examples(String...value) {
449         examples = value;
450         return this;
451      }
452
453      /**
454       * Sets the {@link Schema#exclusiveMaximumValue} property on this annotation.
455       *
456       * @param value The new value for this property.
457       * @return This object.
458       */
459      public Builder exclusiveMaximumValue(String value) {
460         exclusiveMaximumValue = value;
461         return this;
462      }
463
464      /**
465       * Sets the {@link Schema#exclusiveMinimumValue} property on this annotation.
466       *
467       * @param value The new value for this property.
468       * @return This object.
469       */
470      public Builder exclusiveMinimumValue(String value) {
471         exclusiveMinimumValue = value;
472         return this;
473      }
474
475      /**
476       * Sets the {@link Schema#externalDocs} property on this annotation.
477       *
478       * @param value The new value for this property.
479       * @return This object.
480       */
481      public Builder externalDocs(ExternalDocs value) {
482         externalDocs = value;
483         return this;
484      }
485
486      /**
487       * Sets the {@link Schema#f} property on this annotation.
488       *
489       * @param value The new value for this property.
490       * @return This object.
491       */
492      public Builder f(String value) {
493         f = value;
494         return this;
495      }
496
497      /**
498       * Sets the {@link Schema#format} property on this annotation.
499       *
500       * @param value The new value for this property.
501       * @return This object.
502       */
503      public Builder format(String value) {
504         format = value;
505         return this;
506      }
507
508      /**
509       * Sets the {@link Schema#ignore} property on this annotation.
510       *
511       * @param value The new value for this property.
512       * @return This object.
513       */
514      public Builder ignore(boolean value) {
515         ignore = value;
516         return this;
517      }
518
519      /**
520       * Sets the {@link Schema#items} property on this annotation.
521       *
522       * @param value The new value for this property.
523       * @return This object.
524       */
525      public Builder items(Items value) {
526         items = value;
527         return this;
528      }
529
530      /**
531       * Sets the {@link Schema#max} property on this annotation.
532       *
533       * @param value The new value for this property.
534       * @return This object.
535       */
536      public Builder max(String value) {
537         max = value;
538         return this;
539      }
540
541      /**
542       * Sets the {@link Schema#maxi} property on this annotation.
543       *
544       * @param value The new value for this property.
545       * @return This object.
546       */
547      public Builder maxi(long value) {
548         maxi = value;
549         return this;
550      }
551
552      /**
553       * Sets the {@link Schema#maximum} property on this annotation.
554       *
555       * @param value The new value for this property.
556       * @return This object.
557       */
558      public Builder maximum(String value) {
559         maximum = value;
560         return this;
561      }
562
563      /**
564       * Sets the {@link Schema#maxItems} property on this annotation.
565       *
566       * @param value The new value for this property.
567       * @return This object.
568       */
569      public Builder maxItems(long value) {
570         maxItems = value;
571         return this;
572      }
573
574      /**
575       * Sets the {@link Schema#maxl} property on this annotation.
576       *
577       * @param value The new value for this property.
578       * @return This object.
579       */
580      public Builder maxl(long value) {
581         maxl = value;
582         return this;
583      }
584
585      /**
586       * Sets the {@link Schema#maxLength} property on this annotation.
587       *
588       * @param value The new value for this property.
589       * @return This object.
590       */
591      public Builder maxLength(long value) {
592         maxLength = value;
593         return this;
594      }
595
596      /**
597       * Sets the {@link Schema#maxp} property on this annotation.
598       *
599       * @param value The new value for this property.
600       * @return This object.
601       */
602      public Builder maxp(long value) {
603         maxp = value;
604         return this;
605      }
606
607      /**
608       * Sets the {@link Schema#maxProperties} property on this annotation.
609       *
610       * @param value The new value for this property.
611       * @return This object.
612       */
613      public Builder maxProperties(long value) {
614         maxProperties = value;
615         return this;
616      }
617
618      /**
619       * Sets the {@link Schema#min} property on this annotation.
620       *
621       * @param value The new value for this property.
622       * @return This object.
623       */
624      public Builder min(String value) {
625         min = value;
626         return this;
627      }
628
629      /**
630       * Sets the {@link Schema#mini} property on this annotation.
631       *
632       * @param value The new value for this property.
633       * @return This object.
634       */
635      public Builder mini(long value) {
636         mini = value;
637         return this;
638      }
639
640      /**
641       * Sets the {@link Schema#minimum} property on this annotation.
642       *
643       * @param value The new value for this property.
644       * @return This object.
645       */
646      public Builder minimum(String value) {
647         minimum = value;
648         return this;
649      }
650
651      /**
652       * Sets the {@link Schema#minItems} property on this annotation.
653       *
654       * @param value The new value for this property.
655       * @return This object.
656       */
657      public Builder minItems(long value) {
658         minItems = value;
659         return this;
660      }
661
662      /**
663       * Sets the {@link Schema#minl} property on this annotation.
664       *
665       * @param value The new value for this property.
666       * @return This object.
667       */
668      public Builder minl(long value) {
669         minl = value;
670         return this;
671      }
672
673      /**
674       * Sets the {@link Schema#minLength} property on this annotation.
675       *
676       * @param value The new value for this property.
677       * @return This object.
678       */
679      public Builder minLength(long value) {
680         minLength = value;
681         return this;
682      }
683
684      /**
685       * Sets the {@link Schema#minp} property on this annotation.
686       *
687       * @param value The new value for this property.
688       * @return This object.
689       */
690      public Builder minp(long value) {
691         minp = value;
692         return this;
693      }
694
695      /**
696       * Sets the {@link Schema#minProperties} property on this annotation.
697       *
698       * @param value The new value for this property.
699       * @return This object.
700       */
701      public Builder minProperties(long value) {
702         minProperties = value;
703         return this;
704      }
705
706      /**
707       * Sets the {@link Schema#mo} property on this annotation.
708       *
709       * @param value The new value for this property.
710       * @return This object.
711       */
712      public Builder mo(String value) {
713         mo = value;
714         return this;
715      }
716
717      /**
718       * Sets the {@link Schema#multipleOf} property on this annotation.
719       *
720       * @param value The new value for this property.
721       * @return This object.
722       */
723      public Builder multipleOf(String value) {
724         multipleOf = value;
725         return this;
726      }
727
728      // -----------------------------------------------------------------------------------------------------------------
729      // JSON Schema Draft 2020-12 property setters
730      // -----------------------------------------------------------------------------------------------------------------
731
732      /**
733       * Sets the {@link Schema#p} property on this annotation.
734       *
735       * @param value The new value for this property.
736       * @return This object.
737       */
738      public Builder p(String value) {
739         p = value;
740         return this;
741      }
742
743      /**
744       * Sets the {@link Schema#pattern} property on this annotation.
745       *
746       * @param value The new value for this property.
747       * @return This object.
748       */
749      public Builder pattern(String value) {
750         pattern = value;
751         return this;
752      }
753
754      /**
755       * Sets the {@link Schema#prefixItems} property on this annotation.
756       *
757       * @param value The new value for this property.
758       * @return This object.
759       */
760      public Builder prefixItems(String...value) {
761         prefixItems = value;
762         return this;
763      }
764
765      /**
766       * Sets the {@link Schema#r} property on this annotation.
767       *
768       * @param value The new value for this property.
769       * @return This object.
770       */
771      public Builder r(boolean value) {
772         r = value;
773         return this;
774      }
775
776      /**
777       * Sets the {@link Schema#readOnly} property on this annotation.
778       *
779       * @param value The new value for this property.
780       * @return This object.
781       */
782      public Builder readOnly(boolean value) {
783         readOnly = value;
784         return this;
785      }
786
787      /**
788       * Sets the {@link Schema#required} property on this annotation.
789       *
790       * @param value The new value for this property.
791       * @return This object.
792       */
793      public Builder required(boolean value) {
794         required = value;
795         return this;
796      }
797
798      /**
799       * Sets the {@link Schema#ro} property on this annotation.
800       *
801       * @param value The new value for this property.
802       * @return This object.
803       */
804      public Builder ro(boolean value) {
805         ro = value;
806         return this;
807      }
808
809      /**
810       * Sets the {@link Schema#sie} property on this annotation.
811       *
812       * @param value The new value for this property.
813       * @return This object.
814       */
815      public Builder sie(boolean value) {
816         sie = value;
817         return this;
818      }
819
820      /**
821       * Sets the {@link Schema#skipIfEmpty} property on this annotation.
822       *
823       * @param value The new value for this property.
824       * @return This object.
825       */
826      public Builder skipIfEmpty(boolean value) {
827         skipIfEmpty = value;
828         return this;
829      }
830
831      /**
832       * Sets the {@link Schema#su} property on this annotation.
833       *
834       * @param value The new value for this property.
835       * @return This object.
836       * @since 10.0.0
837       */
838      public Builder su(String value) {
839         su = value;
840         return this;
841      }
842
843      /**
844       * Sets the {@link Schema#summary} property on this annotation.
845       *
846       * @param value The new value for this property.
847       * @return This object.
848       * @since 10.0.0
849       */
850      public Builder summary(String value) {
851         summary = value;
852         return this;
853      }
854
855      /**
856       * Sets the {@link Schema#t} property on this annotation.
857       *
858       * @param value The new value for this property.
859       * @return This object.
860       */
861      public Builder t(String value) {
862         t = value;
863         return this;
864      }
865
866      /**
867       * Sets the {@link Schema#title} property on this annotation.
868       *
869       * @param value The new value for this property.
870       * @return This object.
871       */
872      public Builder title(String value) {
873         title = value;
874         return this;
875      }
876
877      /**
878       * Sets the {@link Schema#type} property on this annotation.
879       *
880       * @param value The new value for this property.
881       * @return This object.
882       */
883      public Builder type(String value) {
884         type = value;
885         return this;
886      }
887
888      /**
889       * Sets the {@link Schema#ui} property on this annotation.
890       *
891       * @param value The new value for this property.
892       * @return This object.
893       */
894      public Builder ui(boolean value) {
895         ui = value;
896         return this;
897      }
898
899      /**
900       * Sets the {@link Schema#unevaluatedItems} property on this annotation.
901       *
902       * @param value The new value for this property.
903       * @return This object.
904       */
905      public Builder unevaluatedItems(String...value) {
906         unevaluatedItems = value;
907         return this;
908      }
909
910      /**
911       * Sets the {@link Schema#unevaluatedProperties} property on this annotation.
912       *
913       * @param value The new value for this property.
914       * @return This object.
915       */
916      public Builder unevaluatedProperties(String...value) {
917         unevaluatedProperties = value;
918         return this;
919      }
920
921      /**
922       * Sets the {@link Schema#uniqueItems} property on this annotation.
923       *
924       * @param value The new value for this property.
925       * @return This object.
926       */
927      public Builder uniqueItems(boolean value) {
928         uniqueItems = value;
929         return this;
930      }
931
932      /**
933       * Sets the {@link Schema#xml} property on this annotation.
934       *
935       * @param value The new value for this property.
936       * @return This object.
937       */
938      public Builder xml(String...value) {
939         xml = value;
940         return this;
941      }
942
943   }
944
945   @SuppressWarnings({
946      "java:S2160" // equals() inherited from AnnotationObject compares all annotation interface methods; subclass fields are accessed via those methods
947   })
948   private static class Object extends AnnotationObject implements Schema {
949
950      private final String[] description;
951      private final boolean aev;
952      private final boolean allowEmptyValue;
953      private final boolean emax;
954      private final boolean emin;
955      private final boolean uniqueItems;
956      private final boolean ui;
957      private final boolean required;
958      private final boolean r;
959      private final boolean readOnly;
960      private final boolean ro;
961      private final boolean sie;
962      private final boolean skipIfEmpty;
963      private final boolean ignore;
964      private final ExternalDocs externalDocs;
965      private final Items items;
966      private final long maxLength;
967      private final long maxl;
968      private final long minLength;
969      private final long minl;
970      private final long maxItems;
971      private final long maxi;
972      private final long minItems;
973      private final long mini;
974      private final long maxProperties;
975      private final long maxp;
976      private final long minProperties;
977      private final long minp;
978      private final String $ref;
979      private final String format;
980      private final String f;
981      private final String title;
982      private final String multipleOf;
983      private final String mo;
984      private final String maximum;
985      private final String max;
986      private final String minimum;
987      private final String min;
988      private final String pattern;
989      private final String p;
990      private final String su;
991      private final String summary;
992      private final String type;
993      private final String t;
994      private final String collectionFormat;
995      private final String cf;
996      private final String discriminator;
997      private final String[] d;
998      private final String[] default_;
999      private final String[] df;
1000      private final String[] enum_;
1001      private final String[] e;
1002      private final String[] allOf;
1003      private final String[] xml;
1004      // JSON Schema Draft 2020-12 fields
1005      private final boolean deprecatedProperty;
1006      private final String $id;
1007      private final String contentMediaType;
1008      private final String contentEncoding;
1009      private final String exclusiveMaximumValue;
1010      private final String exclusiveMinimumValue;
1011      private final String[] const_;
1012      private final String[] examples;
1013      private final String[] $comment;
1014      private final String[] prefixItems;
1015      private final String[] unevaluatedItems;
1016      private final String[] unevaluatedProperties;
1017      private final String[] dependentSchemas;
1018      private final String[] dependentRequired;
1019      private final String[] if_;
1020      private final String[] then_;
1021      private final String[] else_;
1022      private final String[] $defs;
1023
1024      Object(SchemaAnnotation.Builder b) {
1025         super(b);
1026         description = cp(b.description);
1027         $ref = b.$ref;
1028         default_ = cp(b.default_);
1029         enum_ = cp(b.enum_);
1030         allOf = cp(b.allOf);
1031         aev = b.aev;
1032         allowEmptyValue = b.allowEmptyValue;
1033         cf = b.cf;
1034         collectionFormat = b.collectionFormat;
1035         d = cp(b.d);
1036         df = cp(b.df);
1037         discriminator = b.discriminator;
1038         e = cp(b.e);
1039         emax = b.emax;
1040         emin = b.emin;
1041         externalDocs = b.externalDocs;
1042         f = b.f;
1043         format = b.format;
1044         ignore = b.ignore;
1045         items = b.items;
1046         max = b.max;
1047         maxi = b.maxi;
1048         maximum = b.maximum;
1049         maxItems = b.maxItems;
1050         maxl = b.maxl;
1051         maxLength = b.maxLength;
1052         maxp = b.maxp;
1053         maxProperties = b.maxProperties;
1054         min = b.min;
1055         mini = b.mini;
1056         minimum = b.minimum;
1057         minItems = b.minItems;
1058         minl = b.minl;
1059         minLength = b.minLength;
1060         minp = b.minp;
1061         minProperties = b.minProperties;
1062         mo = b.mo;
1063         multipleOf = b.multipleOf;
1064         p = b.p;
1065         pattern = b.pattern;
1066         r = b.r;
1067         readOnly = b.readOnly;
1068         required = b.required;
1069         ro = b.ro;
1070         sie = b.sie;
1071         skipIfEmpty = b.skipIfEmpty;
1072         su = b.su;
1073         summary = b.summary;
1074         t = b.t;
1075         title = b.title;
1076         type = b.type;
1077         ui = b.ui;
1078         uniqueItems = b.uniqueItems;
1079         xml = cp(b.xml);
1080         deprecatedProperty = b.deprecatedProperty;
1081         $id = b.$id;
1082         contentMediaType = b.contentMediaType;
1083         contentEncoding = b.contentEncoding;
1084         exclusiveMaximumValue = b.exclusiveMaximumValue;
1085         exclusiveMinimumValue = b.exclusiveMinimumValue;
1086         const_ = cp(b.const_);
1087         examples = cp(b.examples);
1088         $comment = cp(b.$comment);
1089         prefixItems = cp(b.prefixItems);
1090         unevaluatedItems = cp(b.unevaluatedItems);
1091         unevaluatedProperties = cp(b.unevaluatedProperties);
1092         dependentSchemas = cp(b.dependentSchemas);
1093         dependentRequired = cp(b.dependentRequired);
1094         if_ = cp(b.if_);
1095         then_ = cp(b.then_);
1096         else_ = cp(b.else_);
1097         $defs = cp(b.$defs);
1098      }
1099
1100      @Override /* Overridden from Schema */
1101      public String[] const_() {
1102         return const_;
1103      }
1104
1105      @Override /* Overridden from Schema */
1106      public String[] default_() {
1107         return default_;
1108      }
1109
1110      @Override /* Overridden from Schema */
1111      public String[] else_() {
1112         return else_;
1113      }
1114
1115      @Override /* Overridden from Schema */
1116      public String[] enum_() {
1117         return enum_;
1118      }
1119
1120      @Override /* Overridden from Schema */
1121      public String[] if_() {
1122         return if_;
1123      }
1124
1125      @Override /* Overridden from Schema */
1126      public String[] then_() {
1127         return then_;
1128      }
1129
1130      @Override /* Overridden from Schema */
1131      public String[] $comment() {
1132         return $comment;
1133      }
1134
1135      @Override /* Overridden from Schema */
1136      public String[] $defs() {
1137         return $defs;
1138      }
1139
1140      @Override /* Overridden from Schema */
1141      public String $id() {
1142         return $id;
1143      }
1144
1145      @Override /* Overridden from Schema */
1146      public String $ref() {
1147         return $ref;
1148      }
1149
1150      @Override /* Overridden from Schema */
1151      public boolean aev() {
1152         return aev;
1153      }
1154
1155      @Override /* Overridden from Schema */
1156      public String[] allOf() {
1157         return allOf;
1158      }
1159
1160      @Override /* Overridden from Schema */
1161      public boolean allowEmptyValue() {
1162         return allowEmptyValue;
1163      }
1164
1165      @Override /* Overridden from Schema */
1166      public String cf() {
1167         return cf;
1168      }
1169
1170      @Override /* Overridden from Schema */
1171      public String collectionFormat() {
1172         return collectionFormat;
1173      }
1174
1175      @Override /* Overridden from Schema */
1176      public String contentEncoding() {
1177         return contentEncoding;
1178      }
1179
1180      @Override /* Overridden from Schema */
1181      public String contentMediaType() {
1182         return contentMediaType;
1183      }
1184
1185      @Override /* Overridden from Schema */
1186      public String[] d() {
1187         return d;
1188      }
1189
1190      @Override /* Overridden from Schema */
1191      public String[] dependentRequired() {
1192         return dependentRequired;
1193      }
1194
1195      @Override /* Overridden from Schema */
1196      public String[] dependentSchemas() {
1197         return dependentSchemas;
1198      }
1199
1200      @Override /* Overridden from Schema */
1201      public boolean deprecated_() {
1202         return deprecatedProperty;
1203      }
1204
1205      @Override /* Overridden from Schema */
1206      public String[] df() {
1207         return df;
1208      }
1209
1210      @Override /* Overridden from Schema */
1211      public String discriminator() {
1212         return discriminator;
1213      }
1214
1215      @Override /* Overridden from Schema */
1216      public String[] e() {
1217         return e;
1218      }
1219
1220      @Override /* Overridden from Schema */
1221      public boolean emax() {
1222         return emax;
1223      }
1224
1225      @Override /* Overridden from Schema */
1226      public boolean emin() {
1227         return emin;
1228      }
1229
1230      @Override /* Overridden from Schema */
1231      public String[] examples() {
1232         return examples;
1233      }
1234
1235      @Override /* Overridden from Schema */
1236      public String exclusiveMaximumValue() {
1237         return exclusiveMaximumValue;
1238      }
1239
1240      @Override /* Overridden from Schema */
1241      public String exclusiveMinimumValue() {
1242         return exclusiveMinimumValue;
1243      }
1244
1245      @Override /* Overridden from Schema */
1246      public ExternalDocs externalDocs() {
1247         return externalDocs;
1248      }
1249
1250      @Override /* Overridden from Schema */
1251      public String f() {
1252         return f;
1253      }
1254
1255      @Override /* Overridden from Schema */
1256      public String format() {
1257         return format;
1258      }
1259
1260      @Override /* Overridden from Schema */
1261      public boolean ignore() {
1262         return ignore;
1263      }
1264
1265      @Override /* Overridden from Schema */
1266      public Items items() {
1267         return items;
1268      }
1269
1270      @Override /* Overridden from Schema */
1271      public String max() {
1272         return max;
1273      }
1274
1275      @Override /* Overridden from Schema */
1276      public long maxi() {
1277         return maxi;
1278      }
1279
1280      @Override /* Overridden from Schema */
1281      public String maximum() {
1282         return maximum;
1283      }
1284
1285      @Override /* Overridden from Schema */
1286      public long maxItems() {
1287         return maxItems;
1288      }
1289
1290      @Override /* Overridden from Schema */
1291      public long maxl() {
1292         return maxl;
1293      }
1294
1295      @Override /* Overridden from Schema */
1296      public long maxLength() {
1297         return maxLength;
1298      }
1299
1300      @Override /* Overridden from Schema */
1301      public long maxp() {
1302         return maxp;
1303      }
1304
1305      @Override /* Overridden from Schema */
1306      public long maxProperties() {
1307         return maxProperties;
1308      }
1309
1310      @Override /* Overridden from Schema */
1311      public String min() {
1312         return min;
1313      }
1314
1315      @Override /* Overridden from Schema */
1316      public long mini() {
1317         return mini;
1318      }
1319
1320      @Override /* Overridden from Schema */
1321      public String minimum() {
1322         return minimum;
1323      }
1324
1325      @Override /* Overridden from Schema */
1326      public long minItems() {
1327         return minItems;
1328      }
1329
1330      @Override /* Overridden from Schema */
1331      public long minl() {
1332         return minl;
1333      }
1334
1335      @Override /* Overridden from Schema */
1336      public long minLength() {
1337         return minLength;
1338      }
1339
1340      @Override /* Overridden from Schema */
1341      public long minp() {
1342         return minp;
1343      }
1344
1345      @Override /* Overridden from Schema */
1346      public long minProperties() {
1347         return minProperties;
1348      }
1349
1350      @Override /* Overridden from Schema */
1351      public String mo() {
1352         return mo;
1353      }
1354
1355      @Override /* Overridden from Schema */
1356      public String multipleOf() {
1357         return multipleOf;
1358      }
1359
1360      // -----------------------------------------------------------------------------------------------------------------
1361      // JSON Schema Draft 2020-12 property getters
1362      // -----------------------------------------------------------------------------------------------------------------
1363
1364      @Override /* Overridden from Schema */
1365      public String p() {
1366         return p;
1367      }
1368
1369      @Override /* Overridden from Schema */
1370      public String pattern() {
1371         return pattern;
1372      }
1373
1374      @Override /* Overridden from Schema */
1375      public String[] prefixItems() {
1376         return prefixItems;
1377      }
1378
1379      @Override /* Overridden from Schema */
1380      public boolean r() {
1381         return r;
1382      }
1383
1384      @Override /* Overridden from Schema */
1385      public boolean readOnly() {
1386         return readOnly;
1387      }
1388
1389      @Override /* Overridden from Schema */
1390      public boolean required() {
1391         return required;
1392      }
1393
1394      @Override /* Overridden from Schema */
1395      public boolean ro() {
1396         return ro;
1397      }
1398
1399      @Override /* Overridden from Schema */
1400      public boolean sie() {
1401         return sie;
1402      }
1403
1404      @Override /* Overridden from Schema */
1405      public boolean skipIfEmpty() {
1406         return skipIfEmpty;
1407      }
1408
1409      @Override /* Overridden from Schema */
1410      public String su() {
1411         return su;
1412      }
1413
1414      @Override /* Overridden from Schema */
1415      public String summary() {
1416         return summary;
1417      }
1418
1419      @Override /* Overridden from Schema */
1420      public String t() {
1421         return t;
1422      }
1423
1424      @Override /* Overridden from Schema */
1425      public String title() {
1426         return title;
1427      }
1428
1429      @Override /* Overridden from Schema */
1430      public String type() {
1431         return type;
1432      }
1433
1434      @Override /* Overridden from Schema */
1435      public boolean ui() {
1436         return ui;
1437      }
1438
1439      @Override /* Overridden from Schema */
1440      public String[] unevaluatedItems() {
1441         return unevaluatedItems;
1442      }
1443
1444      @Override /* Overridden from Schema */
1445      public String[] unevaluatedProperties() {
1446         return unevaluatedProperties;
1447      }
1448
1449      @Override /* Overridden from Schema */
1450      public boolean uniqueItems() {
1451         return uniqueItems;
1452      }
1453
1454      @Override /* Overridden from Schema */
1455      public String[] xml() {
1456         return xml;
1457      }
1458
1459      @Override /* Overridden from annotation */
1460      public String[] description() {
1461         return description;
1462      }
1463   }
1464
1465   /** Default value */
1466   public static final Schema DEFAULT = create().build();
1467
1468   /**
1469    * Converts the specified <ja>@Schema</ja> annotation into a generic map.
1470    *
1471    * @param a The annotation instance.  Can be <jk>null</jk> (returns an empty map).
1472    * @return The schema converted to a map, or an empty map if the annotation was null.
1473    * @throws ParseException Malformed input encountered.
1474    */
1475   public static JsonMap asMap(Schema a) throws ParseException {
1476      if (a == null)
1477         return JsonMap.EMPTY_MAP;
1478      var m = new JsonMap();
1479      if (SchemaAnnotation.empty(a))
1480         return m;
1481      Predicate<String> ne = Shorts::ine;
1482      Predicate<Collection<?>> nec = Shorts::ine;
1483      Predicate<Map<?,?>> nem = Shorts::ine;
1484      Predicate<Boolean> nf = ObjectUtils::isTrue;
1485      Predicate<Long> nm1 = Shorts::nm1;
1486
1487      // Handle exclusiveMaximum with Draft 2020-12 fallback
1488      String exclusiveMaximumValue;
1489      if (ne.test(a.exclusiveMaximumValue())) {
1490         exclusiveMaximumValue = a.exclusiveMaximumValue();
1491      } else if (a.emax()) {
1492         exclusiveMaximumValue = "true";
1493      } else {
1494         exclusiveMaximumValue = null;
1495      }
1496
1497      // Handle exclusiveMinimum with Draft 2020-12 fallback
1498      String exclusiveMinimumValue;
1499      if (ne.test(a.exclusiveMinimumValue())) {
1500         exclusiveMinimumValue = a.exclusiveMinimumValue();
1501      } else if (a.emin()) {
1502         exclusiveMinimumValue = "true";
1503      } else {
1504         exclusiveMinimumValue = null;
1505      }
1506
1507      // @formatter:off
1508      return m
1509         .appendIf(ne, "allOf", joinnl(a.allOf()))
1510         .appendFirst(ne, "collectionFormat", a.collectionFormat(), a.cf())
1511         .appendIf(ne, "default", joinnl(a.default_(), a.df()))
1512         .appendIf(ne, "discriminator", a.discriminator())
1513         .appendIf(ne, "description", joinnl(a.description(), a.d()))
1514         .appendFirst(nec, "enum", parseSet(a.enum_()), parseSet(a.e()))
1515         .appendIf(ne, "exclusiveMaximum", exclusiveMaximumValue)
1516         .appendIf(ne, "exclusiveMinimum", exclusiveMinimumValue)
1517         .appendIf(nem, "externalDocs", ExternalDocsAnnotation.merge(m.getMap("externalDocs"), a.externalDocs()))
1518         .appendFirst(ne, "format", a.format(), a.f())
1519         .appendIf(ne, "ignore", a.ignore() ? "true" : null)
1520         .appendIf(nem, "items", merge(m.getMap("items"), a.items()))
1521         .appendFirst(ne, "maximum", a.maximum(), a.max())
1522         .appendFirst(nm1, "maxItems", a.maxItems(), a.maxi())
1523         .appendFirst(nm1, "maxLength", a.maxLength(), a.maxl())
1524         .appendFirst(nm1, "maxProperties", a.maxProperties(), a.maxp())
1525         .appendFirst(ne, "minimum", a.minimum(), a.min())
1526         .appendFirst(nm1, "minItems", a.minItems(), a.mini())
1527         .appendFirst(nm1, "minLength", a.minLength(), a.minl())
1528         .appendFirst(nm1, "minProperties", a.minProperties(), a.minp())
1529         .appendFirst(ne, "multipleOf", a.multipleOf(), a.mo())
1530         .appendFirst(ne, "pattern", a.pattern(), a.p())
1531         .appendIf(nf, "readOnly", a.readOnly() || a.ro())
1532         .appendIf(nf, "required", a.required() || a.r())
1533         .appendFirst(ne, "summary", a.summary(), a.su())
1534         .appendIf(ne, "title", a.title())
1535         .appendFirst(ne, "type", a.type(), a.t())
1536         .appendIf(nf, "uniqueItems", a.uniqueItems() || a.ui())
1537         .appendIf(ne, "xml", joinnl(a.xml()))
1538         .appendIf(ne, "$ref", a.$ref())
1539         // JSON Schema Draft 2020-12 properties
1540         .appendIf(ne, "const", joinnl(a.const_()))
1541         .appendIf(nec, "examples", a.examples().length == 0 ? null : l(a.examples()))
1542         .appendIf(ne, "$comment", joinnl(a.$comment()))
1543         .appendIf(nf, "deprecated", a.deprecated_())
1544         .appendIf(ne, "contentMediaType", a.contentMediaType())
1545         .appendIf(ne, "contentEncoding", a.contentEncoding())
1546         .appendIf(ne, "prefixItems", joinnl(a.prefixItems()))
1547         .appendIf(ne, "unevaluatedItems", joinnl(a.unevaluatedItems()))
1548         .appendIf(ne, "unevaluatedProperties", joinnl(a.unevaluatedProperties()))
1549         .appendIf(ne, "dependentSchemas", joinnl(a.dependentSchemas()))
1550         .appendIf(ne, "dependentRequired", joinnl(a.dependentRequired()))
1551         .appendIf(ne, "if", joinnl(a.if_()))
1552         .appendIf(ne, "then", joinnl(a.then_()))
1553         .appendIf(ne, "else", joinnl(a.else_()))
1554         .appendIf(ne, "$defs", joinnl(a.$defs()))
1555         .appendIf(ne, "$id", a.$id())
1556      ;
1557      // @formatter:on
1558   }
1559
1560   /**
1561    * Instantiates a new builder for this class.
1562    *
1563    * @return A new builder object.
1564    */
1565   public static Builder create() {
1566      return new Builder();
1567   }
1568
1569   /**
1570    * Returns <jk>true</jk> if the specified annotation contains all default values.
1571    *
1572    * @param a The annotation to check. Can be <jk>null</jk> (returns <jk>true</jk>).
1573    * @return <jk>true</jk> if the specified annotation contains all default values.
1574    */
1575   public static boolean empty(Schema a) {
1576      return a == null || DEFAULT.equals(a);
1577   }
1578
1579   private static JsonMap merge(JsonMap m, Items a) throws ParseException {
1580      if (ItemsAnnotation.empty(a))
1581         return m;
1582      if (m == null)
1583         m = new JsonMap();
1584      Predicate<String> ne = Shorts::ine;
1585      Predicate<Collection<?>> nec = Shorts::ine;
1586      Predicate<Map<?,?>> nem = Shorts::ine;
1587      Predicate<Boolean> nf = ObjectUtils::isTrue;
1588      Predicate<Long> nm1 = Shorts::nm1;
1589      return m.appendFirst(ne, "collectionFormat", a.collectionFormat(), a.cf()).appendIf(ne, "default", joinnl(a.default_(), a.df())).appendFirst(nec, "enum", parseSet(a.enum_()), parseSet(a.e()))
1590         .appendFirst(ne, "format", a.format(), a.f()).appendIf(nf, "exclusiveMaximum", a.exclusiveMaximum() || a.emax()).appendIf(nf, "exclusiveMinimum", a.exclusiveMinimum() || a.emin())
1591         .appendIf(nem, "items", SubItemsAnnotation.merge(m.getMap("items"), a.items())).appendFirst(ne, "maximum", a.maximum(), a.max()).appendFirst(nm1, "maxItems", a.maxItems(), a.maxi())
1592         .appendFirst(nm1, "maxLength", a.maxLength(), a.maxl()).appendFirst(ne, "minimum", a.minimum(), a.min()).appendFirst(nm1, "minItems", a.minItems(), a.mini())
1593         .appendFirst(nm1, "minLength", a.minLength(), a.minl()).appendFirst(ne, "multipleOf", a.multipleOf(), a.mo()).appendFirst(ne, "pattern", a.pattern(), a.p())
1594         .appendIf(nf, "uniqueItems", a.uniqueItems() || a.ui()).appendFirst(ne, "type", a.type(), a.t()).appendIf(ne, "$ref", a.$ref());
1595   }
1596}