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