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