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