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