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.parser; 014 015import static org.apache.juneau.internal.CollectionUtils.*; 016import static org.apache.juneau.parser.InputStreamParser.*; 017import static org.apache.juneau.parser.ReaderParser.*; 018 019import java.util.*; 020 021import org.apache.juneau.*; 022import org.apache.juneau.http.*; 023import org.apache.juneau.internal.*; 024 025/** 026 * Builder class for creating instances of {@link ParserGroup}. 027 */ 028public class ParserGroupBuilder extends BeanContextBuilder { 029 030 private final List<Object> parsers; 031 032 /** 033 * Create an empty parser group builder. 034 */ 035 public ParserGroupBuilder() { 036 this.parsers = new ArrayList<>(); 037 } 038 039 /** 040 * Clone an existing parser group builder. 041 * 042 * @param copyFrom The parser group that we're copying settings and parsers from. 043 */ 044 public ParserGroupBuilder(ParserGroup copyFrom) { 045 super(copyFrom.getPropertyStore()); 046 this.parsers = new ArrayList<>(); 047 addReverse(parsers, copyFrom.getParsers()); 048 } 049 050 /** 051 * Registers the specified parsers with this group. 052 * 053 * @param p The parsers to append to this group. 054 * @return This object (for method chaining). 055 */ 056 public ParserGroupBuilder append(Class<?>...p) { 057 addReverse(parsers, p); 058 return this; 059 } 060 061 /** 062 * Registers the specified parsers with this group. 063 * 064 * <p> 065 * When passing in pre-instantiated parsers to this group, applying properties and transforms to the group 066 * do not affect them. 067 * 068 * @param p The parsers to append to this group. 069 * @return This object (for method chaining). 070 */ 071 public ParserGroupBuilder append(Parser...p) { 072 addReverse(parsers, p); 073 return this; 074 } 075 076 /** 077 * Registers the specified parsers with this group. 078 * 079 * <p> 080 * Objects can either be instances of parsers or parser classes. 081 * 082 * @param p The parsers to append to this group. 083 * @return This object (for method chaining). 084 */ 085 public ParserGroupBuilder append(List<Object> p) { 086 addReverse(parsers, p); 087 return this; 088 } 089 090 /** 091 * Registers the specified parsers with this group. 092 * 093 * <p> 094 * Objects can either be instances of parsers or parser classes. 095 * 096 * @param p The parsers to append to this group. 097 * @return This object (for method chaining). 098 */ 099 public ParserGroupBuilder append(Object...p) { 100 addReverse(parsers, p); 101 return this; 102 } 103 104 /** 105 * Creates a new {@link ParserGroup} object using a snapshot of the settings defined in this builder. 106 * 107 * <p> 108 * This method can be called multiple times to produce multiple parser groups. 109 * 110 * @return A new {@link ParserGroup} object. 111 */ 112 @Override /* Context */ 113 @SuppressWarnings("unchecked") 114 public ParserGroup build() { 115 List<Parser> l = new ArrayList<>(); 116 for (Object p : parsers) { 117 Class<? extends Parser> c = null; 118 PropertyStore ps = getPropertyStore(); 119 if (p instanceof Class) { 120 c = (Class<? extends Parser>)p; 121 l.add(ContextCache.INSTANCE.create(c, ps)); 122 } else { 123 l.add((Parser)p); 124 } 125 } 126 return new ParserGroup(getPropertyStore(), ArrayUtils.toReverseArray(Parser.class, l)); 127 } 128 129 130 //----------------------------------------------------------------------------------------------------------------- 131 // Properties 132 //----------------------------------------------------------------------------------------------------------------- 133 134 /** 135 * Configuration property: Auto-close streams. 136 * 137 * <p> 138 * If <jk>true</jk>, <l>InputStreams</l> and <l>Readers</l> passed into parsers will be closed 139 * after parsing is complete. 140 * 141 * <h5 class='section'>See Also:</h5> 142 * <ul> 143 * <li class='jf'>{@link Parser#PARSER_autoCloseStreams} 144 * </ul> 145 * 146 * @param value 147 * The new value for this property. 148 * <br>The default value is <jk>false</jk>. 149 * @return This object (for method chaining). 150 */ 151 public ParserGroupBuilder autoCloseStreams(boolean value) { 152 return set(PARSER_autoCloseStreams, value); 153 } 154 155 /** 156 * Configuration property: Auto-close streams. 157 * <p> 158 * Shortcut for calling <code>autoCloseStreams(<jk>true</jk>)</code>. 159 * 160 * <h5 class='section'>See Also:</h5> 161 * <ul> 162 * <li class='jf'>{@link Parser#PARSER_autoCloseStreams} 163 * </ul> 164 * 165 * @return This object (for method chaining). 166 */ 167 public ParserGroupBuilder autoCloseStreams() { 168 return set(PARSER_autoCloseStreams, true); 169 } 170 171 /** 172 * Configuration property: Debug output lines. 173 * 174 * When parse errors occur, this specifies the number of lines of input before and after the 175 * error location to be printed as part of the exception message. 176 * 177 * <h5 class='section'>See Also:</h5> 178 * <ul> 179 * <li class='jf'>{@link Parser#PARSER_debugOutputLines} 180 * </ul> 181 * 182 * @param value 183 * The new value for this property. 184 * <br>The default value is <code>5</code>. 185 * @return This object (for method chaining). 186 */ 187 public ParserGroupBuilder debugOutputLines(int value) { 188 set(PARSER_debugOutputLines, value); 189 return this; 190 } 191 192 /** 193 * Configuration property: Parser listener. 194 * 195 * <p> 196 * Class used to listen for errors and warnings that occur during parsing. 197 * 198 * <h5 class='section'>See Also:</h5> 199 * <ul> 200 * <li class='jf'>{@link Parser#PARSER_listener} 201 * </ul> 202 * 203 * @param value The new value for this property. 204 * @return This object (for method chaining). 205 */ 206 public ParserGroupBuilder listener(Class<? extends ParserListener> value) { 207 return set(PARSER_listener, value); 208 } 209 210 /** 211 * Configuration property: Strict mode. 212 * 213 * <p> 214 * If <jk>true</jk>, strict mode for the parsers are enabled. 215 * 216 * <h5 class='section'>See Also:</h5> 217 * <ul> 218 * <li class='jf'>{@link Parser#PARSER_strict} 219 * </ul> 220 * 221 * @param value 222 * The new value for this property. 223 * <br>The default value is <jk>false</jk>. 224 * @return This object (for method chaining). 225 */ 226 public ParserGroupBuilder strict(boolean value) { 227 return set(PARSER_strict, value); 228 } 229 230 /** 231 * Configuration property: Strict mode. 232 * 233 * <p> 234 * Shortcut for calling <code>strict(<jk>true</jk>)</code>. 235 * 236 * <h5 class='section'>See Also:</h5> 237 * <ul> 238 * <li class='jf'>{@link Parser#PARSER_strict} 239 * </ul> 240 * 241 * @return This object (for method chaining). 242 */ 243 public ParserGroupBuilder strict() { 244 return set(PARSER_strict, true); 245 } 246 247 /** 248 * Configuration property: Trim parsed strings. 249 * 250 * <p> 251 * If <jk>true</jk>, string values will be trimmed of whitespace using {@link String#trim()} before being added to 252 * the POJO. 253 * 254 * <h5 class='section'>See Also:</h5> 255 * <ul> 256 * <li class='jf'>{@link Parser#PARSER_trimStrings} 257 * </ul> 258 * 259 * @param value 260 * The new value for this property. 261 * <br>The default value is <jk>false</jk>. 262 * @return This object (for method chaining). 263 */ 264 public ParserGroupBuilder trimStrings(boolean value) { 265 return set(PARSER_trimStrings, value); 266 } 267 268 /** 269 * Configuration property: Trim parsed strings. 270 * 271 * <p> 272 * Shortcut for calling <code>trimStrings(<jk>true</jk>)</code>. 273 * 274 * <h5 class='section'>See Also:</h5> 275 * <ul> 276 * <li class='jf'>{@link Parser#PARSER_trimStrings} 277 * </ul> 278 * 279 * @return This object (for method chaining). 280 */ 281 public ParserGroupBuilder trimStrings() { 282 return set(PARSER_trimStrings, true); 283 } 284 285 /** 286 * Configuration property: Unbuffered. 287 * 288 * <p> 289 * If <jk>true</jk>, don't use internal buffering during parsing. 290 * 291 * <h5 class='section'>See Also:</h5> 292 * <ul> 293 * <li class='jf'>{@link Parser#PARSER_unbuffered} 294 * </ul> 295 * 296 * @param value 297 * The new value for this property. 298 * <br>The default value is <jk>false</jk>. 299 * @return This object (for method chaining). 300 */ 301 public ParserGroupBuilder unbuffered(boolean value) { 302 return set(PARSER_unbuffered, value); 303 } 304 305 /** 306 * Configuration property: Unbuffered. 307 * 308 * <p> 309 * Shortcut for calling <code>unbuffered(<jk>true</jk>)</code>. 310 * 311 * <h5 class='section'>See Also:</h5> 312 * <ul> 313 * <li class='jf'>{@link Parser#PARSER_unbuffered} 314 * </ul> 315 * 316 * @return This object (for method chaining). 317 */ 318 public ParserGroupBuilder unbuffered() { 319 return set(PARSER_unbuffered, true); 320 } 321 322 /** 323 * Configuration property: File charset. 324 * 325 * <p> 326 * The character set to use for reading <code>Files</code> from the file system. 327 * 328 * <h5 class='section'>See Also:</h5> 329 * <ul> 330 * <li class='jf'>{@link ReaderParser#RPARSER_fileCharset} 331 * </ul> 332 * 333 * @param value 334 * The new value for this property. 335 * <br>The default value is <js>"DEFAULT"</js> which causes the system default to be used. 336 * @return This object (for method chaining). 337 */ 338 public ParserGroupBuilder fileCharset(String value) { 339 return set(RPARSER_fileCharset, value); 340 } 341 342 /** 343 * Configuration property: Input stream charset. 344 * 345 * <p> 346 * The character set to use for converting <code>InputStreams</code> and byte arrays to readers. 347 * 348 * <h5 class='section'>See Also:</h5> 349 * <ul> 350 * <li class='jf'>{@link ReaderParser#RPARSER_inputStreamCharset} 351 * </ul> 352 * 353 * @param value 354 * The new value for this property. 355 * <br>The default value is <js>"UTF-8"</js>. 356 * @return This object (for method chaining). 357 */ 358 public ParserGroupBuilder inputStreamCharset(String value) { 359 return set(RPARSER_inputStreamCharset, value); 360 } 361 362 /** 363 * Configuration property: Binary input format. 364 * 365 * <p> 366 * When using the {@link Parser#parse(Object,Class)} method on stream-based parsers and the input is a string, this defines the format to use 367 * when converting the string into a byte array. 368 * 369 * <h5 class='section'>See Also:</h5> 370 * <ul> 371 * <li class='jf'>{@link InputStreamParser#ISPARSER_binaryFormat} 372 * </ul> 373 * 374 * @param value 375 * The new value for this property. 376 * <br>The default value is {@link BinaryFormat#HEX}. 377 * @return This object (for method chaining). 378 */ 379 public ParserGroupBuilder binaryFormat(BinaryFormat value) { 380 return set(ISPARSER_binaryFormat, value); 381 } 382 383 @Override /* BeanContextBuilder */ 384 public ParserGroupBuilder beanClassVisibility(Visibility value) { 385 super.beanClassVisibility(value); 386 return this; 387 } 388 389 @Override /* BeanContextBuilder */ 390 public ParserGroupBuilder beanConstructorVisibility(Visibility value) { 391 super.beanConstructorVisibility(value); 392 return this; 393 } 394 395 @Override /* BeanContextBuilder */ 396 public ParserGroupBuilder beanDictionary(boolean append, Object...values) { 397 super.beanDictionary(append, values); 398 return this; 399 } 400 401 @Override /* BeanContextBuilder */ 402 public ParserGroupBuilder beanDictionary(Class<?>...values) { 403 super.beanDictionary(values); 404 return this; 405 } 406 407 @Override /* BeanContextBuilder */ 408 public ParserGroupBuilder beanDictionary(Object...values) { 409 super.beanDictionary(values); 410 return this; 411 } 412 413 @Override /* BeanContextBuilder */ 414 public ParserGroupBuilder beanDictionaryRemove(Object...values) { 415 super.beanDictionaryRemove(values); 416 return this; 417 } 418 419 @Override /* BeanContextBuilder */ 420 public ParserGroupBuilder beanFieldVisibility(Visibility value) { 421 super.beanFieldVisibility(value); 422 return this; 423 } 424 425 @Override /* BeanContextBuilder */ 426 public ParserGroupBuilder beanFilters(boolean append, Object...values) { 427 super.beanFilters(append, values); 428 return this; 429 } 430 431 @Override /* BeanContextBuilder */ 432 public ParserGroupBuilder beanFilters(Class<?>...values) { 433 super.beanFilters(values); 434 return this; 435 } 436 437 @Override /* BeanContextBuilder */ 438 public ParserGroupBuilder beanFilters(Object...values) { 439 super.beanFilters(values); 440 return this; 441 } 442 443 @Override /* BeanContextBuilder */ 444 public ParserGroupBuilder beanFiltersRemove(Object...values) { 445 super.beanFiltersRemove(values); 446 return this; 447 } 448 449 @Override /* BeanContextBuilder */ 450 public ParserGroupBuilder beanMapPutReturnsOldValue(boolean value) { 451 super.beanMapPutReturnsOldValue(value); 452 return this; 453 } 454 455 @Override /* BeanContextBuilder */ 456 public ParserGroupBuilder beanMapPutReturnsOldValue() { 457 super.beanMapPutReturnsOldValue(); 458 return this; 459 } 460 461 @Override /* BeanContextBuilder */ 462 public ParserGroupBuilder beanMethodVisibility(Visibility value) { 463 super.beanMethodVisibility(value); 464 return this; 465 } 466 467 @Override /* BeanContextBuilder */ 468 public ParserGroupBuilder beansRequireDefaultConstructor(boolean value) { 469 super.beansRequireDefaultConstructor(value); 470 return this; 471 } 472 473 @Override /* BeanContextBuilder */ 474 public ParserGroupBuilder beansRequireDefaultConstructor() { 475 super.beansRequireDefaultConstructor(); 476 return this; 477 } 478 479 @Override /* BeanContextBuilder */ 480 public ParserGroupBuilder beansRequireSerializable(boolean value) { 481 super.beansRequireSerializable(value); 482 return this; 483 } 484 485 @Override /* BeanContextBuilder */ 486 public ParserGroupBuilder beansRequireSerializable() { 487 super.beansRequireSerializable(); 488 return this; 489 } 490 491 @Override /* BeanContextBuilder */ 492 public ParserGroupBuilder beansRequireSettersForGetters(boolean value) { 493 super.beansRequireSettersForGetters(value); 494 return this; 495 } 496 497 @Override /* BeanContextBuilder */ 498 public ParserGroupBuilder beansRequireSettersForGetters() { 499 super.beansRequireSettersForGetters(); 500 return this; 501 } 502 503 @Override /* BeanContextBuilder */ 504 public ParserGroupBuilder beansRequireSomeProperties(boolean value) { 505 super.beansRequireSomeProperties(value); 506 return this; 507 } 508 509 @Override /* BeanContextBuilder */ 510 public ParserGroupBuilder beanTypePropertyName(String value) { 511 super.beanTypePropertyName(value); 512 return this; 513 } 514 515 @Override /* BeanContextBuilder */ 516 public ParserGroupBuilder debug() { 517 super.debug(); 518 return this; 519 } 520 521 @Override /* BeanContextBuilder */ 522 public <T> ParserGroupBuilder example(Class<T> c, T o) { 523 super.example(c, o); 524 return this; 525 } 526 527 @Override /* BeanContextBuilder */ 528 public ParserGroupBuilder ignoreInvocationExceptionsOnGetters(boolean value) { 529 super.ignoreInvocationExceptionsOnGetters(value); 530 return this; 531 } 532 533 @Override /* BeanContextBuilder */ 534 public ParserGroupBuilder ignoreInvocationExceptionsOnGetters() { 535 super.ignoreInvocationExceptionsOnGetters(); 536 return this; 537 } 538 539 @Override /* BeanContextBuilder */ 540 public ParserGroupBuilder ignoreInvocationExceptionsOnSetters(boolean value) { 541 super.ignoreInvocationExceptionsOnSetters(value); 542 return this; 543 } 544 545 @Override /* BeanContextBuilder */ 546 public ParserGroupBuilder ignoreInvocationExceptionsOnSetters() { 547 super.ignoreInvocationExceptionsOnSetters(); 548 return this; 549 } 550 551 @Override /* BeanContextBuilder */ 552 public ParserGroupBuilder ignorePropertiesWithoutSetters(boolean value) { 553 super.ignorePropertiesWithoutSetters(value); 554 return this; 555 } 556 557 @Override /* BeanContextBuilder */ 558 public ParserGroupBuilder ignoreUnknownBeanProperties(boolean value) { 559 super.ignoreUnknownBeanProperties(value); 560 return this; 561 } 562 563 @Override /* BeanContextBuilder */ 564 public ParserGroupBuilder ignoreUnknownBeanProperties() { 565 super.ignoreUnknownBeanProperties(); 566 return this; 567 } 568 569 @Override /* BeanContextBuilder */ 570 public ParserGroupBuilder ignoreUnknownNullBeanProperties(boolean value) { 571 super.ignoreUnknownNullBeanProperties(value); 572 return this; 573 } 574 575 @Override /* BeanContextBuilder */ 576 public <T> ParserGroupBuilder implClass(Class<T> interfaceClass, Class<? extends T> implClass) { 577 super.implClass(interfaceClass, implClass); 578 return this; 579 } 580 581 @Override /* BeanContextBuilder */ 582 public ParserGroupBuilder implClasses(Map<String,Class<?>> values) { 583 super.implClasses(values); 584 return this; 585 } 586 587 @Override /* BeanContextBuilder */ 588 public ParserGroupBuilder locale(Locale value) { 589 super.locale(value); 590 return this; 591 } 592 593 @Override /* BeanContextBuilder */ 594 public ParserGroupBuilder mediaType(MediaType value) { 595 super.mediaType(value); 596 return this; 597 } 598 599 @Override /* BeanContextBuilder */ 600 public ParserGroupBuilder notBeanClasses(boolean append, Object...values) { 601 super.notBeanClasses(append, values); 602 return this; 603 } 604 605 @Override /* BeanContextBuilder */ 606 public ParserGroupBuilder notBeanClasses(Class<?>...values) { 607 super.notBeanClasses(values); 608 return this; 609 } 610 611 @Override /* BeanContextBuilder */ 612 public ParserGroupBuilder notBeanClasses(Object...values) { 613 super.notBeanClasses(values); 614 return this; 615 } 616 617 @Override /* BeanContextBuilder */ 618 public ParserGroupBuilder notBeanClassesRemove(Object...values) { 619 super.notBeanClassesRemove(values); 620 return this; 621 } 622 623 @Override /* BeanContextBuilder */ 624 public ParserGroupBuilder notBeanPackages(boolean append, Object...values) { 625 super.notBeanPackages(append, values); 626 return this; 627 } 628 629 @Override /* BeanContextBuilder */ 630 public ParserGroupBuilder notBeanPackages(Object...values) { 631 super.notBeanPackages(values); 632 return this; 633 } 634 635 @Override /* BeanContextBuilder */ 636 public ParserGroupBuilder notBeanPackages(String...values) { 637 super.notBeanPackages(values); 638 return this; 639 } 640 641 @Override /* BeanContextBuilder */ 642 public ParserGroupBuilder notBeanPackagesRemove(Object...values) { 643 super.notBeanPackagesRemove(values); 644 return this; 645 } 646 647 @Override /* BeanContextBuilder */ 648 public ParserGroupBuilder pojoSwaps(boolean append, Object...values) { 649 super.pojoSwaps(append, values); 650 return this; 651 } 652 653 @Override /* BeanContextBuilder */ 654 public ParserGroupBuilder pojoSwaps(Class<?>...values) { 655 super.pojoSwaps(values); 656 return this; 657 } 658 659 @Override /* BeanContextBuilder */ 660 public ParserGroupBuilder pojoSwaps(Object...values) { 661 super.pojoSwaps(values); 662 return this; 663 } 664 665 @Override /* BeanContextBuilder */ 666 public ParserGroupBuilder pojoSwapsRemove(Object...values) { 667 super.pojoSwapsRemove(values); 668 return this; 669 } 670 671 @Override /* BeanContextBuilder */ 672 public ParserGroupBuilder sortProperties(boolean value) { 673 super.sortProperties(value); 674 return this; 675 } 676 677 @Override /* BeanContextBuilder */ 678 public ParserGroupBuilder sortProperties() { 679 super.sortProperties(); 680 return this; 681 } 682 683 @Override /* BeanContextBuilder */ 684 public ParserGroupBuilder timeZone(TimeZone value) { 685 super.timeZone(value); 686 return this; 687 } 688 689 @Override /* BeanContextBuilder */ 690 public ParserGroupBuilder useEnumNames() { 691 super.useEnumNames(); 692 return this; 693 } 694 695 @Override /* BeanContextBuilder */ 696 public ParserGroupBuilder useInterfaceProxies(boolean value) { 697 super.useInterfaceProxies(value); 698 return this; 699 } 700 701 @Override /* BeanContextBuilder */ 702 public ParserGroupBuilder useJavaBeanIntrospector(boolean value) { 703 super.useJavaBeanIntrospector(value); 704 return this; 705 } 706 707 @Override /* BeanContextBuilder */ 708 public ParserGroupBuilder useJavaBeanIntrospector() { 709 super.useJavaBeanIntrospector(); 710 return this; 711 } 712 713 @Override /* ContextBuilder */ 714 public ParserGroupBuilder set(String name, Object value) { 715 super.set(name, value); 716 return this; 717 } 718 719 @Override /* ContextBuilder */ 720 public ParserGroupBuilder set(boolean append, String name, Object value) { 721 super.set(append, name, value); 722 return this; 723 } 724 725 @Override /* ContextBuilder */ 726 public ParserGroupBuilder set(Map<String,Object> properties) { 727 super.set(properties); 728 return this; 729 } 730 731 @Override /* ContextBuilder */ 732 public ParserGroupBuilder add(Map<String,Object> properties) { 733 super.add(properties); 734 return this; 735 } 736 737 @Override /* ContextBuilder */ 738 public ParserGroupBuilder addTo(String name, Object value) { 739 super.addTo(name, value); 740 return this; 741 } 742 743 @Override /* ContextBuilder */ 744 public ParserGroupBuilder addTo(String name, String key, Object value) { 745 super.addTo(name, key, value); 746 return this; 747 } 748 749 @Override /* ContextBuilder */ 750 public ParserGroupBuilder removeFrom(String name, Object value) { 751 super.removeFrom(name, value); 752 return this; 753 } 754 755 @Override /* ContextBuilder */ 756 public ParserGroupBuilder apply(PropertyStore copyFrom) { 757 super.apply(copyFrom); 758 return this; 759 } 760}