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.xml; 018 019import static org.apache.juneau.commons.utils.AssertionUtils.*; 020import static org.apache.juneau.commons.utils.ThrowableUtils.*; 021import static org.apache.juneau.commons.utils.Utils.*; 022 023import java.lang.annotation.*; 024import java.nio.charset.*; 025import java.util.*; 026import java.util.concurrent.*; 027 028import javax.xml.stream.*; 029import javax.xml.stream.util.*; 030 031import org.apache.juneau.*; 032import org.apache.juneau.collections.*; 033import org.apache.juneau.commons.collections.*; 034import org.apache.juneau.commons.function.*; 035import org.apache.juneau.commons.reflect.*; 036import org.apache.juneau.parser.*; 037 038/** 039 * Parses text generated by the {@link XmlSerializer} class back into a POJO model. 040 * 041 * <h5 class='topic'>Media types</h5> 042 * <p> 043 * Handles <c>Content-Type</c> types: <bc>text/xml</bc> 044 * 045 * <h5 class='topic'>Description</h5> 046 * <p> 047 * See the {@link XmlSerializer} class for a description of Juneau-generated XML. 048 * 049 * <h5 class='section'>Notes:</h5><ul> 050 * <li class='note'>This class is thread safe and reusable. 051 * </ul> 052 * 053 * <h5 class='section'>See Also:</h5><ul> 054 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/XmlBasics">XML Basics</a> 055 056 * </ul> 057 */ 058public class XmlParser extends ReaderParser implements XmlMetaProvider { 059 /** 060 * Builder class. 061 */ 062 public static class Builder extends ReaderParser.Builder { 063 064 private static final Cache<HashKey,XmlParser> CACHE = Cache.of(HashKey.class, XmlParser.class).build(); 065 066 private boolean preserveRootElement; 067 private boolean validating; 068 private Class<? extends XMLEventAllocator> eventAllocator; 069 private Class<? extends XMLReporter> reporter; 070 private Class<? extends XMLResolver> resolver; 071 072 /** 073 * Constructor, default settings. 074 */ 075 protected Builder() { 076 consumes("text/xml,application/xml"); 077 preserveRootElement = env("XmlParser.preserveRootElement", false); 078 validating = env("XmlParser.validating", false); 079 eventAllocator = null; 080 reporter = null; 081 resolver = null; 082 } 083 084 /** 085 * Copy constructor. 086 * 087 * @param copyFrom The builder to copy from. 088 * <br>Cannot be <jk>null</jk>. 089 */ 090 protected Builder(Builder copyFrom) { 091 super(assertArgNotNull("copyFrom", copyFrom)); 092 preserveRootElement = copyFrom.preserveRootElement; 093 validating = copyFrom.validating; 094 eventAllocator = copyFrom.eventAllocator; 095 reporter = copyFrom.reporter; 096 resolver = copyFrom.resolver; 097 } 098 099 /** 100 * Copy constructor. 101 * 102 * @param copyFrom The bean to copy from. 103 * <br>Cannot be <jk>null</jk>. 104 */ 105 protected Builder(XmlParser copyFrom) { 106 super(assertArgNotNull("copyFrom", copyFrom)); 107 preserveRootElement = copyFrom.preserveRootElement; 108 validating = copyFrom.validating; 109 eventAllocator = copyFrom.eventAllocator; 110 reporter = copyFrom.reporter; 111 resolver = copyFrom.resolver; 112 } 113 114 @Override /* Overridden from Builder */ 115 public Builder annotations(Annotation...values) { 116 super.annotations(values); 117 return this; 118 } 119 120 @Override /* Overridden from Builder */ 121 public Builder apply(AnnotationWorkList work) { 122 super.apply(work); 123 return this; 124 } 125 126 @Override /* Overridden from Builder */ 127 public Builder applyAnnotations(Class<?>...from) { 128 super.applyAnnotations(from); 129 return this; 130 } 131 132 @Override /* Overridden from Builder */ 133 public Builder applyAnnotations(Object...from) { 134 super.applyAnnotations(from); 135 return this; 136 } 137 138 @Override /* Overridden from Builder */ 139 public Builder autoCloseStreams() { 140 super.autoCloseStreams(); 141 return this; 142 } 143 144 @Override /* Overridden from Builder */ 145 public Builder autoCloseStreams(boolean value) { 146 super.autoCloseStreams(value); 147 return this; 148 } 149 150 @Override /* Overridden from Builder */ 151 public Builder beanClassVisibility(Visibility value) { 152 super.beanClassVisibility(value); 153 return this; 154 } 155 156 @Override /* Overridden from Builder */ 157 public Builder beanConstructorVisibility(Visibility value) { 158 super.beanConstructorVisibility(value); 159 return this; 160 } 161 162 @Override /* Overridden from Builder */ 163 public Builder beanContext(BeanContext value) { 164 super.beanContext(value); 165 return this; 166 } 167 168 @Override /* Overridden from Builder */ 169 public Builder beanContext(BeanContext.Builder value) { 170 super.beanContext(value); 171 return this; 172 } 173 174 @Override /* Overridden from Builder */ 175 public Builder beanDictionary(java.lang.Class<?>...values) { 176 super.beanDictionary(values); 177 return this; 178 } 179 180 @Override /* Overridden from Builder */ 181 public Builder beanFieldVisibility(Visibility value) { 182 super.beanFieldVisibility(value); 183 return this; 184 } 185 186 @Override /* Overridden from Builder */ 187 public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) { 188 super.beanInterceptor(on, value); 189 return this; 190 } 191 192 @Override /* Overridden from Builder */ 193 public Builder beanMapPutReturnsOldValue() { 194 super.beanMapPutReturnsOldValue(); 195 return this; 196 } 197 198 @Override /* Overridden from Builder */ 199 public Builder beanMethodVisibility(Visibility value) { 200 super.beanMethodVisibility(value); 201 return this; 202 } 203 204 @Override /* Overridden from Builder */ 205 public Builder beanProperties(Class<?> beanClass, String properties) { 206 super.beanProperties(beanClass, properties); 207 return this; 208 } 209 210 @Override /* Overridden from Builder */ 211 public Builder beanProperties(Map<String,Object> values) { 212 super.beanProperties(values); 213 return this; 214 } 215 216 @Override /* Overridden from Builder */ 217 public Builder beanProperties(String beanClassName, String properties) { 218 super.beanProperties(beanClassName, properties); 219 return this; 220 } 221 222 @Override /* Overridden from Builder */ 223 public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) { 224 super.beanPropertiesExcludes(beanClass, properties); 225 return this; 226 } 227 228 @Override /* Overridden from Builder */ 229 public Builder beanPropertiesExcludes(Map<String,Object> values) { 230 super.beanPropertiesExcludes(values); 231 return this; 232 } 233 234 @Override /* Overridden from Builder */ 235 public Builder beanPropertiesExcludes(String beanClassName, String properties) { 236 super.beanPropertiesExcludes(beanClassName, properties); 237 return this; 238 } 239 240 @Override /* Overridden from Builder */ 241 public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) { 242 super.beanPropertiesReadOnly(beanClass, properties); 243 return this; 244 } 245 246 @Override /* Overridden from Builder */ 247 public Builder beanPropertiesReadOnly(Map<String,Object> values) { 248 super.beanPropertiesReadOnly(values); 249 return this; 250 } 251 252 @Override /* Overridden from Builder */ 253 public Builder beanPropertiesReadOnly(String beanClassName, String properties) { 254 super.beanPropertiesReadOnly(beanClassName, properties); 255 return this; 256 } 257 258 @Override /* Overridden from Builder */ 259 public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) { 260 super.beanPropertiesWriteOnly(beanClass, properties); 261 return this; 262 } 263 264 @Override /* Overridden from Builder */ 265 public Builder beanPropertiesWriteOnly(Map<String,Object> values) { 266 super.beanPropertiesWriteOnly(values); 267 return this; 268 } 269 270 @Override /* Overridden from Builder */ 271 public Builder beanPropertiesWriteOnly(String beanClassName, String properties) { 272 super.beanPropertiesWriteOnly(beanClassName, properties); 273 return this; 274 } 275 276 @Override /* Overridden from Builder */ 277 public Builder beansRequireDefaultConstructor() { 278 super.beansRequireDefaultConstructor(); 279 return this; 280 } 281 282 @Override /* Overridden from Builder */ 283 public Builder beansRequireSerializable() { 284 super.beansRequireSerializable(); 285 return this; 286 } 287 288 @Override /* Overridden from Builder */ 289 public Builder beansRequireSettersForGetters() { 290 super.beansRequireSettersForGetters(); 291 return this; 292 } 293 294 @Override /* Overridden from Context.Builder */ 295 public XmlParser build() { 296 return cache(CACHE).build(XmlParser.class); 297 } 298 299 @Override /* Overridden from Builder */ 300 public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) { 301 super.cache(value); 302 return this; 303 } 304 305 @Override /* Overridden from Builder */ 306 public Builder consumes(String value) { 307 super.consumes(value); 308 return this; 309 } 310 311 @Override /* Overridden from Context.Builder */ 312 public Builder copy() { 313 return new Builder(this); 314 } 315 316 @Override /* Overridden from Builder */ 317 public Builder debug() { 318 super.debug(); 319 return this; 320 } 321 322 @Override /* Overridden from Builder */ 323 public Builder debug(boolean value) { 324 super.debug(value); 325 return this; 326 } 327 328 @Override /* Overridden from Builder */ 329 public Builder debugOutputLines(int value) { 330 super.debugOutputLines(value); 331 return this; 332 } 333 334 @Override /* Overridden from Builder */ 335 public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) { 336 super.dictionaryOn(on, values); 337 return this; 338 } 339 340 @Override /* Overridden from Builder */ 341 public Builder disableBeansRequireSomeProperties() { 342 super.disableBeansRequireSomeProperties(); 343 return this; 344 } 345 346 @Override /* Overridden from Builder */ 347 public Builder disableIgnoreMissingSetters() { 348 super.disableIgnoreMissingSetters(); 349 return this; 350 } 351 352 @Override /* Overridden from Builder */ 353 public Builder disableIgnoreTransientFields() { 354 super.disableIgnoreTransientFields(); 355 return this; 356 } 357 358 @Override /* Overridden from Builder */ 359 public Builder disableIgnoreUnknownNullBeanProperties() { 360 super.disableIgnoreUnknownNullBeanProperties(); 361 return this; 362 } 363 364 @Override /* Overridden from Builder */ 365 public Builder disableInterfaceProxies() { 366 super.disableInterfaceProxies(); 367 return this; 368 } 369 370 /** 371 * XML event allocator. 372 * 373 * <p> 374 * Associates an {@link XMLEventAllocator} with this parser. 375 * 376 * @param value The new value for this property. 377 * <br>Can be <jk>null</jk> (no event allocator will be used). 378 * @return This object. 379 */ 380 public Builder eventAllocator(Class<? extends XMLEventAllocator> value) { 381 eventAllocator = value; 382 return this; 383 } 384 385 @Override /* Overridden from Builder */ 386 public <T> Builder example(Class<T> pojoClass, String json) { 387 super.example(pojoClass, json); 388 return this; 389 } 390 391 @Override /* Overridden from Builder */ 392 public <T> Builder example(Class<T> pojoClass, T o) { 393 super.example(pojoClass, o); 394 return this; 395 } 396 397 @Override /* Overridden from Builder */ 398 public Builder fileCharset(Charset value) { 399 super.fileCharset(value); 400 return this; 401 } 402 403 @Override /* Overridden from Builder */ 404 public Builder findFluentSetters() { 405 super.findFluentSetters(); 406 return this; 407 } 408 409 @Override /* Overridden from Builder */ 410 public Builder findFluentSetters(Class<?> on) { 411 super.findFluentSetters(on); 412 return this; 413 } 414 415 @Override /* Overridden from Context.Builder */ 416 public HashKey hashKey() { 417 // @formatter:off 418 return HashKey.of( 419 super.hashKey(), 420 preserveRootElement, 421 validating, 422 eventAllocator, 423 reporter, 424 resolver 425 ); 426 // @formatter:on 427 } 428 429 @Override /* Overridden from Builder */ 430 public Builder ignoreInvocationExceptionsOnGetters() { 431 super.ignoreInvocationExceptionsOnGetters(); 432 return this; 433 } 434 435 @Override /* Overridden from Builder */ 436 public Builder ignoreInvocationExceptionsOnSetters() { 437 super.ignoreInvocationExceptionsOnSetters(); 438 return this; 439 } 440 441 @Override /* Overridden from Builder */ 442 public Builder ignoreUnknownBeanProperties() { 443 super.ignoreUnknownBeanProperties(); 444 return this; 445 } 446 447 @Override /* Overridden from Builder */ 448 public Builder ignoreUnknownEnumValues() { 449 super.ignoreUnknownEnumValues(); 450 return this; 451 } 452 453 @Override /* Overridden from Builder */ 454 public Builder impl(Context value) { 455 super.impl(value); 456 return this; 457 } 458 459 @Override /* Overridden from Builder */ 460 public Builder implClass(Class<?> interfaceClass, Class<?> implClass) { 461 super.implClass(interfaceClass, implClass); 462 return this; 463 } 464 465 @Override /* Overridden from Builder */ 466 public Builder implClasses(Map<Class<?>,Class<?>> values) { 467 super.implClasses(values); 468 return this; 469 } 470 471 @Override /* Overridden from Builder */ 472 public Builder interfaceClass(Class<?> on, Class<?> value) { 473 super.interfaceClass(on, value); 474 return this; 475 } 476 477 @Override /* Overridden from Builder */ 478 public Builder interfaces(java.lang.Class<?>...value) { 479 super.interfaces(value); 480 return this; 481 } 482 483 @Override /* Overridden from Builder */ 484 public Builder listener(Class<? extends org.apache.juneau.parser.ParserListener> value) { 485 super.listener(value); 486 return this; 487 } 488 489 @Override /* Overridden from Builder */ 490 public Builder locale(Locale value) { 491 super.locale(value); 492 return this; 493 } 494 495 @Override /* Overridden from Builder */ 496 public Builder mediaType(MediaType value) { 497 super.mediaType(value); 498 return this; 499 } 500 501 @Override /* Overridden from Builder */ 502 public Builder notBeanClasses(java.lang.Class<?>...values) { 503 super.notBeanClasses(values); 504 return this; 505 } 506 507 @Override /* Overridden from Builder */ 508 public Builder notBeanPackages(String...values) { 509 super.notBeanPackages(values); 510 return this; 511 } 512 513 /** 514 * Preserve root element during generalized parsing. 515 * 516 * <p> 517 * When enabled, when parsing into a generic {@link JsonMap}, the map will contain a single entry whose key 518 * is the root element name. 519 * 520 * <h5 class='section'>Example:</h5> 521 * <p class='bjava'> 522 * <jc>// Parser with preserve-root-element.</jc> 523 * ReaderParser <jv>parser1</jv> = XmlParser 524 * .<jsm>create</jsm>() 525 * .preserveRootElement() 526 * .build(); 527 * 528 * <jc>// Parser without preserve-root-element (the default behavior).</jc> 529 * ReaderParser <jv>parser2</jv> = XmlParser 530 * .<jsm>create</jsm>() 531 * .build(); 532 * 533 * String <jv>xml</jv> = <js>"<root><a>foobar</a></root>"</js>; 534 * 535 * <jc>// Produces: "{ root: { a:'foobar' }}"</jc> 536 * JsonMap <jv>map1</jv> = <jv>parser1</jv>.parse(<jv>xml</jv>, JsonMap.<jk>class</jk>); 537 * 538 * <jc>// Produces: "{ a:'foobar' }"</jc> 539 * JsonMap <jv>map2</jv> = <jv>parser2</jv>.parse(<jv>xml</jv>, JsonMap.<jk>class</jk>); 540 * </p> 541 * 542 * @return This object. 543 */ 544 public Builder preserveRootElement() { 545 return preserveRootElement(true); 546 } 547 548 /** 549 * Same as {@link #preserveRootElement()} but allows you to explicitly specify the value. 550 * 551 * @param value The value for this setting. 552 * @return This object. 553 */ 554 public Builder preserveRootElement(boolean value) { 555 preserveRootElement = value; 556 return this; 557 } 558 559 @Override /* Overridden from Builder */ 560 public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) { 561 super.propertyNamer(on, value); 562 return this; 563 } 564 565 @Override /* Overridden from Builder */ 566 public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) { 567 super.propertyNamer(value); 568 return this; 569 } 570 571 /** 572 * XML reporter. 573 * 574 * <p> 575 * Associates an {@link XMLReporter} with this parser. 576 * 577 * @param value The new value for this property. 578 * <br>Can be <jk>null</jk> (no reporter will be used). 579 * @return This object. 580 */ 581 public Builder reporter(Class<? extends XMLReporter> value) { 582 reporter = value; 583 return this; 584 } 585 586 /** 587 * XML resolver. 588 * 589 * <p> 590 * Associates an {@link XMLResolver} with this parser. 591 * 592 * @param value The new value for this property. 593 * <br>Can be <jk>null</jk> (no resolver will be used). 594 * @return This object. 595 */ 596 public Builder resolver(Class<? extends XMLResolver> value) { 597 resolver = value; 598 return this; 599 } 600 601 @Override /* Overridden from Builder */ 602 public Builder sortProperties() { 603 super.sortProperties(); 604 return this; 605 } 606 607 @Override /* Overridden from Builder */ 608 public Builder sortProperties(java.lang.Class<?>...on) { 609 super.sortProperties(on); 610 return this; 611 } 612 613 @Override /* Overridden from Builder */ 614 public Builder stopClass(Class<?> on, Class<?> value) { 615 super.stopClass(on, value); 616 return this; 617 } 618 619 @Override /* Overridden from Builder */ 620 public Builder streamCharset(Charset value) { 621 super.streamCharset(value); 622 return this; 623 } 624 625 @Override /* Overridden from Builder */ 626 public Builder strict() { 627 super.strict(); 628 return this; 629 } 630 631 @Override /* Overridden from Builder */ 632 public Builder strict(boolean value) { 633 super.strict(value); 634 return this; 635 } 636 637 @Override /* Overridden from Builder */ 638 public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) { 639 super.swap(normalClass, swappedClass, swapFunction); 640 return this; 641 } 642 643 @Override /* Overridden from Builder */ 644 public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) { 645 super.swap(normalClass, swappedClass, swapFunction, unswapFunction); 646 return this; 647 } 648 649 @Override /* Overridden from Builder */ 650 public Builder swaps(Class<?>...values) { 651 super.swaps(values); 652 return this; 653 } 654 655 @Override /* Overridden from Builder */ 656 public Builder swaps(Object...values) { 657 super.swaps(values); 658 return this; 659 } 660 661 @Override /* Overridden from Builder */ 662 public Builder timeZone(TimeZone value) { 663 super.timeZone(value); 664 return this; 665 } 666 667 @Override /* Overridden from Builder */ 668 public Builder trimStrings() { 669 super.trimStrings(); 670 return this; 671 } 672 673 @Override /* Overridden from Builder */ 674 public Builder trimStrings(boolean value) { 675 super.trimStrings(value); 676 return this; 677 } 678 679 @Override /* Overridden from Builder */ 680 public Builder type(Class<? extends org.apache.juneau.Context> value) { 681 super.type(value); 682 return this; 683 } 684 685 @Override /* Overridden from Builder */ 686 public Builder typeName(Class<?> on, String value) { 687 super.typeName(on, value); 688 return this; 689 } 690 691 @Override /* Overridden from Builder */ 692 public Builder typePropertyName(Class<?> on, String value) { 693 super.typePropertyName(on, value); 694 return this; 695 } 696 697 @Override /* Overridden from Builder */ 698 public Builder typePropertyName(String value) { 699 super.typePropertyName(value); 700 return this; 701 } 702 703 @Override /* Overridden from Builder */ 704 public Builder unbuffered() { 705 super.unbuffered(); 706 return this; 707 } 708 709 @Override /* Overridden from Builder */ 710 public Builder unbuffered(boolean value) { 711 super.unbuffered(value); 712 return this; 713 } 714 715 @Override /* Overridden from Builder */ 716 public Builder useEnumNames() { 717 super.useEnumNames(); 718 return this; 719 } 720 721 @Override /* Overridden from Builder */ 722 public Builder useJavaBeanIntrospector() { 723 super.useJavaBeanIntrospector(); 724 return this; 725 } 726 727 /** 728 * Enable validation. 729 * 730 * <p> 731 * If <jk>true</jk>, XML document will be validated. 732 * 733 * <p> 734 * See {@link XMLInputFactory#IS_VALIDATING} for more info. 735 * 736 * @return This object. 737 */ 738 public Builder validating() { 739 return validating(true); 740 } 741 742 /** 743 * Same as {@link #validating()} but allows you to explicitly specify the value. 744 * 745 * @param value The value for this setting. 746 * @return This object. 747 */ 748 public Builder validating(boolean value) { 749 validating = value; 750 return this; 751 } 752 } 753 754 /** Default parser, all default settings.*/ 755 public static final XmlParser DEFAULT = new XmlParser(create()); 756 757 /** 758 * Creates a new builder for this object. 759 * 760 * @return A new builder. 761 */ 762 public static Builder create() { 763 return new Builder(); 764 } 765 766 protected final boolean preserveRootElement; 767 protected final boolean validating; 768 protected final Class<? extends XMLEventAllocator> eventAllocator; 769 protected final Class<? extends XMLReporter> reporter; 770 protected final Class<? extends XMLResolver> resolver; 771 772 private final XMLEventAllocator eventAllocatorImpl; 773 private final XMLReporter reporterImpl; 774 private final XMLResolver resolverImpl; 775 private final Map<BeanMeta<?>,XmlBeanMeta> xmlBeanMetas = new ConcurrentHashMap<>(); 776 private final Map<BeanPropertyMeta,XmlBeanPropertyMeta> xmlBeanPropertyMetas = new ConcurrentHashMap<>(); 777 private final Map<ClassMeta<?>,XmlClassMeta> xmlClassMetas = new ConcurrentHashMap<>(); 778 779 /** 780 * Constructor. 781 * 782 * @param builder 783 * The property store containing all the settings for this object. 784 */ 785 public XmlParser(Builder builder) { 786 super(builder); 787 eventAllocator = builder.eventAllocator; 788 preserveRootElement = builder.preserveRootElement; 789 reporter = builder.reporter; 790 resolver = builder.resolver; 791 validating = builder.validating; 792 793 reporterImpl = nn(reporter) ? newInstance(reporter) : null; 794 resolverImpl = nn(resolver) ? newInstance(resolver) : null; 795 eventAllocatorImpl = nn(eventAllocator) ? newInstance(eventAllocator) : null; 796 } 797 798 @Override /* Overridden from Context */ 799 public Builder copy() { 800 return new Builder(this); 801 } 802 803 @Override /* Overridden from Context */ 804 public XmlParserSession.Builder createSession() { 805 return XmlParserSession.create(this); 806 } 807 808 @Override /* Overridden from Context */ 809 public XmlParserSession getSession() { return createSession().build(); } 810 811 @Override /* Overridden from XmlMetaProvider */ 812 public XmlBeanMeta getXmlBeanMeta(BeanMeta<?> bm) { 813 var m = xmlBeanMetas.get(bm); 814 if (m == null) { 815 m = new XmlBeanMeta(bm, this); 816 xmlBeanMetas.put(bm, m); 817 } 818 return m; 819 } 820 821 @Override /* Overridden from XmlMetaProvider */ 822 public XmlBeanPropertyMeta getXmlBeanPropertyMeta(BeanPropertyMeta bpm) { 823 var m = xmlBeanPropertyMetas.get(bpm); 824 if (m == null) { 825 var dbpm = bpm.getDelegateFor(); 826 m = new XmlBeanPropertyMeta(dbpm, this); 827 xmlBeanPropertyMetas.put(bpm, m); 828 } 829 return m; 830 } 831 832 @Override /* Overridden from XmlMetaProvider */ 833 public XmlClassMeta getXmlClassMeta(ClassMeta<?> cm) { 834 var m = xmlClassMetas.get(cm); 835 if (m == null) { 836 m = new XmlClassMeta(cm, this); 837 xmlClassMetas.put(cm, m); 838 } 839 return m; 840 } 841 842 private static <T> T newInstance(Class<T> c) { 843 try { 844 return c.getDeclaredConstructor().newInstance(); 845 } catch (Exception e) { 846 throw toRex(e); 847 } 848 } 849 850 /** 851 * XML event allocator. 852 * 853 * @see Builder#eventAllocator(Class) 854 * @return 855 * The {@link XMLEventAllocator} associated with this parser, or <jk>null</jk> if there isn't one. 856 */ 857 protected final XMLEventAllocator getEventAllocator() { return eventAllocatorImpl; } 858 859 /** 860 * XML reporter. 861 * 862 * @see Builder#reporter(Class) 863 * @return 864 * The {@link XMLReporter} associated with this parser, or <jk>null</jk> if there isn't one. 865 */ 866 protected final XMLReporter getReporter() { return reporterImpl; } 867 868 /** 869 * XML resolver. 870 * 871 * @see Builder#resolver(Class) 872 * @return 873 * The {@link XMLResolver} associated with this parser, or <jk>null</jk> if there isn't one. 874 */ 875 protected final XMLResolver getResolver() { return resolverImpl; } 876 877 /** 878 * Preserve root element during generalized parsing. 879 * 880 * @see Builder#preserveRootElement() 881 * @return 882 * <jk>true</jk> if when parsing into a generic {@link JsonMap}, the map will contain a single entry whose key 883 * is the root element name. 884 */ 885 protected final boolean isPreserveRootElement() { return preserveRootElement; } 886 887 /** 888 * Enable validation. 889 * 890 * @see Builder#validating() 891 * @return 892 * <jk>true</jk> if XML document will be validated. 893 */ 894 protected final boolean isValidating() { return validating; } 895 896 @Override /* Overridden from ReaderParser */ 897 protected FluentMap<String,Object> properties() { 898 return super.properties() 899 .a("eventAllocator", eventAllocator) 900 .a("preserveRootElement", preserveRootElement) 901 .a("reporter", reporter) 902 .a("resolver", resolver) 903 .a("validating", validating); 904 } 905}