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 SubItems @SubItems} annotation.
033 *
034 */
035@SuppressWarnings({
036   "java:S100", // Builder/annotation methods such as default_(), enum_() and $ref() use trailing underscore/$ to avoid Java keywords and match JSON Schema names
037   "java:S116", // Field names match JSON Schema property names for API consistency
038   "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants
039})
040public class SubItemsAnnotation {
041
042   /**
043    * Prevents instantiation.
044    */
045   private SubItemsAnnotation() {}
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 String[] description = {};
057      private String $ref = "";
058      private String cf = "";
059      private String collectionFormat = "";
060      private String f = "";
061      private String format = "";
062      private String max = "";
063      private String maximum = "";
064      private String min = "";
065      private String minimum = "";
066      private String mo = "";
067      private String multipleOf = "";
068      private String p = "";
069      private String pattern = "";
070      private String t = "";
071      private String type = "";
072      private long maxItems = -1;
073      private long maxLength = -1;
074      private long maxi = -1;
075      private long maxl = -1;
076      private long minItems = -1;
077      private long minLength = -1;
078      private long mini = -1;
079      private long minl = -1;
080      private boolean emax;
081      private boolean emin;
082      private boolean exclusiveMaximum;
083      private boolean exclusiveMinimum;
084      private boolean ui;
085      private boolean uniqueItems;
086      private String[] default_ = {};
087      private String[] enum_ = {};
088      private String[] df = {};
089      private String[] e = {};
090
091      /**
092       * Constructor.
093       */
094      protected Builder() {
095         super(SubItems.class);
096      }
097
098      /**
099       * Sets the <c>default_</c> property on this annotation.
100       *
101       * @param value The new value for this property.
102       * @return This object.
103       */
104      public Builder default_(String...value) {
105         default_ = value;
106         return this;
107      }
108
109      /**
110       * Sets the <c>enum_</c> property on this annotation.
111       *
112       * @param value The new value for this property.
113       * @return This object.
114       */
115      public Builder enum_(String...value) {
116         enum_ = value;
117         return this;
118      }
119
120      /**
121       * Sets the <c>$ref</c> property on this annotation.
122       *
123       * @param value The new value for this property.
124       * @return This object.
125       */
126      public Builder $ref(String value) {
127         this.$ref = value;
128         return this;
129      }
130
131      /**
132       * Instantiates a new {@link SubItems @SubItems} object initialized with this builder.
133       *
134       * @return A new {@link SubItems @SubItems} object.
135       */
136      public SubItems build() {
137         return new Object(this);
138      }
139
140      /**
141       * Sets the description property on this annotation.
142       *
143       * @param value The new value for this property.
144       * @return This object.
145       */
146      public Builder description(String...value) {
147         description = value;
148         return this;
149      }
150
151      /**
152       * Sets the <c>cf</c> property on this annotation.
153       *
154       * @param value The new value for this property.
155       * @return This object.
156       */
157      public Builder cf(String value) {
158         cf = value;
159         return this;
160      }
161
162      /**
163       * Sets the <c>collectionFormat</c> property on this annotation.
164       *
165       * @param value The new value for this property.
166       * @return This object.
167       */
168      public Builder collectionFormat(String value) {
169         collectionFormat = value;
170         return this;
171      }
172
173      /**
174       * Sets the <c>df</c> property on this annotation.
175       *
176       * @param value The new value for this property.
177       * @return This object.
178       */
179      public Builder df(String...value) {
180         df = value;
181         return this;
182      }
183
184      /**
185       * Sets the <c>e</c> property on this annotation.
186       *
187       * @param value The new value for this property.
188       * @return This object.
189       */
190      public Builder e(String...value) {
191         e = value;
192         return this;
193      }
194
195      /**
196       * Sets the <c>emax</c> property on this annotation.
197       *
198       * @param value The new value for this property.
199       * @return This object.
200       */
201      public Builder emax(boolean value) {
202         emax = value;
203         return this;
204      }
205
206      /**
207       * Sets the <c>emin</c> property on this annotation.
208       *
209       * @param value The new value for this property.
210       * @return This object.
211       */
212      public Builder emin(boolean value) {
213         emin = value;
214         return this;
215      }
216
217      /**
218       * Sets the <c>exclusiveMaximum</c> property on this annotation.
219       *
220       * @param value The new value for this property.
221       * @return This object.
222       */
223      public Builder exclusiveMaximum(boolean value) {
224         exclusiveMaximum = value;
225         return this;
226      }
227
228      /**
229       * Sets the <c>exclusiveMinimum</c> property on this annotation.
230       *
231       * @param value The new value for this property.
232       * @return This object.
233       */
234      public Builder exclusiveMinimum(boolean value) {
235         exclusiveMinimum = value;
236         return this;
237      }
238
239      /**
240       * Sets the <c>f</c> property on this annotation.
241       *
242       * @param value The new value for this property.
243       * @return This object.
244       */
245      public Builder f(String value) {
246         f = value;
247         return this;
248      }
249
250      /**
251       * Sets the <c>format</c> property on this annotation.
252       *
253       * @param value The new value for this property.
254       * @return This object.
255       */
256      public Builder format(String value) {
257         format = value;
258         return this;
259      }
260
261      /**
262       * Sets the <c>max</c> property on this annotation.
263       *
264       * @param value The new value for this property.
265       * @return This object.
266       */
267      public Builder max(String value) {
268         max = value;
269         return this;
270      }
271
272      /**
273       * Sets the <c>maxi</c> property on this annotation.
274       *
275       * @param value The new value for this property.
276       * @return This object.
277       */
278      public Builder maxi(long value) {
279         maxi = value;
280         return this;
281      }
282
283      /**
284       * Sets the <c>maximum</c> property on this annotation.
285       *
286       * @param value The new value for this property.
287       * @return This object.
288       */
289      public Builder maximum(String value) {
290         maximum = value;
291         return this;
292      }
293
294      /**
295       * Sets the <c>maxItems</c> property on this annotation.
296       *
297       * @param value The new value for this property.
298       * @return This object.
299       */
300      public Builder maxItems(long value) {
301         maxItems = value;
302         return this;
303      }
304
305      /**
306       * Sets the <c>maxl</c> property on this annotation.
307       *
308       * @param value The new value for this property.
309       * @return This object.
310       */
311      public Builder maxl(long value) {
312         maxl = value;
313         return this;
314      }
315
316      /**
317       * Sets the <c>maxLength</c> property on this annotation.
318       *
319       * @param value The new value for this property.
320       * @return This object.
321       */
322      public Builder maxLength(long value) {
323         maxLength = value;
324         return this;
325      }
326
327      /**
328       * Sets the <c>min</c> property on this annotation.
329       *
330       * @param value The new value for this property.
331       * @return This object.
332       */
333      public Builder min(String value) {
334         min = value;
335         return this;
336      }
337
338      /**
339       * Sets the <c>mini</c> property on this annotation.
340       *
341       * @param value The new value for this property.
342       * @return This object.
343       */
344      public Builder mini(long value) {
345         mini = value;
346         return this;
347      }
348
349      /**
350       * Sets the <c>minimum</c> property on this annotation.
351       *
352       * @param value The new value for this property.
353       * @return This object.
354       */
355      public Builder minimum(String value) {
356         minimum = value;
357         return this;
358      }
359
360      /**
361       * Sets the <c>minItems</c> property on this annotation.
362       *
363       * @param value The new value for this property.
364       * @return This object.
365       */
366      public Builder minItems(long value) {
367         minItems = value;
368         return this;
369      }
370
371      /**
372       * Sets the <c>minl</c> property on this annotation.
373       *
374       * @param value The new value for this property.
375       * @return This object.
376       */
377      public Builder minl(long value) {
378         minl = value;
379         return this;
380      }
381
382      /**
383       * Sets the <c>minLength</c> property on this annotation.
384       *
385       * @param value The new value for this property.
386       * @return This object.
387       */
388      public Builder minLength(long value) {
389         minLength = value;
390         return this;
391      }
392
393      /**
394       * Sets the <c>mo</c> property on this annotation.
395       *
396       * @param value The new value for this property.
397       * @return This object.
398       */
399      public Builder mo(String value) {
400         mo = value;
401         return this;
402      }
403
404      /**
405       * Sets the <c>multipleOf</c> property on this annotation.
406       *
407       * @param value The new value for this property.
408       * @return This object.
409       */
410      public Builder multipleOf(String value) {
411         multipleOf = value;
412         return this;
413      }
414
415      /**
416       * Sets the <c>p</c> property on this annotation.
417       *
418       * @param value The new value for this property.
419       * @return This object.
420       */
421      public Builder p(String value) {
422         p = value;
423         return this;
424      }
425
426      /**
427       * Sets the <c>pattern</c> property on this annotation.
428       *
429       * @param value The new value for this property.
430       * @return This object.
431       */
432      public Builder pattern(String value) {
433         pattern = value;
434         return this;
435      }
436
437      /**
438       * Sets the <c>t</c> property on this annotation.
439       *
440       * @param value The new value for this property.
441       * @return This object.
442       */
443      public Builder t(String value) {
444         t = value;
445         return this;
446      }
447
448      /**
449       * Sets the <c>type</c> property on this annotation.
450       *
451       * @param value The new value for this property.
452       * @return This object.
453       */
454      public Builder type(String value) {
455         type = value;
456         return this;
457      }
458
459      /**
460       * Sets the <c>ui</c> property on this annotation.
461       *
462       * @param value The new value for this property.
463       * @return This object.
464       */
465      public Builder ui(boolean value) {
466         ui = value;
467         return this;
468      }
469
470      /**
471       * Sets the <c>uniqueItems</c> property on this annotation.
472       *
473       * @param value The new value for this property.
474       * @return This object.
475       */
476      public Builder uniqueItems(boolean value) {
477         uniqueItems = value;
478         return this;
479      }
480
481   }
482
483   @SuppressWarnings({
484      "java:S2160" // equals() inherited from AnnotationObject compares all annotation interface methods; subclass fields are accessed via those methods
485   })
486   private static class Object extends AnnotationObject implements SubItems {
487
488      private final String[] description;
489      private final boolean emax;
490      private final boolean emin;
491      private final boolean exclusiveMaximum;
492      private final boolean exclusiveMinimum;
493      private final boolean ui;
494      private final boolean uniqueItems;
495      private final long maxi;
496      private final long maxItems;
497      private final long maxl;
498      private final long maxLength;
499      private final long mini;
500      private final long minItems;
501      private final long minl;
502      private final long minLength;
503      private final String $ref;
504      private final String cf;
505      private final String collectionFormat;
506      private final String f;
507      private final String format;
508      private final String max;
509      private final String maximum;
510      private final String min;
511      private final String minimum;
512      private final String mo;
513      private final String multipleOf;
514      private final String p;
515      private final String pattern;
516      private final String t;
517      private final String type;
518      private final String[] default_;
519      private final String[] enum_;
520      private final String[] df;
521      private final String[] e;
522
523      Object(SubItemsAnnotation.Builder b) {
524         super(b);
525         description = cp(b.description);
526         $ref = b.$ref;
527         default_ = cp(b.default_);
528         enum_ = cp(b.enum_);
529         cf = b.cf;
530         collectionFormat = b.collectionFormat;
531         df = cp(b.df);
532         e = cp(b.e);
533         emax = b.emax;
534         emin = b.emin;
535         exclusiveMaximum = b.exclusiveMaximum;
536         exclusiveMinimum = b.exclusiveMinimum;
537         f = b.f;
538         format = b.format;
539         max = b.max;
540         maxi = b.maxi;
541         maximum = b.maximum;
542         maxItems = b.maxItems;
543         maxl = b.maxl;
544         maxLength = b.maxLength;
545         min = b.min;
546         mini = b.mini;
547         minimum = b.minimum;
548         minItems = b.minItems;
549         minl = b.minl;
550         minLength = b.minLength;
551         mo = b.mo;
552         multipleOf = b.multipleOf;
553         p = b.p;
554         pattern = b.pattern;
555         t = b.t;
556         type = b.type;
557         ui = b.ui;
558         uniqueItems = b.uniqueItems;
559      }
560
561      @Override /* Overridden from SubItems */
562      public String[] default_() {
563         return default_;
564      }
565
566      @Override /* Overridden from SubItems */
567      public String[] enum_() {
568         return enum_;
569      }
570
571      @Override /* Overridden from SubItems */
572      public String $ref() {
573         return $ref;
574      }
575
576      @Override /* Overridden from SubItems */
577      public String cf() {
578         return cf;
579      }
580
581      @Override /* Overridden from SubItems */
582      public String collectionFormat() {
583         return collectionFormat;
584      }
585
586      @Override /* Overridden from SubItems */
587      public String[] df() {
588         return df;
589      }
590
591      @Override /* Overridden from SubItems */
592      public String[] e() {
593         return e;
594      }
595
596      @Override /* Overridden from SubItems */
597      public boolean emax() {
598         return emax;
599      }
600
601      @Override /* Overridden from SubItems */
602      public boolean emin() {
603         return emin;
604      }
605
606      @Override /* Overridden from SubItems */
607      public boolean exclusiveMaximum() {
608         return exclusiveMaximum;
609      }
610
611      @Override /* Overridden from SubItems */
612      public boolean exclusiveMinimum() {
613         return exclusiveMinimum;
614      }
615
616      @Override /* Overridden from SubItems */
617      public String f() {
618         return f;
619      }
620
621      @Override /* Overridden from SubItems */
622      public String format() {
623         return format;
624      }
625
626      @Override /* Overridden from SubItems */
627      public String max() {
628         return max;
629      }
630
631      @Override /* Overridden from SubItems */
632      public long maxi() {
633         return maxi;
634      }
635
636      @Override /* Overridden from SubItems */
637      public String maximum() {
638         return maximum;
639      }
640
641      @Override /* Overridden from SubItems */
642      public long maxItems() {
643         return maxItems;
644      }
645
646      @Override /* Overridden from SubItems */
647      public long maxl() {
648         return maxl;
649      }
650
651      @Override /* Overridden from SubItems */
652      public long maxLength() {
653         return maxLength;
654      }
655
656      @Override /* Overridden from SubItems */
657      public String min() {
658         return min;
659      }
660
661      @Override /* Overridden from SubItems */
662      public long mini() {
663         return mini;
664      }
665
666      @Override /* Overridden from SubItems */
667      public String minimum() {
668         return minimum;
669      }
670
671      @Override /* Overridden from SubItems */
672      public long minItems() {
673         return minItems;
674      }
675
676      @Override /* Overridden from SubItems */
677      public long minl() {
678         return minl;
679      }
680
681      @Override /* Overridden from SubItems */
682      public long minLength() {
683         return minLength;
684      }
685
686      @Override /* Overridden from SubItems */
687      public String mo() {
688         return mo;
689      }
690
691      @Override /* Overridden from SubItems */
692      public String multipleOf() {
693         return multipleOf;
694      }
695
696      @Override /* Overridden from SubItems */
697      public String p() {
698         return p;
699      }
700
701      @Override /* Overridden from SubItems */
702      public String pattern() {
703         return pattern;
704      }
705
706      @Override /* Overridden from SubItems */
707      public String t() {
708         return t;
709      }
710
711      @Override /* Overridden from SubItems */
712      public String type() {
713         return type;
714      }
715
716      @Override /* Overridden from SubItems */
717      public boolean ui() {
718         return ui;
719      }
720
721      @Override /* Overridden from SubItems */
722      public boolean uniqueItems() {
723         return uniqueItems;
724      }
725
726      @Override /* Overridden from annotation */
727      public String[] description() {
728         return description;
729      }
730   }
731
732   /** Default value */
733   public static final SubItems DEFAULT = create().build();
734
735   /**
736    * Instantiates a new builder for this class.
737    *
738    * @return A new builder object.
739    */
740   public static Builder create() {
741      return new Builder();
742   }
743
744   /**
745    * Returns <jk>true</jk> if the specified annotation contains all default values.
746    *
747    * @param a The annotation to check. Can be <jk>null</jk> (returns <jk>true</jk>).
748    * @return <jk>true</jk> if the specified annotation contains all default values.
749    */
750   public static boolean empty(SubItems a) {
751      return a == null || DEFAULT.equals(a);
752   }
753
754   /**
755    * Merges the contents of the specified annotation into the specified generic map.
756    *
757    * @param om The map to copy the contents to. Can be <jk>null</jk> (a new map is created).
758    * @param a The annotation to apply. Can be <jk>null</jk> (returns the map unchanged).
759    * @return The same map (or a new map if <c>om</c> was <jk>null</jk>) with the annotation contents applied.
760    * @throws ParseException Invalid JSON found in value.
761    */
762   public static JsonMap merge(JsonMap om, SubItems a) throws ParseException {
763      if (SubItemsAnnotation.empty(a))
764         return om;
765      if (om == null)
766         om = new JsonMap();
767      Predicate<String> ne = Shorts::ine;
768      Predicate<Collection<?>> nec = Shorts::ine;
769      Predicate<Boolean> nf = ObjectUtils::isTrue;
770      Predicate<Long> nm1 = Shorts::nm1;
771      // @formatter:off
772      return om
773         .appendFirst(ne, "collectionFormat", a.collectionFormat(), a.cf())
774         .appendIf(ne, "default", joinnl(a.default_(), a.df()))
775         .appendFirst(nec, "enum", parseSet(a.enum_()), parseSet(a.e()))
776         .appendIf(nf, "exclusiveMaximum", a.exclusiveMaximum() || a.emax())
777         .appendIf(nf, "exclusiveMinimum", a.exclusiveMinimum() || a.emin())
778         .appendFirst(ne, "format", a.format(), a.f())
779         .appendFirst(ne, "maximum", a.maximum(), a.max())
780         .appendFirst(nm1, "maxItems", a.maxItems(), a.maxi())
781         .appendFirst(nm1, "maxLength", a.maxLength(), a.maxl())
782         .appendFirst(ne, "minimum", a.minimum(), a.min())
783         .appendFirst(nm1, "minItems", a.minItems(), a.mini())
784         .appendFirst(nm1, "minLength", a.minLength(), a.minl())
785         .appendFirst(ne, "multipleOf", a.multipleOf(), a.mo())
786         .appendFirst(ne, "pattern", a.pattern(), a.p())
787         .appendFirst(ne, "type", a.type(), a.t())
788         .appendIf(nf, "uniqueItems", a.uniqueItems() || a.ui())
789         .appendIf(ne, "$ref", a.$ref())
790      ;
791      // @formatter:on
792   }
793}