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 > 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}