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.parser; 018 019import static org.apache.juneau.collections.JsonMap.*; 020import static org.apache.juneau.common.utils.Utils.*; 021 022import java.io.*; 023import java.lang.annotation.*; 024import java.lang.reflect.*; 025import java.nio.charset.*; 026import java.util.*; 027 028import org.apache.juneau.*; 029import org.apache.juneau.collections.*; 030import org.apache.juneau.common.utils.*; 031import org.apache.juneau.html.*; 032import org.apache.juneau.internal.*; 033import org.apache.juneau.json.*; 034import org.apache.juneau.msgpack.*; 035import org.apache.juneau.objecttools.*; 036import org.apache.juneau.swap.*; 037import org.apache.juneau.swaps.*; 038import org.apache.juneau.uon.*; 039import org.apache.juneau.utils.*; 040import org.apache.juneau.xml.*; 041 042/** 043 * Parent class for all Juneau parsers. 044 * 045 * <h5 class='topic'>Valid data conversions</h5> 046 * <p> 047 * Parsers can parse any parsable POJO types, as specified in the <a class="doclink" href="https://juneau.apache.org/docs/topics/PojoCategories">POJO Categories</a>. 048 * 049 * <p> 050 * Some examples of conversions are shown below... 051 * </p> 052 * <table class='styled'> 053 * <tr> 054 * <th>Data type</th> 055 * <th>Class type</th> 056 * <th>JSON example</th> 057 * <th>XML example</th> 058 * <th>Class examples</th> 059 * </tr> 060 * <tr> 061 * <td>object</td> 062 * <td>Maps, Java beans</td> 063 * <td class='code'>{name:<js>'John Smith'</js>,age:21}</td> 064 * <td class='code'><xt><object> 065 * <name</xt> <xa>type</xa>=<xs>'string'</xs><xt>></xt>John Smith<xt></name> 066 * <age</xt> <xa>type</xa>=<xs>'number'</xs><xt>></xt>21<xt></age> 067 * </object></xt></td> 068 * <td class='code'>HashMap, TreeMap<String,Integer></td> 069 * </tr> 070 * <tr> 071 * <td>array</td> 072 * <td>Collections, Java arrays</td> 073 * <td class='code'>[1,2,3]</td> 074 * <td class='code'><xt><array> 075 * <number></xt>1<xt></number> 076 * <number></xt>2<xt></number> 077 * <number></xt>3<xt></number> 078 * </array></xt></td> 079 * <td class='code'>List<Integer>, <jk>int</jk>[], Float[], Set<Person></td> 080 * </tr> 081 * <tr> 082 * <td>number</td> 083 * <td>Numbers</td> 084 * <td class='code'>123</td> 085 * <td class='code'><xt><number></xt>123<xt></number></xt></td> 086 * <td class='code'>Integer, Long, Float, <jk>int</jk></td> 087 * </tr> 088 * <tr> 089 * <td>boolean</td> 090 * <td>Booleans</td> 091 * <td class='code'><jk>true</jk></td> 092 * <td class='code'><xt><boolean></xt>true<xt></boolean></xt></td> 093 * <td class='code'>Boolean</td> 094 * </tr> 095 * <tr> 096 * <td>string</td> 097 * <td>CharSequences</td> 098 * <td class='code'><js>'foobar'</js></td> 099 * <td class='code'><xt><string></xt>foobar<xt></string></xt></td> 100 * <td class='code'>String, StringBuilder</td> 101 * </tr> 102 * </table> 103 * 104 * <p> 105 * In addition, any class types with {@link ObjectSwap ObjectSwaps} associated with them on the registered 106 * bean context can also be passed in. 107 * 108 * <p> 109 * For example, if the {@link TemporalCalendarSwap} transform is used to generalize {@code Calendar} objects to {@code String} 110 * objects. 111 * When registered with this parser, you can construct {@code Calendar} objects from {@code Strings} using the 112 * following syntax... 113 * <p class='bjava'> 114 * Calendar <jv>calendar</jv> = <jv>parser</jv>.parse(<js>"'Sun Mar 03 04:05:06 EST 2001'"</js>, GregorianCalendar.<jk>class</jk>); 115 * </p> 116 * 117 * <p> 118 * If <code>Object.<jk>class</jk></code> is specified as the target type, then the parser automatically determines the 119 * data types and generates the following object types... 120 * <table class='styled'> 121 * <tr><th>JSON type</th><th>Class type</th></tr> 122 * <tr><td>object</td><td>{@link JsonMap}</td></tr> 123 * <tr><td>array</td><td>{@link JsonList}</td></tr> 124 * <tr><td>number</td><td>{@link Number}<br>(depending on length and format, could be {@link Integer}, 125 * {@link Double}, {@link Float}, etc...)</td></tr> 126 * <tr><td>boolean</td><td>{@link Boolean}</td></tr> 127 * <tr><td>string</td><td>{@link String}</td></tr> 128 * </table> 129 * 130 * <h5 class='section'>Notes:</h5><ul> 131 * <li class='note'>This class is thread safe and reusable. 132 * </ul> 133 * 134 * <h5 class='section'>See Also:</h5><ul> 135 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/SerializersAndParsers">Serializers and Parsers</a> 136 137 * </ul> 138 */ 139public class Parser extends BeanContextable { 140 141 //------------------------------------------------------------------------------------------------------------------- 142 // Static 143 //------------------------------------------------------------------------------------------------------------------- 144 145 /** 146 * Creates a new builder for this object. 147 * 148 * @return A new builder. 149 */ 150 public static Builder create() { 151 return new Builder(); 152 } 153 154 //------------------------------------------------------------------------------------------------------------------- 155 // Static 156 //------------------------------------------------------------------------------------------------------------------- 157 158 /** 159 * Represents no Parser. 160 */ 161 public static abstract class Null extends Parser { 162 private Null(Builder builder) { 163 super(builder); 164 } 165 } 166 167 /** 168 * Instantiates a builder of the specified parser class. 169 * 170 * <p> 171 * Looks for a public static method called <c>create</c> that returns an object that can be passed into a public 172 * or protected constructor of the class. 173 * 174 * @param c The builder to create. 175 * @return A new builder. 176 */ 177 public static Builder createParserBuilder(Class<? extends Parser> c) { 178 return (Builder)Context.createBuilder(c); 179 } 180 181 //------------------------------------------------------------------------------------------------------------------- 182 // Builder 183 //------------------------------------------------------------------------------------------------------------------- 184 185 /** 186 * Builder class. 187 */ 188 public static class Builder extends BeanContextable.Builder { 189 190 boolean autoCloseStreams, strict, trimStrings, unbuffered; 191 String consumes; 192 int debugOutputLines; 193 Class<? extends ParserListener> listener; 194 195 /** 196 * Constructor, default settings. 197 */ 198 protected Builder() { 199 autoCloseStreams = env("Parser.autoCloseStreams", false); 200 strict = env("Parser.strict", false); 201 trimStrings = env("Parser.trimStrings", false); 202 unbuffered = env("Parser.unbuffered", false); 203 debugOutputLines = env("Parser.debugOutputLines", 5); 204 listener = null; 205 consumes = null; 206 } 207 208 /** 209 * Copy constructor. 210 * 211 * @param copyFrom The bean to copy from. 212 */ 213 protected Builder(Parser copyFrom) { 214 super(copyFrom); 215 autoCloseStreams = copyFrom.autoCloseStreams; 216 strict = copyFrom.strict; 217 trimStrings = copyFrom.trimStrings; 218 unbuffered = copyFrom.unbuffered; 219 debugOutputLines = copyFrom.debugOutputLines; 220 listener = copyFrom.listener; 221 consumes = copyFrom.consumes; 222 } 223 224 /** 225 * Copy constructor. 226 * 227 * @param copyFrom The builder to copy from. 228 */ 229 protected Builder(Builder copyFrom) { 230 super(copyFrom); 231 autoCloseStreams = copyFrom.autoCloseStreams; 232 strict = copyFrom.strict; 233 trimStrings = copyFrom.trimStrings; 234 unbuffered = copyFrom.unbuffered; 235 debugOutputLines = copyFrom.debugOutputLines; 236 listener = copyFrom.listener; 237 consumes = copyFrom.consumes; 238 } 239 240 @Override /* Context.Builder */ 241 public Builder copy() { 242 return new Builder(this); 243 } 244 245 @Override /* Context.Builder */ 246 public Parser build() { 247 return build(Parser.class); 248 } 249 250 @Override /* Context.Builder */ 251 public HashKey hashKey() { 252 return HashKey.of( 253 super.hashKey(), 254 autoCloseStreams, 255 strict, 256 trimStrings, 257 unbuffered, 258 debugOutputLines, 259 listener, 260 consumes 261 ); 262 } 263 264 //----------------------------------------------------------------------------------------------------------------- 265 // Properties 266 //----------------------------------------------------------------------------------------------------------------- 267 268 /** 269 * Specifies the media type that this parser consumes. 270 * 271 * @param value The value for this setting. 272 * @return This object. 273 */ 274 public Builder consumes(String value) { 275 this.consumes = value; 276 return this; 277 } 278 279 /** 280 * Returns the current value for the 'consumes' property. 281 * 282 * @return The current value for the 'consumes' property. 283 */ 284 public String getConsumes() { 285 return consumes; 286 } 287 288 /** 289 * Auto-close streams. 290 * 291 * <p> 292 * When enabled, <l>InputStreams</l> and <l>Readers</l> passed into parsers will be closed 293 * after parsing is complete. 294 * 295 * <h5 class='section'>Example:</h5> 296 * <p class='bjava'> 297 * <jc>// Create a parser using strict mode.</jc> 298 * ReaderParser <jv>parser</jv> = JsonParser 299 * .<jsm>create</jsm>() 300 * .autoCloseStreams() 301 * .build(); 302 * 303 * Reader <jv>myReader</jv> = <jk>new</jk> FileReader(<js>"/tmp/myfile.json"</js>); 304 * MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<jv>myReader</jv>, MyBean.<jk>class</jk>); 305 * 306 * <jsm>assertTrue</jsm>(<jv>myReader</jv>.isClosed()); 307 * </p> 308 * 309 * @return This object. 310 */ 311 public Builder autoCloseStreams() { 312 return autoCloseStreams(true); 313 } 314 315 /** 316 * Same as {@link #autoCloseStreams()} but allows you to explicitly specify the value. 317 * 318 * @param value The value for this setting. 319 * @return This object. 320 */ 321 public Builder autoCloseStreams(boolean value) { 322 autoCloseStreams = value; 323 return this; 324 } 325 326 /** 327 * Debug output lines. 328 * 329 * <p> 330 * When parse errors occur, this specifies the number of lines of input before and after the 331 * error location to be printed as part of the exception message. 332 * 333 * <h5 class='section'>Example:</h5> 334 * <p class='bjava'> 335 * <jc>// Create a parser whose exceptions print out 100 lines before and after the parse error location.</jc> 336 * ReaderParser <jv>parser</jv> = JsonParser 337 * .<jsm>create</jsm>() 338 * .debug() <jc>// Enable debug mode to capture Reader contents as strings.</jc> 339 * .debugOuputLines(100) 340 * .build(); 341 * 342 * Reader <jv>myReader</jv> = <jk>new</jk> FileReader(<js>"/tmp/mybadfile.json"</js>); 343 * <jk>try</jk> { 344 * <jv>parser</jv>.parse(<jv>myReader</jv>, Object.<jk>class</jk>); 345 * } <jk>catch</jk> (ParseException <jv>e</jv>) { 346 * System.<jsf>err</jsf>.println(<jv>e</jv>.getMessage()); <jc>// Will display 200 lines of the output.</jc> 347 * } 348 * </p> 349 * 350 * @param value 351 * The new value for this property. 352 * <br>The default value is <c>5</c>. 353 * @return This object. 354 */ 355 public Builder debugOutputLines(int value) { 356 debugOutputLines = value; 357 return this; 358 } 359 360 /** 361 * Parser listener. 362 * 363 * <p> 364 * Class used to listen for errors and warnings that occur during parsing. 365 * 366 * <h5 class='section'>Example:</h5> 367 * <p class='bjava'> 368 * <jc>// Define our parser listener.</jc> 369 * <jc>// Simply captures all unknown bean property events.</jc> 370 * <jk>public class</jk> MyParserListener <jk>extends</jk> ParserListener { 371 * 372 * <jc>// A simple property to store our events.</jc> 373 * <jk>public</jk> List<String> <jf>events</jf> = <jk>new</jk> LinkedList<>(); 374 * 375 * <ja>@Override</ja> 376 * <jk>public</jk> <T> <jk>void</jk> onUnknownBeanProperty(ParserSession <jv>session</jv>, String <jv>propertyName</jv>, Class<T> <jv>beanClass</jv>, T <jv>bean</jv>) { 377 * Position <jv>position</jv> = <jv>parser</jv>.getPosition(); 378 * <jf>events</jf>.add(<jv>propertyName</jv> + <js>","</js> + <jv>position</jv>.getLine() + <js>","</js> + <jv>position</jv>.getColumn()); 379 * } 380 * } 381 * 382 * <jc>// Create a parser using our listener.</jc> 383 * ReaderParser <jv>parser</jv> = JsonParser 384 * .<jsm>create</jsm>() 385 * .listener(MyParserListener.<jk>class</jk>) 386 * .build(); 387 * 388 * <jc>// Create a session object.</jc> 389 * <jc>// Needed because listeners are created per-session.</jc> 390 * <jk>try</jk> (ReaderParserSession <jv>session</jv> = <jv>parser</jv>.createSession()) { 391 * 392 * <jc>// Parse some JSON object.</jc> 393 * MyBean <jv>myBean</jv> = <jv>session</jv>.parse(<js>"{...}"</js>, MyBean.<jk>class</jk>); 394 * 395 * <jc>// Get the listener.</jc> 396 * MyParserListener <jv>listener</jv> = <jv>session</jv>.getListener(MyParserListener.<jk>class</jk>); 397 * 398 * <jc>// Dump the results to the console.</jc> 399 * Json5.<jsf>DEFAULT</jsf>.println(<jv>listener</jv>.<jf>events</jf>); 400 * } 401 * </p> 402 * 403 * @param value The new value for this property. 404 * @return This object. 405 */ 406 public Builder listener(Class<? extends ParserListener> value) { 407 listener = value; 408 return this; 409 } 410 411 /** 412 * Strict mode. 413 * 414 * <p> 415 * When enabled, strict mode for the parser is enabled. 416 * 417 * <p> 418 * Strict mode can mean different things for different parsers. 419 * 420 * <table class='styled'> 421 * <tr><th>Parser class</th><th>Strict behavior</th></tr> 422 * <tr> 423 * <td>All reader-based parsers</td> 424 * <td> 425 * When enabled, throws {@link ParseException ParseExceptions} on malformed charset input. 426 * Otherwise, malformed input is ignored. 427 * </td> 428 * </tr> 429 * <tr> 430 * <td>{@link JsonParser}</td> 431 * <td> 432 * When enabled, throws exceptions on the following invalid JSON syntax: 433 * <ul> 434 * <li>Unquoted attributes. 435 * <li>Missing attribute values. 436 * <li>Concatenated strings. 437 * <li>Javascript comments. 438 * <li>Numbers and booleans when Strings are expected. 439 * <li>Numbers valid in Java but not JSON (e.g. octal notation, etc...) 440 * </ul> 441 * </td> 442 * </tr> 443 * </table> 444 * 445 * <h5 class='section'>Example:</h5> 446 * <p class='bjava'> 447 * <jc>// Create a parser using strict mode.</jc> 448 * ReaderParser <jv>parser</jv> = JsonParser 449 * .<jsm>create</jsm>() 450 * .strict() 451 * .build(); 452 * 453 * <jc>// Use it.</jc> 454 * <jk>try</jk> { 455 * String <jv>json</jv> = <js>"{unquotedAttr:'value'}"</js>; 456 * <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>); 457 * } <jk>catch</jk> (ParseException <jv>e</jv>) { 458 * <jsm>assertTrue</jsm>(<jv>e</jv>.getMessage().contains(<js>"Unquoted attribute detected."</js>); 459 * } 460 * </p> 461 * 462 * @return This object. 463 */ 464 public Builder strict() { 465 return strict(true); 466 } 467 468 /** 469 * Same as {@link #strict()} but allows you to explicitly specify the value. 470 * 471 * @param value The value for this setting. 472 * @return This object. 473 */ 474 public Builder strict(boolean value) { 475 strict = value; 476 return this; 477 } 478 479 /** 480 * Trim parsed strings. 481 * 482 * <p> 483 * When enabled, string values will be trimmed of whitespace using {@link String#trim()} before being added to 484 * the POJO. 485 * 486 * <h5 class='section'>Example:</h5> 487 * <p class='bjava'> 488 * <jc>// Create a parser with trim-strings enabled.</jc> 489 * ReaderParser <jv>parser</jv> = JsonParser 490 * .<jsm>create</jsm>() 491 * .trimStrings() 492 * .build(); 493 * 494 * <jc>// Use it.</jc> 495 * String <jv>json</jv> = <js>"{' foo ':' bar '}"</js>; 496 * Map<String,String> <jv>myMap</jv> = <jv>parser</jv>.parse(<jv>json</jv>, HashMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>); 497 * 498 * <jc>// Make sure strings are parsed.</jc> 499 * <jsm>assertEquals</jsm>(<js>"bar"</js>, <jv>myMap</jv>.get(<js>"foo"</js>)); 500 * </p> 501 * 502 * @return This object. 503 */ 504 public Builder trimStrings() { 505 return trimStrings(true); 506 } 507 508 /** 509 * Same as {@link #trimStrings()} but allows you to explicitly specify the value. 510 * 511 * @param value The value for this setting. 512 * @return This object. 513 */ 514 public Builder trimStrings(boolean value) { 515 trimStrings = value; 516 return this; 517 } 518 519 /** 520 * Unbuffered. 521 * 522 * <p> 523 * When enabled, don't use internal buffering during parsing. 524 * 525 * <p> 526 * This is useful in cases when you want to parse the same input stream or reader multiple times 527 * because it may contain multiple independent POJOs to parse. 528 * <br>Buffering would cause the parser to read past the current POJO in the stream. 529 * 530 * <h5 class='section'>Example:</h5> 531 * <p class='bjava'> 532 * <jc>// Create a parser using strict mode.</jc> 533 * ReaderParser <jv>parser</jv> = JsonParser. 534 * .<jsm>create</jsm>() 535 * .unbuffered(<jk>true</jk>) 536 * .build(); 537 * 538 * <jc>// If you're calling parse on the same input multiple times, use a session instead of the parser directly.</jc> 539 * <jc>// It's more efficient because we don't need to recalc the session settings again. </jc> 540 * ReaderParserSession <jv>session</jv> = <jv>parser</jv>.createSession(); 541 * 542 * <jc>// Read input with multiple POJOs</jc> 543 * Reader <jv>json</jv> = <jk>new</jk> StringReader(<js>"{foo:'bar'}{foo:'baz'}"</js>); 544 * MyBean <jv>myBean1</jv> = <jv>session</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>); 545 * MyBean <jv>myBean2</jv> = <jv>session</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>); 546 * </p> 547 * 548 * <h5 class='section'>Notes:</h5><ul> 549 * <li class='note'> 550 * This only allows for multi-input streams for the following parsers: 551 * <ul> 552 * <li class='jc'>{@link JsonParser} 553 * <li class='jc'>{@link UonParser} 554 * </ul> 555 * It has no effect on the following parsers: 556 * <ul> 557 * <li class='jc'>{@link MsgPackParser} - It already doesn't use buffering. 558 * <li class='jc'>{@link XmlParser}, {@link HtmlParser} - These use StAX which doesn't allow for more than one root element anyway. 559 * <li>RDF parsers - These read everything into an internal model before any parsing begins. 560 * </ul> 561 * </ul> 562 * 563 * @return This object. 564 */ 565 public Builder unbuffered() { 566 return unbuffered(true); 567 } 568 569 /** 570 * Same as {@link #unbuffered()} but allows you to explicitly specify the value. 571 * 572 * @param value The value for this setting. 573 * @return This object. 574 */ 575 public Builder unbuffered(boolean value) { 576 unbuffered = value; 577 return this; 578 } 579 @Override /* Overridden from Builder */ 580 public Builder annotations(Annotation...values) { 581 super.annotations(values); 582 return this; 583 } 584 585 @Override /* Overridden from Builder */ 586 public Builder apply(AnnotationWorkList work) { 587 super.apply(work); 588 return this; 589 } 590 591 @Override /* Overridden from Builder */ 592 public Builder applyAnnotations(Object...from) { 593 super.applyAnnotations(from); 594 return this; 595 } 596 597 @Override /* Overridden from Builder */ 598 public Builder applyAnnotations(Class<?>...from) { 599 super.applyAnnotations(from); 600 return this; 601 } 602 603 @Override /* Overridden from Builder */ 604 public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) { 605 super.cache(value); 606 return this; 607 } 608 609 @Override /* Overridden from Builder */ 610 public Builder debug() { 611 super.debug(); 612 return this; 613 } 614 615 @Override /* Overridden from Builder */ 616 public Builder debug(boolean value) { 617 super.debug(value); 618 return this; 619 } 620 621 @Override /* Overridden from Builder */ 622 public Builder impl(Context value) { 623 super.impl(value); 624 return this; 625 } 626 627 @Override /* Overridden from Builder */ 628 public Builder type(Class<? extends org.apache.juneau.Context> value) { 629 super.type(value); 630 return this; 631 } 632 633 @Override /* Overridden from Builder */ 634 public Builder beanClassVisibility(Visibility value) { 635 super.beanClassVisibility(value); 636 return this; 637 } 638 639 @Override /* Overridden from Builder */ 640 public Builder beanConstructorVisibility(Visibility value) { 641 super.beanConstructorVisibility(value); 642 return this; 643 } 644 645 @Override /* Overridden from Builder */ 646 public Builder beanContext(BeanContext value) { 647 super.beanContext(value); 648 return this; 649 } 650 651 @Override /* Overridden from Builder */ 652 public Builder beanContext(BeanContext.Builder value) { 653 super.beanContext(value); 654 return this; 655 } 656 657 @Override /* Overridden from Builder */ 658 public Builder beanDictionary(java.lang.Class<?>...values) { 659 super.beanDictionary(values); 660 return this; 661 } 662 663 @Override /* Overridden from Builder */ 664 public Builder beanFieldVisibility(Visibility value) { 665 super.beanFieldVisibility(value); 666 return this; 667 } 668 669 @Override /* Overridden from Builder */ 670 public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) { 671 super.beanInterceptor(on, value); 672 return this; 673 } 674 675 @Override /* Overridden from Builder */ 676 public Builder beanMapPutReturnsOldValue() { 677 super.beanMapPutReturnsOldValue(); 678 return this; 679 } 680 681 @Override /* Overridden from Builder */ 682 public Builder beanMethodVisibility(Visibility value) { 683 super.beanMethodVisibility(value); 684 return this; 685 } 686 687 @Override /* Overridden from Builder */ 688 public Builder beanProperties(Map<String,Object> values) { 689 super.beanProperties(values); 690 return this; 691 } 692 693 @Override /* Overridden from Builder */ 694 public Builder beanProperties(Class<?> beanClass, String properties) { 695 super.beanProperties(beanClass, properties); 696 return this; 697 } 698 699 @Override /* Overridden from Builder */ 700 public Builder beanProperties(String beanClassName, String properties) { 701 super.beanProperties(beanClassName, properties); 702 return this; 703 } 704 705 @Override /* Overridden from Builder */ 706 public Builder beanPropertiesExcludes(Map<String,Object> values) { 707 super.beanPropertiesExcludes(values); 708 return this; 709 } 710 711 @Override /* Overridden from Builder */ 712 public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) { 713 super.beanPropertiesExcludes(beanClass, properties); 714 return this; 715 } 716 717 @Override /* Overridden from Builder */ 718 public Builder beanPropertiesExcludes(String beanClassName, String properties) { 719 super.beanPropertiesExcludes(beanClassName, properties); 720 return this; 721 } 722 723 @Override /* Overridden from Builder */ 724 public Builder beanPropertiesReadOnly(Map<String,Object> values) { 725 super.beanPropertiesReadOnly(values); 726 return this; 727 } 728 729 @Override /* Overridden from Builder */ 730 public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) { 731 super.beanPropertiesReadOnly(beanClass, properties); 732 return this; 733 } 734 735 @Override /* Overridden from Builder */ 736 public Builder beanPropertiesReadOnly(String beanClassName, String properties) { 737 super.beanPropertiesReadOnly(beanClassName, properties); 738 return this; 739 } 740 741 @Override /* Overridden from Builder */ 742 public Builder beanPropertiesWriteOnly(Map<String,Object> values) { 743 super.beanPropertiesWriteOnly(values); 744 return this; 745 } 746 747 @Override /* Overridden from Builder */ 748 public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) { 749 super.beanPropertiesWriteOnly(beanClass, properties); 750 return this; 751 } 752 753 @Override /* Overridden from Builder */ 754 public Builder beanPropertiesWriteOnly(String beanClassName, String properties) { 755 super.beanPropertiesWriteOnly(beanClassName, properties); 756 return this; 757 } 758 759 @Override /* Overridden from Builder */ 760 public Builder beansRequireDefaultConstructor() { 761 super.beansRequireDefaultConstructor(); 762 return this; 763 } 764 765 @Override /* Overridden from Builder */ 766 public Builder beansRequireSerializable() { 767 super.beansRequireSerializable(); 768 return this; 769 } 770 771 @Override /* Overridden from Builder */ 772 public Builder beansRequireSettersForGetters() { 773 super.beansRequireSettersForGetters(); 774 return this; 775 } 776 777 @Override /* Overridden from Builder */ 778 public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) { 779 super.dictionaryOn(on, values); 780 return this; 781 } 782 783 @Override /* Overridden from Builder */ 784 public Builder disableBeansRequireSomeProperties() { 785 super.disableBeansRequireSomeProperties(); 786 return this; 787 } 788 789 @Override /* Overridden from Builder */ 790 public Builder disableIgnoreMissingSetters() { 791 super.disableIgnoreMissingSetters(); 792 return this; 793 } 794 795 @Override /* Overridden from Builder */ 796 public Builder disableIgnoreTransientFields() { 797 super.disableIgnoreTransientFields(); 798 return this; 799 } 800 801 @Override /* Overridden from Builder */ 802 public Builder disableIgnoreUnknownNullBeanProperties() { 803 super.disableIgnoreUnknownNullBeanProperties(); 804 return this; 805 } 806 807 @Override /* Overridden from Builder */ 808 public Builder disableInterfaceProxies() { 809 super.disableInterfaceProxies(); 810 return this; 811 } 812 813 @Override /* Overridden from Builder */ 814 public <T> Builder example(Class<T> pojoClass, T o) { 815 super.example(pojoClass, o); 816 return this; 817 } 818 819 @Override /* Overridden from Builder */ 820 public <T> Builder example(Class<T> pojoClass, String json) { 821 super.example(pojoClass, json); 822 return this; 823 } 824 825 @Override /* Overridden from Builder */ 826 public Builder findFluentSetters() { 827 super.findFluentSetters(); 828 return this; 829 } 830 831 @Override /* Overridden from Builder */ 832 public Builder findFluentSetters(Class<?> on) { 833 super.findFluentSetters(on); 834 return this; 835 } 836 837 @Override /* Overridden from Builder */ 838 public Builder ignoreInvocationExceptionsOnGetters() { 839 super.ignoreInvocationExceptionsOnGetters(); 840 return this; 841 } 842 843 @Override /* Overridden from Builder */ 844 public Builder ignoreInvocationExceptionsOnSetters() { 845 super.ignoreInvocationExceptionsOnSetters(); 846 return this; 847 } 848 849 @Override /* Overridden from Builder */ 850 public Builder ignoreUnknownBeanProperties() { 851 super.ignoreUnknownBeanProperties(); 852 return this; 853 } 854 855 @Override /* Overridden from Builder */ 856 public Builder ignoreUnknownEnumValues() { 857 super.ignoreUnknownEnumValues(); 858 return this; 859 } 860 861 @Override /* Overridden from Builder */ 862 public Builder implClass(Class<?> interfaceClass, Class<?> implClass) { 863 super.implClass(interfaceClass, implClass); 864 return this; 865 } 866 867 @Override /* Overridden from Builder */ 868 public Builder implClasses(Map<Class<?>,Class<?>> values) { 869 super.implClasses(values); 870 return this; 871 } 872 873 @Override /* Overridden from Builder */ 874 public Builder interfaceClass(Class<?> on, Class<?> value) { 875 super.interfaceClass(on, value); 876 return this; 877 } 878 879 @Override /* Overridden from Builder */ 880 public Builder interfaces(java.lang.Class<?>...value) { 881 super.interfaces(value); 882 return this; 883 } 884 885 @Override /* Overridden from Builder */ 886 public Builder locale(Locale value) { 887 super.locale(value); 888 return this; 889 } 890 891 @Override /* Overridden from Builder */ 892 public Builder mediaType(MediaType value) { 893 super.mediaType(value); 894 return this; 895 } 896 897 @Override /* Overridden from Builder */ 898 public Builder notBeanClasses(java.lang.Class<?>...values) { 899 super.notBeanClasses(values); 900 return this; 901 } 902 903 @Override /* Overridden from Builder */ 904 public Builder notBeanPackages(String...values) { 905 super.notBeanPackages(values); 906 return this; 907 } 908 909 @Override /* Overridden from Builder */ 910 public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) { 911 super.propertyNamer(value); 912 return this; 913 } 914 915 @Override /* Overridden from Builder */ 916 public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) { 917 super.propertyNamer(on, value); 918 return this; 919 } 920 921 @Override /* Overridden from Builder */ 922 public Builder sortProperties() { 923 super.sortProperties(); 924 return this; 925 } 926 927 @Override /* Overridden from Builder */ 928 public Builder sortProperties(java.lang.Class<?>...on) { 929 super.sortProperties(on); 930 return this; 931 } 932 933 @Override /* Overridden from Builder */ 934 public Builder stopClass(Class<?> on, Class<?> value) { 935 super.stopClass(on, value); 936 return this; 937 } 938 939 @Override /* Overridden from Builder */ 940 public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) { 941 super.swap(normalClass, swappedClass, swapFunction); 942 return this; 943 } 944 945 @Override /* Overridden from Builder */ 946 public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) { 947 super.swap(normalClass, swappedClass, swapFunction, unswapFunction); 948 return this; 949 } 950 951 @Override /* Overridden from Builder */ 952 public Builder swaps(Object...values) { 953 super.swaps(values); 954 return this; 955 } 956 957 @Override /* Overridden from Builder */ 958 public Builder swaps(Class<?>...values) { 959 super.swaps(values); 960 return this; 961 } 962 963 @Override /* Overridden from Builder */ 964 public Builder timeZone(TimeZone value) { 965 super.timeZone(value); 966 return this; 967 } 968 969 @Override /* Overridden from Builder */ 970 public Builder typeName(Class<?> on, String value) { 971 super.typeName(on, value); 972 return this; 973 } 974 975 @Override /* Overridden from Builder */ 976 public Builder typePropertyName(String value) { 977 super.typePropertyName(value); 978 return this; 979 } 980 981 @Override /* Overridden from Builder */ 982 public Builder typePropertyName(Class<?> on, String value) { 983 super.typePropertyName(on, value); 984 return this; 985 } 986 987 @Override /* Overridden from Builder */ 988 public Builder useEnumNames() { 989 super.useEnumNames(); 990 return this; 991 } 992 993 @Override /* Overridden from Builder */ 994 public Builder useJavaBeanIntrospector() { 995 super.useJavaBeanIntrospector(); 996 return this; 997 } 998 } 999 //------------------------------------------------------------------------------------------------------------------- 1000 // Instance 1001 //------------------------------------------------------------------------------------------------------------------- 1002 1003 final boolean trimStrings, strict, autoCloseStreams, unbuffered; 1004 final int debugOutputLines; 1005 final String consumes; 1006 final Class<? extends ParserListener> listener; 1007 1008 /** General parser properties currently set on this parser. */ 1009 private final MediaType[] consumesArray; 1010 1011 /** 1012 * Constructor. 1013 * 1014 * @param builder The builder this object. 1015 */ 1016 protected Parser(Builder builder) { 1017 super(builder); 1018 1019 consumes = builder.consumes; 1020 trimStrings = builder.trimStrings; 1021 strict = builder.strict; 1022 autoCloseStreams = builder.autoCloseStreams; 1023 debugOutputLines = builder.debugOutputLines; 1024 unbuffered = builder.unbuffered; 1025 listener = builder.listener; 1026 1027 String[] _consumes = splita(consumes != null ? consumes : ""); 1028 this.consumesArray = new MediaType[_consumes.length]; 1029 for (int i = 0; i < _consumes.length; i++) { 1030 this.consumesArray[i] = MediaType.of(_consumes[i]); 1031 } 1032 } 1033 1034 @Override /* Context */ 1035 public Builder copy() { 1036 return new Builder(this); 1037 } 1038 1039 //----------------------------------------------------------------------------------------------------------------- 1040 // Abstract methods 1041 //----------------------------------------------------------------------------------------------------------------- 1042 1043 /** 1044 * Returns <jk>true</jk> if this parser subclasses from {@link ReaderParser}. 1045 * 1046 * @return <jk>true</jk> if this parser subclasses from {@link ReaderParser}. 1047 */ 1048 public boolean isReaderParser() { 1049 return true; 1050 } 1051 1052 //----------------------------------------------------------------------------------------------------------------- 1053 // Other methods 1054 //----------------------------------------------------------------------------------------------------------------- 1055 1056 /** 1057 * Parses input into the specified object type. 1058 * 1059 * <p> 1060 * The type can be a simple type (e.g. beans, strings, numbers) or parameterized type (collections/maps). 1061 * 1062 * <h5 class='section'>Examples:</h5> 1063 * <p class='bjava'> 1064 * ReaderParser <jv>parser</jv> = JsonParser.<jsf>DEFAULT</jsf>; 1065 * 1066 * <jc>// Parse into a linked-list of strings.</jc> 1067 * List <jv>list1</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>, String.<jk>class</jk>); 1068 * 1069 * <jc>// Parse into a linked-list of beans.</jc> 1070 * List <jv>list2</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>); 1071 * 1072 * <jc>// Parse into a linked-list of linked-lists of strings.</jc> 1073 * List <jv>list3</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>); 1074 * 1075 * <jc>// Parse into a map of string keys/values.</jc> 1076 * Map <jv>map1</jv> = <jv>parser</jv>.parse(<jv>json</jv>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>); 1077 * 1078 * <jc>// Parse into a map containing string keys and values of lists containing beans.</jc> 1079 * Map <jv>map2</jv> = <jv>parser</jv>.parse(<jv>json</jv>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>); 1080 * </p> 1081 * 1082 * <p> 1083 * <c>Collection</c> classes are assumed to be followed by zero or one objects indicating the element type. 1084 * 1085 * <p> 1086 * <c>Map</c> classes are assumed to be followed by zero or two meta objects indicating the key and value types. 1087 * 1088 * <p> 1089 * The array can be arbitrarily long to indicate arbitrarily complex data structures. 1090 * 1091 * <h5 class='section'>Notes:</h5><ul> 1092 * <li class='note'> 1093 * Use the {@link #parse(Object, Class)} method instead if you don't need a parameterized map/collection. 1094 * </ul> 1095 * 1096 * @param <T> The class type of the object to create. 1097 * @param input 1098 * The input. 1099 * <br>Character-based parsers can handle the following input class types: 1100 * <ul> 1101 * <li><jk>null</jk> 1102 * <li>{@link Reader} 1103 * <li>{@link CharSequence} 1104 * <li>{@link InputStream} containing UTF-8 encoded text (or charset defined by 1105 * {@link ReaderParser.Builder#streamCharset(Charset)} property value). 1106 * <li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or charset defined by 1107 * {@link ReaderParser.Builder#streamCharset(Charset)} property value). 1108 * <li>{@link File} containing system encoded text (or charset defined by 1109 * {@link ReaderParser.Builder#fileCharset(Charset)} property value). 1110 * </ul> 1111 * <br>Stream-based parsers can handle the following input class types: 1112 * <ul> 1113 * <li><jk>null</jk> 1114 * <li>{@link InputStream} 1115 * <li><code><jk>byte</jk>[]</code> 1116 * <li>{@link File} 1117 * <li>{@link CharSequence} containing encoded bytes according to the {@link InputStreamParser.Builder#binaryFormat(BinaryFormat)} setting. 1118 * </ul> 1119 * @param type 1120 * The object type to create. 1121 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 1122 * @param args 1123 * The type arguments of the class if it's a collection or map. 1124 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 1125 * <br>Ignored if the main type is not a map or collection. 1126 * @return The parsed object. 1127 * @throws ParseException Malformed input encountered. 1128 * @throws IOException Thrown by underlying stream. 1129 * @see BeanSession#getClassMeta(Type,Type...) for argument syntax for maps and collections. 1130 */ 1131 public final <T> T parse(Object input, Type type, Type...args) throws ParseException, IOException { 1132 return getSession().parse(input, type, args); 1133 } 1134 1135 /** 1136 * Same as {@link #parse(Object, Type, Type...)} but since it's a {@link String} input doesn't throw an {@link IOException}. 1137 * 1138 * @param <T> The class type of the object being created. 1139 * @param input 1140 * The input. 1141 * See {@link #parse(Object, Type, Type...)} for details. 1142 * @param type 1143 * The object type to create. 1144 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 1145 * @param args 1146 * The type arguments of the class if it's a collection or map. 1147 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 1148 * <br>Ignored if the main type is not a map or collection. 1149 * @return The parsed object. 1150 * @throws ParseException Malformed input encountered. 1151 */ 1152 public final <T> T parse(String input, Type type, Type...args) throws ParseException { 1153 return getSession().parse(input, type, args); 1154 } 1155 1156 /** 1157 * Same as {@link #parse(Object, Type, Type...)} except optimized for a non-parameterized class. 1158 * 1159 * <p> 1160 * This is the preferred parse method for simple types since you don't need to cast the results. 1161 * 1162 * <h5 class='section'>Examples:</h5> 1163 * <p class='bjava'> 1164 * ReaderParser <jv>parser</jv> = JsonParser.<jsf>DEFAULT</jsf>; 1165 * 1166 * <jc>// Parse into a string.</jc> 1167 * String <jv>string</jv> = <jv>parser</jv>.parse(<jv>json</jv>, String.<jk>class</jk>); 1168 * 1169 * <jc>// Parse into a bean.</jc> 1170 * MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>); 1171 * 1172 * <jc>// Parse into a bean array.</jc> 1173 * MyBean[] <jv>beanArray</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean[].<jk>class</jk>); 1174 * 1175 * <jc>// Parse into a linked-list of objects.</jc> 1176 * List <jv>list</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>); 1177 * 1178 * <jc>// Parse into a map of object keys/values.</jc> 1179 * Map <jv>map</jv> = <jv>parser</jv>.parse(<jv>json</jv>, TreeMap.<jk>class</jk>); 1180 * </p> 1181 * 1182 * @param <T> The class type of the object being created. 1183 * @param input 1184 * The input. 1185 * See {@link #parse(Object, Type, Type...)} for details. 1186 * @param type The object type to create. 1187 * @return The parsed object. 1188 * @throws ParseException Malformed input encountered. 1189 * @throws IOException Thrown by the underlying stream. 1190 */ 1191 public final <T> T parse(Object input, Class<T> type) throws ParseException, IOException { 1192 return getSession().parse(input, type); 1193 } 1194 1195 /** 1196 * Same as {@link #parse(Object, Class)} but since it's a {@link String} input doesn't throw an {@link IOException}. 1197 * 1198 * @param <T> The class type of the object being created. 1199 * @param input 1200 * The input. 1201 * See {@link #parse(Object, Type, Type...)} for details. 1202 * @param type The object type to create. 1203 * @return The parsed object. 1204 * @throws ParseException Malformed input encountered. 1205 */ 1206 public final <T> T parse(String input, Class<T> type) throws ParseException { 1207 return getSession().parse(input, type); 1208 } 1209 1210 /** 1211 * Same as {@link #parse(Object, Type, Type...)} except the type has already been converted into a {@link ClassMeta} 1212 * object. 1213 * 1214 * <p> 1215 * This is mostly an internal method used by the framework. 1216 * 1217 * @param <T> The class type of the object being created. 1218 * @param input 1219 * The input. 1220 * See {@link #parse(Object, Type, Type...)} for details. 1221 * @param type The object type to create. 1222 * @return The parsed object. 1223 * @throws ParseException Malformed input encountered. 1224 * @throws IOException Thrown by the underlying stream. 1225 */ 1226 public final <T> T parse(Object input, ClassMeta<T> type) throws ParseException, IOException { 1227 return getSession().parse(input, type); 1228 } 1229 1230 /** 1231 * Same as {@link #parse(Object, ClassMeta)} but since it's a {@link String} input doesn't throw an {@link IOException}. 1232 * 1233 * @param <T> The class type of the object being created. 1234 * @param input 1235 * The input. 1236 * See {@link #parse(Object, Type, Type...)} for details. 1237 * @param type The object type to create. 1238 * @return The parsed object. 1239 * @throws ParseException Malformed input encountered. 1240 */ 1241 public final <T> T parse(String input, ClassMeta<T> type) throws ParseException { 1242 return getSession().parse(input, type); 1243 } 1244 1245 @Override /* Context */ 1246 public ParserSession.Builder createSession() { 1247 return ParserSession.create(this); 1248 } 1249 1250 @Override /* Context */ 1251 public ParserSession getSession() { 1252 return createSession().build(); 1253 } 1254 1255 /** 1256 * Workhorse method. 1257 * 1258 * <p> 1259 * Subclasses are expected to either implement this method or {@link ParserSession#doParse(ParserPipe, ClassMeta)}. 1260 * 1261 * @param session The current session. 1262 * @param pipe Where to get the input from. 1263 * @param type 1264 * The class type of the object to create. 1265 * If <jk>null</jk> or <code>Object.<jk>class</jk></code>, object type is based on what's being parsed. 1266 * For example, when parsing JSON text, it may return a <c>String</c>, <c>Number</c>, 1267 * <c>JsonMap</c>, etc... 1268 * @param <T> The class type of the object to create. 1269 * @return The parsed object. 1270 * @throws IOException Thrown by underlying stream. 1271 * @throws ParseException Malformed input encountered. 1272 * @throws ExecutableException Exception occurred on invoked constructor/method/field. 1273 */ 1274 public <T> T doParse(ParserSession session, ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException { 1275 throw new UnsupportedOperationException(); 1276 } 1277 1278 //----------------------------------------------------------------------------------------------------------------- 1279 // Optional methods 1280 //----------------------------------------------------------------------------------------------------------------- 1281 1282 /** 1283 * Parses the contents of the specified reader and loads the results into the specified map. 1284 * 1285 * <p> 1286 * Reader must contain something that serializes to a map (such as text containing a JSON object). 1287 * 1288 * <p> 1289 * Used in the following locations: 1290 * <ul class='spaced-list'> 1291 * <li> 1292 * The various character-based constructors in {@link JsonMap} (e.g. 1293 * {@link JsonMap#JsonMap(CharSequence,Parser)}). 1294 * </ul> 1295 * 1296 * @param <K> The key class type. 1297 * @param <V> The value class type. 1298 * @param input The input. See {@link #parse(Object, ClassMeta)} for supported input types. 1299 * @param m The map being loaded. 1300 * @param keyType The class type of the keys, or <jk>null</jk> to default to <code>String.<jk>class</jk></code>. 1301 * @param valueType The class type of the values, or <jk>null</jk> to default to whatever is being parsed. 1302 * @return The same map that was passed in to allow this method to be chained. 1303 * @throws ParseException Malformed input encountered. 1304 * @throws UnsupportedOperationException If not implemented. 1305 */ 1306 public final <K,V> Map<K,V> parseIntoMap(Object input, Map<K,V> m, Type keyType, Type valueType) throws ParseException { 1307 return getSession().parseIntoMap(input, m, keyType, valueType); 1308 } 1309 1310 /** 1311 * Parses the contents of the specified reader and loads the results into the specified collection. 1312 * 1313 * <p> 1314 * Used in the following locations: 1315 * <ul class='spaced-list'> 1316 * <li> 1317 * The various character-based constructors in {@link JsonList} (e.g. 1318 * {@link JsonList#JsonList(CharSequence,Parser)}. 1319 * </ul> 1320 * 1321 * @param <E> The element class type. 1322 * @param input The input. See {@link #parse(Object, ClassMeta)} for supported input types. 1323 * @param c The collection being loaded. 1324 * @param elementType The class type of the elements, or <jk>null</jk> to default to whatever is being parsed. 1325 * @return The same collection that was passed in to allow this method to be chained. 1326 * @throws ParseException Malformed input encountered. 1327 * @throws UnsupportedOperationException If not implemented. 1328 */ 1329 public final <E> Collection<E> parseIntoCollection(Object input, Collection<E> c, Type elementType) throws ParseException { 1330 return getSession().parseIntoCollection(input, c, elementType); 1331 } 1332 1333 /** 1334 * Parses the specified array input with each entry in the object defined by the {@code argTypes} 1335 * argument. 1336 * 1337 * <p> 1338 * Used for converting arrays (e.g. <js>"[arg1,arg2,...]"</js>) into an {@code Object[]} that can be passed 1339 * to the {@code Method.invoke(target, args)} method. 1340 * 1341 * <p> 1342 * Used in the following locations: 1343 * <ul class='spaced-list'> 1344 * <li> 1345 * Used to parse argument strings in the {@link ObjectIntrospector#invokeMethod(Method, Reader)} method. 1346 * </ul> 1347 * 1348 * @param input The input. Subclasses can support different input types. 1349 * @param argTypes Specifies the type of objects to create for each entry in the array. 1350 * @return An array of parsed objects. 1351 * @throws ParseException Malformed input encountered. 1352 */ 1353 public final Object[] parseArgs(Object input, Type[] argTypes) throws ParseException { 1354 if (argTypes == null || argTypes.length == 0) 1355 return new Object[0]; 1356 return getSession().parseArgs(input, argTypes); 1357 } 1358 1359 1360 //----------------------------------------------------------------------------------------------------------------- 1361 // Other methods 1362 //----------------------------------------------------------------------------------------------------------------- 1363 1364 /** 1365 * Returns the media types handled based on the values passed to the <c>consumes</c> constructor parameter. 1366 * 1367 * @return The list of media types. Never <jk>null</jk>. 1368 */ 1369 public final List<MediaType> getMediaTypes() { 1370 return Utils.alist(consumesArray); 1371 } 1372 1373 /** 1374 * Returns the first media type handled based on the values passed to the <c>consumes</c> constructor parameter. 1375 * 1376 * @return The media type. 1377 */ 1378 public final MediaType getPrimaryMediaType() { 1379 return consumesArray == null || consumesArray.length == 0 ? null : consumesArray[0]; 1380 } 1381 1382 /** 1383 * Returns <jk>true</jk> if this parser can handle the specified content type. 1384 * 1385 * @param contentType The content type to test. 1386 * @return <jk>true</jk> if this parser can handle the specified content type. 1387 */ 1388 public boolean canHandle(String contentType) { 1389 if (contentType != null) 1390 for (MediaType mt : getMediaTypes()) 1391 if (contentType.equals(mt.toString())) 1392 return true; 1393 return false; 1394 } 1395 1396 //----------------------------------------------------------------------------------------------------------------- 1397 // Properties 1398 //----------------------------------------------------------------------------------------------------------------- 1399 1400 /** 1401 * Auto-close streams. 1402 * 1403 * @see Parser.Builder#autoCloseStreams() 1404 * @return 1405 * <jk>true</jk> if <l>InputStreams</l> and <l>Readers</l> passed into parsers will be closed 1406 * after parsing is complete. 1407 */ 1408 protected final boolean isAutoCloseStreams() { 1409 return autoCloseStreams; 1410 } 1411 1412 /** 1413 * Debug output lines. 1414 * 1415 * @see Parser.Builder#debugOutputLines(int) 1416 * @return 1417 * The number of lines of input before and after the error location to be printed as part of the exception message. 1418 */ 1419 protected final int getDebugOutputLines() { 1420 return debugOutputLines; 1421 } 1422 1423 /** 1424 * Parser listener. 1425 * 1426 * @see Parser.Builder#listener(Class) 1427 * @return 1428 * Class used to listen for errors and warnings that occur during parsing. 1429 */ 1430 protected final Class<? extends ParserListener> getListener() { 1431 return listener; 1432 } 1433 1434 /** 1435 * Strict mode. 1436 * 1437 * @see Parser.Builder#strict() 1438 * @return 1439 * <jk>true</jk> if strict mode for the parser is enabled. 1440 */ 1441 protected final boolean isStrict() { 1442 return strict; 1443 } 1444 1445 /** 1446 * Trim parsed strings. 1447 * 1448 * @see Parser.Builder#trimStrings() 1449 * @return 1450 * <jk>true</jk> if string values will be trimmed of whitespace using {@link String#trim()} before being added to 1451 * the POJO. 1452 */ 1453 protected final boolean isTrimStrings() { 1454 return trimStrings; 1455 } 1456 1457 /** 1458 * Unbuffered. 1459 * 1460 * @see Parser.Builder#unbuffered() 1461 * @return 1462 * <jk>true</jk> if parsers don't use internal buffering during parsing. 1463 */ 1464 protected final boolean isUnbuffered() { 1465 return unbuffered; 1466 } 1467 1468 //----------------------------------------------------------------------------------------------------------------- 1469 // Other methods 1470 //----------------------------------------------------------------------------------------------------------------- 1471 1472 @Override /* Context */ 1473 protected JsonMap properties() { 1474 return filteredMap() 1475 .append("autoCloseStreams", autoCloseStreams) 1476 .append("debugOutputLines", debugOutputLines) 1477 .append("listener", listener) 1478 .append("strict", strict) 1479 .append("trimStrings", trimStrings) 1480 .append("unbuffered", unbuffered); 1481 } 1482}