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.bean.swagger;
018
019import static org.apache.juneau.commons.utils.AssertionUtils.*;
020import static org.apache.juneau.commons.utils.CollectionUtils.*;
021import static org.apache.juneau.commons.utils.ThrowableUtils.*;
022import static org.apache.juneau.commons.utils.Utils.*;
023import static org.apache.juneau.internal.ConverterUtils.*;
024
025import java.util.*;
026
027import org.apache.juneau.annotation.*;
028import org.apache.juneau.commons.collections.*;
029import org.apache.juneau.marshaller.*;
030
031/**
032 * A limited subset of JSON-Schema's items object.
033 *
034 * <p>
035 * The Items Object is a limited subset of JSON-Schema's items object for Swagger 2.0. It is used by parameter
036 * definitions that are not located in "body" to describe the type of items in an array. This is particularly useful
037 * for query parameters, path parameters, and header parameters that accept arrays.
038 *
039 * <h5 class='section'>Swagger Specification:</h5>
040 * <p>
041 * The Items Object supports the following fields from JSON Schema:
042 * <ul class='spaced-list'>
043 *    <li><c>type</c> (string, REQUIRED) - The data type. Values: <js>"string"</js>, <js>"number"</js>, <js>"integer"</js>, <js>"boolean"</js>, <js>"array"</js>
044 *    <li><c>format</c> (string) - The format modifier (e.g., <js>"int32"</js>, <js>"int64"</js>, <js>"float"</js>, <js>"double"</js>, <js>"date"</js>, <js>"date-time"</js>)
045 *    <li><c>items</c> ({@link Items}) - Required if type is <js>"array"</js>. Describes the type of items in the array
046 *    <li><c>collectionFormat</c> (string) - How multiple values are formatted. Values: <js>"csv"</js>, <js>"ssv"</js>, <js>"tsv"</js>, <js>"pipes"</js>, <js>"multi"</js>
047 *    <li><c>default</c> (any) - The default value
048 *    <li><c>maximum</c> (number), <c>exclusiveMaximum</c> (boolean), <c>minimum</c> (number), <c>exclusiveMinimum</c> (boolean) - Numeric constraints
049 *    <li><c>maxLength</c> (integer), <c>minLength</c> (integer), <c>pattern</c> (string) - String constraints
050 *    <li><c>maxItems</c> (integer), <c>minItems</c> (integer), <c>uniqueItems</c> (boolean) - Array constraints
051 *    <li><c>enum</c> (array) - Possible values for this item
052 *    <li><c>multipleOf</c> (number) - Must be a multiple of this value
053 * </ul>
054 *
055 * <h5 class='section'>Example:</h5>
056 * <p class='bjava'>
057 *    <jc>// Construct using SwaggerBuilder.</jc>
058 *    Items <jv>items</jv> = <jsm>items</jsm>(<js>"string"</js>).minLength(2);
059 *
060 *    <jc>// Serialize using JsonSerializer.</jc>
061 *    String <jv>json</jv> = Json.<jsm>from</jsm>(<jv>items</jv>);
062 *
063 *    <jc>// Or just use toString() which does the same as above.</jc>
064 *    <jv>json</jv> = <jv>items</jv>.toString();
065 * </p>
066 * <p class='bjson'>
067 *    <jc>// Output</jc>
068 *    {
069 *       <js>"type"</js>: <js>"string"</js>,
070 *       <js>"minLength"</js>: 2
071 *    }
072 * </p>
073 *
074 * <h5 class='section'>See Also:</h5><ul>
075 *    <li class='link'><a class="doclink" href="https://swagger.io/specification/v2/#items-object">Swagger 2.0 Specification &gt; Items Object</a>
076 *    <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/2-0/describing-parameters/">Swagger Describing Parameters</a>
077 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanSwagger2">juneau-bean-swagger-v2</a>
078 * </ul>
079 */
080public class Items extends SwaggerElement {
081
082   private static final String[] VALID_TYPES = { "string", "number", "integer", "boolean", "array" };
083   private static final String[] VALID_COLLECTION_FORMATS = { "csv", "ssv", "tsv", "pipes", "multi" };
084
085   private String type, format, collectionFormat, pattern, ref;
086   private Number maximum, minimum, multipleOf;
087   private Integer maxLength, minLength, maxItems, minItems;
088   private Boolean exclusiveMaximum, exclusiveMinimum, uniqueItems;
089   private Items items;  // NOSONAR - Intentional naming.
090   private Object default_;
091   private Set<Object> enum_ = new LinkedHashSet<>();
092
093   /**
094    * Default constructor.
095    */
096   public Items() {}
097
098   /**
099    * Copy constructor.
100    *
101    * @param copyFrom The object to copy.
102    */
103   public Items(Items copyFrom) {
104      super(copyFrom);
105
106      this.collectionFormat = copyFrom.collectionFormat;
107      this.default_ = copyFrom.default_;
108      if (nn(copyFrom.enum_))
109         this.enum_.addAll(copyOf(copyFrom.enum_));
110      this.exclusiveMaximum = copyFrom.exclusiveMaximum;
111      this.exclusiveMinimum = copyFrom.exclusiveMinimum;
112      this.format = copyFrom.format;
113      this.items = copyFrom.items == null ? null : copyFrom.items.copy();
114      this.maximum = copyFrom.maximum;
115      this.maxItems = copyFrom.maxItems;
116      this.maxLength = copyFrom.maxLength;
117      this.minimum = copyFrom.minimum;
118      this.minItems = copyFrom.minItems;
119      this.minLength = copyFrom.minLength;
120      this.multipleOf = copyFrom.multipleOf;
121      this.pattern = copyFrom.pattern;
122      this.ref = copyFrom.ref;
123      this.type = copyFrom.type;
124      this.uniqueItems = copyFrom.uniqueItems;
125   }
126
127   /**
128    * Bean property fluent setter:  <property>enum</property>.
129    *
130    * @param value
131    *    The new value for this property.
132    *    <br>String values can be JSON arrays.
133    * @return This object.
134    */
135   public Items addEnum(Object...value) {
136      if (nn(value))
137         for (var v : value)
138            if (nn(v))
139               enum_.add(v);
140      return this;
141   }
142
143   /**
144    * Make a deep copy of this object.
145    *
146    * @return A deep copy of this object.
147    */
148   public Items copy() {
149      return new Items(this);
150   }
151
152   @Override /* Overridden from SwaggerElement */
153   public <T> T get(String property, Class<T> type) {
154      assertArgNotNull("property", property);
155      return switch (property) {
156         case "collectionFormat" -> toType(getCollectionFormat(), type);
157         case "default" -> toType(getDefault(), type);
158         case "enum" -> toType(getEnum(), type);
159         case "exclusiveMaximum" -> toType(getExclusiveMaximum(), type);
160         case "exclusiveMinimum" -> toType(getExclusiveMinimum(), type);
161         case "format" -> toType(getFormat(), type);
162         case "items" -> toType(getItems(), type);
163         case "maximum" -> toType(getMaximum(), type);
164         case "maxItems" -> toType(getMaxItems(), type);
165         case "maxLength" -> toType(getMaxLength(), type);
166         case "minimum" -> toType(getMinimum(), type);
167         case "minItems" -> toType(getMinItems(), type);
168         case "minLength" -> toType(getMinLength(), type);
169         case "multipleOf" -> toType(getMultipleOf(), type);
170         case "pattern" -> toType(getPattern(), type);
171         case "$ref" -> toType(getRef(), type);
172         case "type" -> toType(getType(), type);
173         case "uniqueItems" -> toType(getUniqueItems(), type);
174         default -> super.get(property, type);
175      };
176   }
177
178   /**
179    * Bean property getter:  <property>collectionFormat</property>.
180    *
181    * <p>
182    * Determines the format of the array if type array is used.
183    *
184    * @return The property value, or <jk>null</jk> if it is not set.
185    */
186   public String getCollectionFormat() { return collectionFormat; }
187
188   /**
189    * Bean property getter:  <property>default</property>.
190    *
191    * <p>
192    * Declares the value of the item that the server will use if none is provided.
193    *
194    * <h5 class='section'>Notes:</h5><ul>
195    *    <li class='note'>
196    *       <js>"default"</js> has no meaning for required items.
197    *    <li class='note'>
198    *       Unlike JSON Schema this value MUST conform to the defined <c>type</c> for the data type.
199    * </ul>
200    *
201    * @return The property value, or <jk>null</jk> if it is not set.
202    */
203   public Object getDefault() { return default_; }
204
205   /**
206    * Bean property getter:  <property>enum</property>.
207    *
208    * @return The property value, or <jk>null</jk> if it is not set.
209    */
210   public Set<Object> getEnum() { return nullIfEmpty(enum_); }
211
212   /**
213    * Bean property getter:  <property>exclusiveMaximum</property>.
214    *
215    * @return The property value, or <jk>null</jk> if it is not set.
216    */
217   public Boolean getExclusiveMaximum() { return exclusiveMaximum; }
218
219   /**
220    * Bean property getter:  <property>exclusiveMinimum</property>.
221    *
222    * @return The property value, or <jk>null</jk> if it is not set.
223    */
224   public Boolean getExclusiveMinimum() { return exclusiveMinimum; }
225
226   /**
227    * Bean property getter:  <property>format</property>.
228    *
229    * <p>
230    * The extending format for the previously mentioned <c>type</c>.
231    *
232    * @return The property value, or <jk>null</jk> if it is not set.
233    */
234   public String getFormat() { return format; }
235
236   /**
237    * Bean property getter:  <property>items</property>.
238    *
239    * <p>
240    * Describes the type of items in the array.
241    *
242    * @return The property value, or <jk>null</jk> if it is not set.
243    */
244   public Items getItems() { return items; }
245
246   /**
247    * Bean property getter:  <property>maximum</property>.
248    *
249    * @return The property value, or <jk>null</jk> if it is not set.
250    */
251   public Number getMaximum() { return maximum; }
252
253   /**
254    * Bean property getter:  <property>maxItems</property>.
255    *
256    * @return The property value, or <jk>null</jk> if it is not set.
257    */
258   public Integer getMaxItems() { return maxItems; }
259
260   /**
261    * Bean property getter:  <property>maxLength</property>.
262    *
263    * @return The property value, or <jk>null</jk> if it is not set.
264    */
265   public Integer getMaxLength() { return maxLength; }
266
267   /**
268    * Bean property getter:  <property>minimum</property>.
269    *
270    * @return The property value, or <jk>null</jk> if it is not set.
271    */
272   public Number getMinimum() { return minimum; }
273
274   /**
275    * Bean property getter:  <property>minItems</property>.
276    *
277    * @return The property value, or <jk>null</jk> if it is not set.
278    */
279   public Integer getMinItems() { return minItems; }
280
281   /**
282    * Bean property getter:  <property>minLength</property>.
283    *
284    * @return The property value, or <jk>null</jk> if it is not set.
285    */
286   public Integer getMinLength() { return minLength; }
287
288   /**
289    * Bean property getter:  <property>multipleOf</property>.
290    *
291    * @return The property value, or <jk>null</jk> if it is not set.
292    */
293   public Number getMultipleOf() { return multipleOf; }
294
295   /**
296    * Bean property getter:  <property>pattern</property>.
297    *
298    * @return The property value, or <jk>null</jk> if it is not set.
299    */
300   public String getPattern() { return pattern; }
301
302   /**
303    * Bean property getter:  <property>$ref</property>.
304    *
305    * @return The property value, or <jk>null</jk> if it is not set.
306    */
307   @Beanp("$ref")
308   public String getRef() { return ref; }
309
310   /**
311    * Bean property getter:  <property>type</property>.
312    *
313    * <p>
314    * The internal type of the array.
315    *
316    * @return The property value, or <jk>null</jk> if it is not set.
317    */
318   public String getType() { return type; }
319
320   /**
321    * Bean property getter:  <property>uniqueItems</property>.
322    *
323    * @return The property value, or <jk>null</jk> if it is not set.
324    */
325   public Boolean getUniqueItems() { return uniqueItems; }
326
327   @Override /* Overridden from SwaggerElement */
328   public Set<String> keySet() {
329      // @formatter:off
330      var s = setb(String.class)
331         .addIf(nn(ref), "$ref")
332         .addIf(nn(collectionFormat), "collectionFormat")
333         .addIf(nn(default_), "default")
334         .addIf(ne(enum_), "enum")
335         .addIf(nn(exclusiveMaximum), "exclusiveMaximum")
336         .addIf(nn(exclusiveMinimum), "exclusiveMinimum")
337         .addIf(nn(format), "format")
338         .addIf(nn(items), "items")
339         .addIf(nn(maxItems), "maxItems")
340         .addIf(nn(maxLength), "maxLength")
341         .addIf(nn(maximum), "maximum")
342         .addIf(nn(minItems), "minItems")
343         .addIf(nn(minLength), "minLength")
344         .addIf(nn(minimum), "minimum")
345         .addIf(nn(multipleOf), "multipleOf")
346         .addIf(nn(pattern), "pattern")
347         .addIf(nn(type), "type")
348         .addIf(nn(uniqueItems), "uniqueItems")
349         .build();
350      // @formatter:on
351      return new MultiSet<>(s, super.keySet());
352   }
353
354   /**
355    * Resolves any <js>"$ref"</js> attributes in this element.
356    *
357    * @param swagger The swagger document containing the definitions.
358    * @param refStack Keeps track of previously-visited references so that we don't cause recursive loops.
359    * @param maxDepth
360    *    The maximum depth to resolve references.
361    *    <br>After that level is reached, <c>$ref</c> references will be left alone.
362    *    <br>Useful if you have very complex models and you don't want your swagger page to be overly-complex.
363    * @return
364    *    This object with references resolved.
365    *    <br>May or may not be the same object.
366    */
367   public Items resolveRefs(Swagger swagger, Deque<String> refStack, int maxDepth) {
368
369      if (nn(ref)) {
370         if (refStack.contains(ref) || refStack.size() >= maxDepth)
371            return this;
372         refStack.addLast(ref);
373         var r = swagger.findRef(ref, Items.class).resolveRefs(swagger, refStack, maxDepth);
374         refStack.removeLast();
375         return r;
376      }
377
378      if (nn(items))
379         items = items.resolveRefs(swagger, refStack, maxDepth);
380
381      return this;
382   }
383
384   @Override /* Overridden from SwaggerElement */
385   public Items set(String property, Object value) {
386      assertArgNotNull("property", property);
387      return switch (property) {
388         case "collectionFormat" -> setCollectionFormat(s(value));
389         case "default" -> setDefault(value);
390         case "enum" -> setEnum(listb(Object.class).addAny(value).sparse().build());
391         case "exclusiveMaximum" -> setExclusiveMaximum(toBoolean(value));
392         case "exclusiveMinimum" -> setExclusiveMinimum(toBoolean(value));
393         case "format" -> setFormat(s(value));
394         case "items" -> setItems(toType(value, Items.class));
395         case "maximum" -> setMaximum(toNumber(value));
396         case "maxItems" -> setMaxItems(toInteger(value));
397         case "maxLength" -> setMaxLength(toInteger(value));
398         case "minimum" -> setMinimum(toNumber(value));
399         case "minItems" -> setMinItems(toInteger(value));
400         case "minLength" -> setMinLength(toInteger(value));
401         case "multipleOf" -> setMultipleOf(toNumber(value));
402         case "pattern" -> setPattern(s(value));
403         case "$ref" -> setRef(s(value));
404         case "type" -> setType(s(value));
405         case "uniqueItems" -> setUniqueItems(toBoolean(value));
406         default -> {
407            super.set(property, value);
408            yield this;
409         }
410      };
411   }
412
413   /**
414    * Bean property setter:  <property>collectionFormat</property>.
415    *
416    * <p>
417    * Determines the format of the array if type array is used.
418    *
419    * @param value
420    *    The new value for this property.
421    *    <br>Valid values:
422    *    <ul>
423    *       <li><js>"csv"</js> (default) - comma separated values <c>foo,bar</c>.
424    *       <li><js>"ssv"</js> - space separated values <c>foo bar</c>.
425    *       <li><js>"tsv"</js> - tab separated values <c>foo\tbar</c>.
426    *       <li><js>"pipes"</js> - pipe separated values <c>foo|bar</c>.
427    *    </ul>
428    *    <br>Can be <jk>null</jk> to unset the property.
429    * @return This object.
430    */
431   public Items setCollectionFormat(String value) {
432      if (isStrict() && ! contains(value, VALID_COLLECTION_FORMATS))
433         throw rex("Invalid value passed in to setCollectionFormat(String).  Value=''{0}'', valid values={1}", value, Json5.of(VALID_COLLECTION_FORMATS));
434      collectionFormat = value;
435      return this;
436   }
437
438   /**
439    * Bean property setter:  <property>default</property>.
440    *
441    * <p>
442    * Declares the value of the item that the server will use if none is provided.
443    *
444    * <h5 class='section'>Notes:</h5><ul>
445    *    <li class='note'>
446    *       <js>"default"</js> has no meaning for required items.
447    *    <li class='note'>
448    *       Unlike JSON Schema this value MUST conform to the defined <c>type</c> for the data type.
449    * </ul>
450    *
451    * @param value
452    *    The new value for this property.
453    *    <br>Can be <jk>null</jk> to unset the property.
454    * @return This object.
455    */
456   public Items setDefault(Object value) {
457      default_ = value;
458      return this;
459   }
460
461   /**
462    * Bean property setter:  <property>enum</property>.
463    *
464    * @param value
465    *    The new value for this property.
466    *    <br>Can be <jk>null</jk> to unset the property.
467    * @return This object.
468    */
469   public Items setEnum(Collection<Object> value) {
470      enum_.clear();
471      if (nn(value))
472         enum_.addAll(value);
473      return this;
474   }
475
476   /**
477    * Bean property setter:  <property>enum</property>.
478    *
479    * @param value
480    *    The new value for this property.
481    *    <br>Can be <jk>null</jk> to unset the property.
482    * @return This object.
483    */
484   public Items setEnum(Object...value) {
485      return setEnum(l(value));
486   }
487
488   /**
489    * Bean property setter:  <property>exclusiveMaximum</property>.
490    *
491    * @param value
492    *    The new value for this property.
493    *    <br>Can be <jk>null</jk> to unset the property.
494    * @return This object.
495    */
496   public Items setExclusiveMaximum(Boolean value) {
497      exclusiveMaximum = value;
498      return this;
499   }
500
501   /**
502    * Bean property setter:  <property>exclusiveMinimum</property>.
503    *
504    * @param value
505    *    The new value for this property.
506    *    <br>Can be <jk>null</jk> to unset the property.
507    * @return This object.
508    */
509   public Items setExclusiveMinimum(Boolean value) {
510      exclusiveMinimum = value;
511      return this;
512   }
513
514   /**
515    * Bean property setter:  <property>format</property>.
516    *
517    * <p>
518    * The extending format for the previously mentioned <c>type</c>.
519    *
520    * @param value
521    *    The new value for this property.
522    *    <br>Can be <jk>null</jk> to unset the property.
523    * @return This object.
524    */
525   public Items setFormat(String value) {
526      format = value;
527      return this;
528   }
529
530   /**
531    * Bean property setter:  <property>items</property>.
532    *
533    * <p>
534    * Describes the type of items in the array.
535    *
536    * @param value
537    *    The new value for this property.
538    *    <br>Property value is required if <c>type</c> is <js>"array"</js>.
539    *    <br>Can be <jk>null</jk> to unset the property.
540    * @return This object.
541    */
542   public Items setItems(Items value) {
543      items = value;
544      return this;
545   }
546
547   /**
548    * Bean property setter:  <property>maximum</property>.
549    *
550    * @param value
551    *    The new value for this property.
552    *    <br>Can be <jk>null</jk> to unset the property.
553    * @return This object.
554    */
555   public Items setMaximum(Number value) {
556      maximum = value;
557      return this;
558   }
559
560   /**
561    * Bean property setter:  <property>maxItems</property>.
562    *
563    * @param value
564    *    The new value for this property.
565    *    <br>Can be <jk>null</jk> to unset the property.
566    * @return This object.
567    */
568   public Items setMaxItems(Integer value) {
569      maxItems = value;
570      return this;
571   }
572
573   /**
574    * Bean property setter:  <property>maxLength</property>.
575    *
576    * @param value
577    *    The new value for this property.
578    *    <br>Can be <jk>null</jk> to unset the property.
579    * @return This object.
580    */
581   public Items setMaxLength(Integer value) {
582      maxLength = value;
583      return this;
584   }
585
586   /**
587    * Bean property setter:  <property>minimum</property>.
588    *
589    * @param value
590    *    The new value for this property.
591    *    <br>Can be <jk>null</jk> to unset the property.
592    * @return This object.
593    */
594   public Items setMinimum(Number value) {
595      minimum = value;
596      return this;
597   }
598
599   /**
600    * Bean property setter:  <property>minItems</property>.
601    *
602    * @param value
603    *    The new value for this property.
604    *    <br>Can be <jk>null</jk> to unset the property.
605    * @return This object.
606    */
607   public Items setMinItems(Integer value) {
608      minItems = value;
609      return this;
610   }
611
612   /**
613    * Bean property setter:  <property>minLength</property>.
614    *
615    * @param value
616    *    The new value for this property.
617    *    <br>Can be <jk>null</jk> to unset the property.
618    * @return This object.
619    */
620   public Items setMinLength(Integer value) {
621      minLength = value;
622      return this;
623   }
624
625   /**
626    * Bean property setter:  <property>multipleOf</property>.
627    *
628    * @param value
629    *    The new value for this property.
630    *    <br>Can be <jk>null</jk> to unset the property.
631    * @return This object.
632    */
633   public Items setMultipleOf(Number value) {
634      multipleOf = value;
635      return this;
636   }
637
638   /**
639    * Bean property setter:  <property>pattern</property>.
640    *
641    * @param value
642    *    The new value for this property.
643    *    <br>This string SHOULD be a valid regular expression.
644    *    <br>Can be <jk>null</jk> to unset the property.
645    * @return This object.
646    */
647   public Items setPattern(String value) {
648      pattern = value;
649      return this;
650   }
651
652   /**
653    * Bean property setter:  <property>$ref</property>.
654    *
655    * @param value
656    *    The new value for this property.
657    *    <br>Can be <jk>null</jk> to unset the property.
658    * @return This object.
659    */
660   @Beanp("$ref")
661   public Items setRef(String value) {
662      ref = value;
663      return this;
664   }
665
666   /**
667    * Bean property setter:  <property>type</property>.
668    *
669    * <p>
670    * The internal type of the array.
671    *
672    * @param value
673    *    The new value for this property.
674    *    <br>Valid values:
675    *    <ul>
676    *       <li><js>"string"</js>
677    *       <li><js>"number"</js>
678    *       <li><js>"integer"</js>
679    *       <li><js>"boolean"</js>
680    *       <li><js>"array"</js>
681    *    </ul>
682    *    <br>Property value is required.
683    *    <br>Can be <jk>null</jk> to unset the property.
684    * @return This object.
685    */
686   public Items setType(String value) {
687      if (isStrict() && ! contains(value, VALID_TYPES))
688         throw rex("Invalid value passed in to setType(String).  Value=''{0}'', valid values={1}", value, Json5.of(VALID_TYPES));
689      type = value;
690      return this;
691   }
692
693   /**
694    * Bean property setter:  <property>uniqueItems</property>.
695    *
696    * @param value
697    *    The new value for this property.
698    *    <br>Can be <jk>null</jk> to unset the property.
699    * @return This object.
700    */
701   public Items setUniqueItems(Boolean value) {
702      uniqueItems = value;
703      return this;
704   }
705
706   @Override /* Overridden from SwaggerElement */
707   public Items strict() {
708      super.strict();
709      return this;
710   }
711
712   /**
713    * Sets strict mode on this bean.
714    *
715    * @param value
716    *    The new value for this property.
717    *    <br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
718    *    <br>Can be <jk>null</jk> (interpreted as <jk>false</jk>).
719    * @return This object.
720    */
721   @Override
722   public Items strict(Object value) {
723      super.strict(value);
724      return this;
725   }
726}