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.xml; 014 015import static org.apache.juneau.collections.JsonMap.*; 016import static org.apache.juneau.internal.CollectionUtils.*; 017 018import java.lang.annotation.*; 019import java.lang.reflect.*; 020import java.nio.charset.*; 021import java.util.*; 022import java.util.concurrent.*; 023 024import org.apache.juneau.*; 025import org.apache.juneau.collections.*; 026import org.apache.juneau.internal.*; 027import org.apache.juneau.json.*; 028import org.apache.juneau.serializer.*; 029import org.apache.juneau.utils.*; 030 031/** 032 * Serializes POJO models to XML. 033 * 034 * <h5 class='topic'>Media types</h5> 035 * <p> 036 * Handles <c>Accept</c> types: <bc>text/xml</bc> 037 * <p> 038 * Produces <c>Content-Type</c> types: <bc>text/xml</bc> 039 * 040 * <h5 class='topic'>Description</h5> 041 * <p> 042 * See the {@link JsonSerializer} class for details on how Java models map to JSON. 043 * 044 * <p> 045 * For example, the following JSON... 046 * <p class='bjson'> 047 * { 048 * name:<js>'John Smith'</js>, 049 * address: { 050 * streetAddress: <js>'21 2nd Street'</js>, 051 * city: <js>'New York'</js>, 052 * state: <js>'NY'</js>, 053 * postalCode: <js>10021</js> 054 * }, 055 * phoneNumbers: [ 056 * <js>'212 555-1111'</js>, 057 * <js>'212 555-2222'</js> 058 * ], 059 * additionalInfo: <jk>null</jk>, 060 * remote: <jk>false</jk>, 061 * height: <js>62.4</js>, 062 * <js>'fico score'</js>: <js>' > 640'</js> 063 * } 064 * <p> 065 * ...maps to the following XML using the default serializer... 066 * <p class='bxml'> 067 * <xt><object></xt> 068 * <xt><name></xt>John Smith<xt></name></xt> 069 * <xt><address></xt> 070 * <xt><streetAddress></xt>21 2nd Street<xt></streetAddress></xt> 071 * <xt><city></xt>New York<xt></city></xt> 072 * <xt><state></xt>NY<xt></state></xt> 073 * <xt><postalCode></xt>10021<xt></postalCode></xt> 074 * <xt></address></xt> 075 * <xt><phoneNumbers></xt> 076 * <xt><string></xt>212 555-1111<xt></string></xt> 077 * <xt><string></xt>212 555-2222<xt></string></xt> 078 * <xt></phoneNumbers></xt> 079 * <xt><additionalInfo</xt> <xa>_type</xa>=<xs>'null'</xs><xt>></additionalInfo></xt> 080 * <xt><remote></xt>false<xt></remote></xt> 081 * <xt><height></xt>62.4<xt></height></xt> 082 * <xt><fico_x0020_score></xt> &gt; 640<xt></fico_x0020_score></xt> 083 * <xt></object></xt> 084 * 085 * <p> 086 * An additional "add-json-properties" mode is also provided to prevent loss of JSON data types... 087 * <p class='bxml'> 088 * <xt><object></xt> 089 * <xt><name</xt> <xa>_type</xa>=<xs>'string'</xs><xt>></xt>John Smith<xt></name></xt> 090 * <xt><address</xt> <xa>_type</xa>=<xs>'object'</xs><xt>></xt> 091 * <xt><streetAddress</xt> <xa>_type</xa>=<xs>'string'</xs><xt>></xt>21 2nd Street<xt></streetAddress></xt> 092 * <xt><city</xt> <xa>_type</xa>=<xs>'string'</xs><xt>></xt>New York<xt></city></xt> 093 * <xt><state</xt> <xa>_type</xa>=<xs>'string'</xs><xt>></xt>NY<xt></state></xt> 094 * <xt><postalCode</xt> <xa>_type</xa>=<xs>'number'</xs><xt>></xt>10021<xt></postalCode></xt> 095 * <xt></address></xt> 096 * <xt><phoneNumbers</xt> <xa>_type</xa>=<xs>'array'</xs><xt>></xt> 097 * <xt><string></xt>212 555-1111<xt></string></xt> 098 * <xt><string></xt>212 555-2222<xt></string></xt> 099 * <xt></phoneNumbers></xt> 100 * <xt><additionalInfo</xt> <xa>_type</xa>=<xs>'null'</xs><xt>></additionalInfo></xt> 101 * <xt><remote</xt> <xa>_type</xa>=<xs>'boolean'</xs><xt>></xt>false<xt></remote></xt> 102 * <xt><height</xt> <xa>_type</xa>=<xs>'number'</xs><xt>></xt>62.4<xt></height></xt> 103 * <xt><fico_x0020_score</xt> <xa>_type</xa>=<xs>'string'</xs><xt>></xt> &gt; 640<xt></fico_x0020_score></xt> 104 * <xt></object></xt> 105 * </p> 106 * 107 * <p> 108 * This serializer provides several serialization options. 109 * Typically, one of the predefined <jsf>DEFAULT</jsf> serializers will be sufficient. 110 * However, custom serializers can be constructed to fine-tune behavior. 111 * 112 * <p> 113 * If an attribute name contains any non-valid XML element characters, they will be escaped using standard 114 * {@code _x####_} notation. 115 * 116 * <h5 class='topic'>Behavior-specific subclasses</h5> 117 * <p> 118 * The following direct subclasses are provided for convenience: 119 * <ul> 120 * <li>{@link Sq} - Default serializer, single quotes. 121 * <li>{@link SqReadable} - Default serializer, single quotes, whitespace added. 122 * </ul> 123 * 124 * <h5 class='section'>Notes:</h5><ul> 125 * <li class='note'>This class is thread safe and reusable. 126 * </ul> 127 * 128 * <h5 class='section'>See Also:</h5><ul> 129 * <li class='link'><a class="doclink" href="../../../../index.html#jm.XmlDetails">XML Details</a> 130 131 * </ul> 132 */ 133public class XmlSerializer extends WriterSerializer implements XmlMetaProvider { 134 135 //------------------------------------------------------------------------------------------------------------------- 136 // Static 137 //------------------------------------------------------------------------------------------------------------------- 138 139 private static final Namespace[] EMPTY_NAMESPACE_ARRAY = new Namespace[0]; 140 141 /** Default serializer without namespaces. */ 142 public static final XmlSerializer DEFAULT = new XmlSerializer(create()); 143 144 /** Default serializer without namespaces, with single quotes. */ 145 public static final XmlSerializer DEFAULT_SQ = new Sq(create()); 146 147 /** Default serializer without namespaces, with single quotes, whitespace added. */ 148 public static final XmlSerializer DEFAULT_SQ_READABLE = new SqReadable(create()); 149 150 /** Default serializer, all default settings. */ 151 public static final XmlSerializer DEFAULT_NS = new Ns(create()); 152 153 /** Default serializer, single quotes. */ 154 public static final XmlSerializer DEFAULT_NS_SQ = new NsSq(create()); 155 156 /** Default serializer, single quotes, whitespace added. */ 157 public static final XmlSerializer DEFAULT_NS_SQ_READABLE = new NsSqReadable(create()); 158 159 /** 160 * Creates a new builder for this object. 161 * 162 * @return A new builder. 163 */ 164 public static Builder create() { 165 return new Builder(); 166 } 167 168 //------------------------------------------------------------------------------------------------------------------- 169 // Static subclasses 170 //------------------------------------------------------------------------------------------------------------------- 171 172 /** Default serializer, single quotes. */ 173 public static class Sq extends XmlSerializer { 174 175 /** 176 * Constructor. 177 * 178 * @param builder The builder for this object. 179 */ 180 public Sq(Builder builder) { 181 super(builder.quoteChar('\'')); 182 } 183 } 184 185 /** Default serializer, single quotes, whitespace added. */ 186 public static class SqReadable extends XmlSerializer { 187 188 /** 189 * Constructor. 190 * 191 * @param builder The builder for this object. 192 */ 193 public SqReadable(Builder builder) { 194 super(builder.quoteChar('\'').useWhitespace()); 195 } 196 } 197 198 /** Default serializer without namespaces. */ 199 public static class Ns extends XmlSerializer { 200 201 /** 202 * Constructor. 203 * 204 * @param builder The builder for this object. 205 */ 206 public Ns(Builder builder) { 207 super(builder.enableNamespaces()); 208 } 209 } 210 211 /** Default serializer without namespaces, single quotes. */ 212 public static class NsSq extends XmlSerializer { 213 214 /** 215 * Constructor. 216 * 217 * @param builder The builder for this object. 218 */ 219 public NsSq(Builder builder) { 220 super(builder.enableNamespaces().quoteChar('\'')); 221 } 222 } 223 224 /** Default serializer without namespaces, single quotes, with whitespace. */ 225 public static class NsSqReadable extends XmlSerializer { 226 227 /** 228 * Constructor. 229 * 230 * @param builder The builder for this object. 231 */ 232 public NsSqReadable(Builder builder) { 233 super(builder.enableNamespaces().quoteChar('\'').useWhitespace()); 234 } 235 } 236 237 @SuppressWarnings("javadoc") 238 protected static final Namespace 239 DEFAULT_JUNEAU_NAMESPACE = Namespace.of("juneau", "http://www.apache.org/2013/Juneau"), 240 DEFAULT_XS_NAMESPACE = Namespace.of("xs", "http://www.w3.org/2001/XMLSchema"); 241 242 //------------------------------------------------------------------------------------------------------------------- 243 // Builder 244 //------------------------------------------------------------------------------------------------------------------- 245 246 /** 247 * Builder class. 248 */ 249 @FluentSetters 250 public static class Builder extends WriterSerializer.Builder { 251 252 private static final Cache<HashKey,XmlSerializer> CACHE = Cache.of(HashKey.class, XmlSerializer.class).build(); 253 254 boolean addBeanTypesXml, addNamespaceUrisToRoot, disableAutoDetectNamespaces, enableNamespaces; 255 Namespace defaultNamespace; 256 List<Namespace> namespaces; 257 258 /** 259 * Constructor, default settings. 260 */ 261 protected Builder() { 262 super(); 263 produces("text/xml"); 264 addBeanTypesXml = env("XmlSerializer.addBeanTypes", false); 265 addNamespaceUrisToRoot = env("XmlSerializer.addNamespaceUrisToRoot", false); 266 disableAutoDetectNamespaces = env("XmlSerializer.disableAutoDetectNamespaces", false); 267 enableNamespaces = env("XmlSerializer.enableNamespaces", false); 268 defaultNamespace = null; 269 namespaces = null; 270 271 } 272 273 /** 274 * Copy constructor. 275 * 276 * @param copyFrom The bean to copy from. 277 */ 278 protected Builder(XmlSerializer copyFrom) { 279 super(copyFrom); 280 addBeanTypesXml = copyFrom.addBeanTypesXml; 281 addNamespaceUrisToRoot = copyFrom.addNamespaceUrlsToRoot; 282 disableAutoDetectNamespaces = ! copyFrom.autoDetectNamespaces; 283 enableNamespaces = copyFrom.enableNamespaces; 284 defaultNamespace = copyFrom.defaultNamespace; 285 namespaces = copyFrom.namespaces.length == 0 ? null : list(copyFrom.namespaces); 286 } 287 288 /** 289 * Copy constructor. 290 * 291 * @param copyFrom The builder to copy from. 292 */ 293 protected Builder(Builder copyFrom) { 294 super(copyFrom); 295 addBeanTypesXml = copyFrom.addBeanTypesXml; 296 addNamespaceUrisToRoot = copyFrom.addNamespaceUrisToRoot; 297 disableAutoDetectNamespaces = copyFrom.disableAutoDetectNamespaces; 298 enableNamespaces = copyFrom.enableNamespaces; 299 defaultNamespace = copyFrom.defaultNamespace; 300 namespaces = copyOf(copyFrom.namespaces); 301 } 302 303 @Override /* Context.Builder */ 304 public Builder copy() { 305 return new Builder(this); 306 } 307 308 @Override /* Context.Builder */ 309 public XmlSerializer build() { 310 return cache(CACHE).build(XmlSerializer.class); 311 } 312 313 @Override /* Context.Builder */ 314 public HashKey hashKey() { 315 return HashKey.of( 316 super.hashKey(), 317 addBeanTypesXml, 318 addNamespaceUrisToRoot, 319 disableAutoDetectNamespaces, 320 enableNamespaces, 321 defaultNamespace, 322 namespaces 323 ); 324 } 325 326 //----------------------------------------------------------------------------------------------------------------- 327 // Properties 328 //----------------------------------------------------------------------------------------------------------------- 329 330 /** 331 * Add <js>"_type"</js> properties when needed. 332 * 333 * <p> 334 * If <jk>true</jk>, then <js>"_type"</js> properties will be added to beans if their type cannot be inferred 335 * through reflection. 336 * 337 * <p> 338 * When present, this value overrides the {@link org.apache.juneau.serializer.Serializer.Builder#addBeanTypes()} setting and is 339 * provided to customize the behavior of specific serializers in a {@link SerializerSet}. 340 * 341 * @return This object. 342 */ 343 @FluentSetter 344 public Builder addBeanTypesXml() { 345 return addBeanTypesXml(true); 346 } 347 348 /** 349 * Same as {@link #addBeanTypesXml()} but allows you to explicitly specify the value. 350 * 351 * @param value The value for this setting. 352 * @return This object. 353 */ 354 @FluentSetter 355 public Builder addBeanTypesXml(boolean value) { 356 addBeanTypesXml = value; 357 return this; 358 } 359 360 /** 361 * Add namespace URLs to the root element. 362 * 363 * <p> 364 * Use this setting to add {@code xmlns:x} attributes to the root element for the default and all mapped namespaces. 365 * 366 * <p> 367 * This setting is ignored if {@link #enableNamespaces()} is not enabled. 368 * 369 * <h5 class='section'>See Also:</h5><ul> 370 * <li class='link'><a class="doclink" href="../../../../index.html#jm.XmlNamespaces">Namespaces</a> 371 * </ul> 372 * 373 * @return This object. 374 */ 375 @FluentSetter 376 public Builder addNamespaceUrisToRoot() { 377 return addNamespaceUrisToRoot(true); 378 } 379 380 /** 381 * Same as {@link #addNamespaceUrisToRoot()} but allows you to explicitly specify the value. 382 * 383 * @param value The value for this setting. 384 * @return This object. 385 */ 386 @FluentSetter 387 public Builder addNamespaceUrisToRoot(boolean value) { 388 addNamespaceUrisToRoot = value; 389 return this; 390 } 391 392 /** 393 * Don't auto-detect namespace usage. 394 * 395 * <p> 396 * Don't detect namespace usage before serialization. 397 * 398 * <p> 399 * Used in conjunction with {@link Builder#addNamespaceUrisToRoot()} to reduce the list of namespace URLs appended to the 400 * root element to only those that will be used in the resulting document. 401 * 402 * <p> 403 * If disabled, then the data structure will first be crawled looking for namespaces that will be encountered before 404 * the root element is serialized. 405 * 406 * <p> 407 * This setting is ignored if {@link Builder#enableNamespaces()} is not enabled. 408 * 409 * <h5 class='section'>Notes:</h5><ul> 410 * <li class='note'> 411 * Auto-detection of namespaces can be costly performance-wise. 412 * <br>In high-performance environments, it's recommended that namespace detection be 413 * disabled, and that namespaces be manually defined through the {@link Builder#namespaces(Namespace...)} property. 414 * </ul> 415 * 416 * <h5 class='section'>See Also:</h5><ul> 417 * <li class='link'><a class="doclink" href="../../../../index.html#jm.XmlNamespaces">Namespaces</a> 418 * </ul> 419 * 420 * @return This object. 421 */ 422 @FluentSetter 423 public Builder disableAutoDetectNamespaces() { 424 return disableAutoDetectNamespaces(true); 425 } 426 427 /** 428 * Same as {@link #disableAutoDetectNamespaces()} but allows you to explicitly specify the value. 429 * 430 * @param value The value for this setting. 431 * @return This object. 432 */ 433 @FluentSetter 434 public Builder disableAutoDetectNamespaces(boolean value) { 435 disableAutoDetectNamespaces = value; 436 return this; 437 } 438 439 /** 440 * Default namespace. 441 * 442 * <p> 443 * Specifies the default namespace URI for this document. 444 * 445 * <h5 class='section'>See Also:</h5><ul> 446 * <li class='link'><a class="doclink" href="../../../../index.html#jm.XmlNamespaces">Namespaces</a> 447 * </ul> 448 * 449 * @param value 450 * The new value for this property. 451 * <br>The default is <js>"juneau: http://www.apache.org/2013/Juneau"</js>. 452 * @return This object. 453 */ 454 @FluentSetter 455 public Builder defaultNamespace(Namespace value) { 456 defaultNamespace = value; 457 return this; 458 } 459 460 /** 461 * Enable support for XML namespaces. 462 * 463 * <p> 464 * If not enabled, XML output will not contain any namespaces regardless of any other settings. 465 * 466 * <h5 class='section'>See Also:</h5><ul> 467 * <li class='link'><a class="doclink" href="../../../../index.html#jm.XmlNamespaces">Namespaces</a> 468 * </ul> 469 * 470 * @return This object. 471 */ 472 @FluentSetter 473 public Builder enableNamespaces() { 474 return enableNamespaces(true); 475 } 476 477 /** 478 * Same as {@link #enableNamespaces()} but allows you to explicitly specify the value. 479 * 480 * @param value The value for this setting. 481 * @return This object. 482 */ 483 @FluentSetter 484 public Builder enableNamespaces(boolean value) { 485 enableNamespaces = value; 486 return this; 487 } 488 489 /** 490 * Enable support for XML namespaces. 491 * 492 * <p> 493 * Shortcut for calling <code>enableNamespaces(<jk>true</jk>)</code>. 494 * 495 * @return This object. 496 */ 497 @FluentSetter 498 public Builder ns() { 499 return enableNamespaces(); 500 } 501 502 /** 503 * Default namespaces. 504 * 505 * <p> 506 * The default list of namespaces associated with this serializer. 507 * 508 * @param values The new value for this property. 509 * @return This object. 510 */ 511 @FluentSetter 512 public Builder namespaces(Namespace...values) { 513 namespaces = addAll(namespaces, values); 514 return this; 515 } 516 517 // <FluentSetters> 518 519 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 520 public Builder annotations(Annotation...values) { 521 super.annotations(values); 522 return this; 523 } 524 525 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 526 public Builder apply(AnnotationWorkList work) { 527 super.apply(work); 528 return this; 529 } 530 531 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 532 public Builder applyAnnotations(java.lang.Class<?>...fromClasses) { 533 super.applyAnnotations(fromClasses); 534 return this; 535 } 536 537 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 538 public Builder applyAnnotations(Method...fromMethods) { 539 super.applyAnnotations(fromMethods); 540 return this; 541 } 542 543 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 544 public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) { 545 super.cache(value); 546 return this; 547 } 548 549 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 550 public Builder debug() { 551 super.debug(); 552 return this; 553 } 554 555 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 556 public Builder debug(boolean value) { 557 super.debug(value); 558 return this; 559 } 560 561 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 562 public Builder impl(Context value) { 563 super.impl(value); 564 return this; 565 } 566 567 @Override /* GENERATED - org.apache.juneau.Context.Builder */ 568 public Builder type(Class<? extends org.apache.juneau.Context> value) { 569 super.type(value); 570 return this; 571 } 572 573 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 574 public Builder beanClassVisibility(Visibility value) { 575 super.beanClassVisibility(value); 576 return this; 577 } 578 579 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 580 public Builder beanConstructorVisibility(Visibility value) { 581 super.beanConstructorVisibility(value); 582 return this; 583 } 584 585 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 586 public Builder beanContext(BeanContext value) { 587 super.beanContext(value); 588 return this; 589 } 590 591 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 592 public Builder beanContext(BeanContext.Builder value) { 593 super.beanContext(value); 594 return this; 595 } 596 597 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 598 public Builder beanDictionary(java.lang.Class<?>...values) { 599 super.beanDictionary(values); 600 return this; 601 } 602 603 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 604 public Builder beanFieldVisibility(Visibility value) { 605 super.beanFieldVisibility(value); 606 return this; 607 } 608 609 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 610 public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) { 611 super.beanInterceptor(on, value); 612 return this; 613 } 614 615 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 616 public Builder beanMapPutReturnsOldValue() { 617 super.beanMapPutReturnsOldValue(); 618 return this; 619 } 620 621 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 622 public Builder beanMethodVisibility(Visibility value) { 623 super.beanMethodVisibility(value); 624 return this; 625 } 626 627 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 628 public Builder beanProperties(Map<String,Object> values) { 629 super.beanProperties(values); 630 return this; 631 } 632 633 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 634 public Builder beanProperties(Class<?> beanClass, String properties) { 635 super.beanProperties(beanClass, properties); 636 return this; 637 } 638 639 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 640 public Builder beanProperties(String beanClassName, String properties) { 641 super.beanProperties(beanClassName, properties); 642 return this; 643 } 644 645 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 646 public Builder beanPropertiesExcludes(Map<String,Object> values) { 647 super.beanPropertiesExcludes(values); 648 return this; 649 } 650 651 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 652 public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) { 653 super.beanPropertiesExcludes(beanClass, properties); 654 return this; 655 } 656 657 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 658 public Builder beanPropertiesExcludes(String beanClassName, String properties) { 659 super.beanPropertiesExcludes(beanClassName, properties); 660 return this; 661 } 662 663 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 664 public Builder beanPropertiesReadOnly(Map<String,Object> values) { 665 super.beanPropertiesReadOnly(values); 666 return this; 667 } 668 669 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 670 public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) { 671 super.beanPropertiesReadOnly(beanClass, properties); 672 return this; 673 } 674 675 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 676 public Builder beanPropertiesReadOnly(String beanClassName, String properties) { 677 super.beanPropertiesReadOnly(beanClassName, properties); 678 return this; 679 } 680 681 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 682 public Builder beanPropertiesWriteOnly(Map<String,Object> values) { 683 super.beanPropertiesWriteOnly(values); 684 return this; 685 } 686 687 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 688 public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) { 689 super.beanPropertiesWriteOnly(beanClass, properties); 690 return this; 691 } 692 693 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 694 public Builder beanPropertiesWriteOnly(String beanClassName, String properties) { 695 super.beanPropertiesWriteOnly(beanClassName, properties); 696 return this; 697 } 698 699 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 700 public Builder beansRequireDefaultConstructor() { 701 super.beansRequireDefaultConstructor(); 702 return this; 703 } 704 705 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 706 public Builder beansRequireSerializable() { 707 super.beansRequireSerializable(); 708 return this; 709 } 710 711 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 712 public Builder beansRequireSettersForGetters() { 713 super.beansRequireSettersForGetters(); 714 return this; 715 } 716 717 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 718 public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) { 719 super.dictionaryOn(on, values); 720 return this; 721 } 722 723 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 724 public Builder disableBeansRequireSomeProperties() { 725 super.disableBeansRequireSomeProperties(); 726 return this; 727 } 728 729 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 730 public Builder disableIgnoreMissingSetters() { 731 super.disableIgnoreMissingSetters(); 732 return this; 733 } 734 735 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 736 public Builder disableIgnoreTransientFields() { 737 super.disableIgnoreTransientFields(); 738 return this; 739 } 740 741 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 742 public Builder disableIgnoreUnknownNullBeanProperties() { 743 super.disableIgnoreUnknownNullBeanProperties(); 744 return this; 745 } 746 747 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 748 public Builder disableInterfaceProxies() { 749 super.disableInterfaceProxies(); 750 return this; 751 } 752 753 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 754 public <T> Builder example(Class<T> pojoClass, T o) { 755 super.example(pojoClass, o); 756 return this; 757 } 758 759 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 760 public <T> Builder example(Class<T> pojoClass, String json) { 761 super.example(pojoClass, json); 762 return this; 763 } 764 765 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 766 public Builder findFluentSetters() { 767 super.findFluentSetters(); 768 return this; 769 } 770 771 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 772 public Builder findFluentSetters(Class<?> on) { 773 super.findFluentSetters(on); 774 return this; 775 } 776 777 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 778 public Builder ignoreInvocationExceptionsOnGetters() { 779 super.ignoreInvocationExceptionsOnGetters(); 780 return this; 781 } 782 783 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 784 public Builder ignoreInvocationExceptionsOnSetters() { 785 super.ignoreInvocationExceptionsOnSetters(); 786 return this; 787 } 788 789 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 790 public Builder ignoreUnknownBeanProperties() { 791 super.ignoreUnknownBeanProperties(); 792 return this; 793 } 794 795 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 796 public Builder ignoreUnknownEnumValues() { 797 super.ignoreUnknownEnumValues(); 798 return this; 799 } 800 801 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 802 public Builder implClass(Class<?> interfaceClass, Class<?> implClass) { 803 super.implClass(interfaceClass, implClass); 804 return this; 805 } 806 807 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 808 public Builder implClasses(Map<Class<?>,Class<?>> values) { 809 super.implClasses(values); 810 return this; 811 } 812 813 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 814 public Builder interfaceClass(Class<?> on, Class<?> value) { 815 super.interfaceClass(on, value); 816 return this; 817 } 818 819 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 820 public Builder interfaces(java.lang.Class<?>...value) { 821 super.interfaces(value); 822 return this; 823 } 824 825 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 826 public Builder locale(Locale value) { 827 super.locale(value); 828 return this; 829 } 830 831 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 832 public Builder mediaType(MediaType value) { 833 super.mediaType(value); 834 return this; 835 } 836 837 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 838 public Builder notBeanClasses(java.lang.Class<?>...values) { 839 super.notBeanClasses(values); 840 return this; 841 } 842 843 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 844 public Builder notBeanPackages(String...values) { 845 super.notBeanPackages(values); 846 return this; 847 } 848 849 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 850 public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) { 851 super.propertyNamer(value); 852 return this; 853 } 854 855 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 856 public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) { 857 super.propertyNamer(on, value); 858 return this; 859 } 860 861 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 862 public Builder sortProperties() { 863 super.sortProperties(); 864 return this; 865 } 866 867 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 868 public Builder sortProperties(java.lang.Class<?>...on) { 869 super.sortProperties(on); 870 return this; 871 } 872 873 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 874 public Builder stopClass(Class<?> on, Class<?> value) { 875 super.stopClass(on, value); 876 return this; 877 } 878 879 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 880 public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) { 881 super.swap(normalClass, swappedClass, swapFunction); 882 return this; 883 } 884 885 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 886 public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) { 887 super.swap(normalClass, swappedClass, swapFunction, unswapFunction); 888 return this; 889 } 890 891 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 892 public Builder swaps(java.lang.Class<?>...values) { 893 super.swaps(values); 894 return this; 895 } 896 897 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 898 public Builder timeZone(TimeZone value) { 899 super.timeZone(value); 900 return this; 901 } 902 903 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 904 public Builder typeName(Class<?> on, String value) { 905 super.typeName(on, value); 906 return this; 907 } 908 909 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 910 public Builder typePropertyName(String value) { 911 super.typePropertyName(value); 912 return this; 913 } 914 915 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 916 public Builder typePropertyName(Class<?> on, String value) { 917 super.typePropertyName(on, value); 918 return this; 919 } 920 921 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 922 public Builder useEnumNames() { 923 super.useEnumNames(); 924 return this; 925 } 926 927 @Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */ 928 public Builder useJavaBeanIntrospector() { 929 super.useJavaBeanIntrospector(); 930 return this; 931 } 932 933 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 934 public Builder detectRecursions() { 935 super.detectRecursions(); 936 return this; 937 } 938 939 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 940 public Builder detectRecursions(boolean value) { 941 super.detectRecursions(value); 942 return this; 943 } 944 945 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 946 public Builder ignoreRecursions() { 947 super.ignoreRecursions(); 948 return this; 949 } 950 951 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 952 public Builder ignoreRecursions(boolean value) { 953 super.ignoreRecursions(value); 954 return this; 955 } 956 957 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 958 public Builder initialDepth(int value) { 959 super.initialDepth(value); 960 return this; 961 } 962 963 @Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */ 964 public Builder maxDepth(int value) { 965 super.maxDepth(value); 966 return this; 967 } 968 969 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 970 public Builder accept(String value) { 971 super.accept(value); 972 return this; 973 } 974 975 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 976 public Builder addBeanTypes() { 977 super.addBeanTypes(); 978 return this; 979 } 980 981 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 982 public Builder addBeanTypes(boolean value) { 983 super.addBeanTypes(value); 984 return this; 985 } 986 987 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 988 public Builder addRootType() { 989 super.addRootType(); 990 return this; 991 } 992 993 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 994 public Builder addRootType(boolean value) { 995 super.addRootType(value); 996 return this; 997 } 998 999 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1000 public Builder keepNullProperties() { 1001 super.keepNullProperties(); 1002 return this; 1003 } 1004 1005 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1006 public Builder keepNullProperties(boolean value) { 1007 super.keepNullProperties(value); 1008 return this; 1009 } 1010 1011 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1012 public Builder listener(Class<? extends org.apache.juneau.serializer.SerializerListener> value) { 1013 super.listener(value); 1014 return this; 1015 } 1016 1017 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1018 public Builder produces(String value) { 1019 super.produces(value); 1020 return this; 1021 } 1022 1023 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1024 public Builder sortCollections() { 1025 super.sortCollections(); 1026 return this; 1027 } 1028 1029 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1030 public Builder sortCollections(boolean value) { 1031 super.sortCollections(value); 1032 return this; 1033 } 1034 1035 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1036 public Builder sortMaps() { 1037 super.sortMaps(); 1038 return this; 1039 } 1040 1041 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1042 public Builder sortMaps(boolean value) { 1043 super.sortMaps(value); 1044 return this; 1045 } 1046 1047 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1048 public Builder trimEmptyCollections() { 1049 super.trimEmptyCollections(); 1050 return this; 1051 } 1052 1053 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1054 public Builder trimEmptyCollections(boolean value) { 1055 super.trimEmptyCollections(value); 1056 return this; 1057 } 1058 1059 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1060 public Builder trimEmptyMaps() { 1061 super.trimEmptyMaps(); 1062 return this; 1063 } 1064 1065 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1066 public Builder trimEmptyMaps(boolean value) { 1067 super.trimEmptyMaps(value); 1068 return this; 1069 } 1070 1071 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1072 public Builder trimStrings() { 1073 super.trimStrings(); 1074 return this; 1075 } 1076 1077 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1078 public Builder trimStrings(boolean value) { 1079 super.trimStrings(value); 1080 return this; 1081 } 1082 1083 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1084 public Builder uriContext(UriContext value) { 1085 super.uriContext(value); 1086 return this; 1087 } 1088 1089 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1090 public Builder uriRelativity(UriRelativity value) { 1091 super.uriRelativity(value); 1092 return this; 1093 } 1094 1095 @Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */ 1096 public Builder uriResolution(UriResolution value) { 1097 super.uriResolution(value); 1098 return this; 1099 } 1100 1101 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1102 public Builder fileCharset(Charset value) { 1103 super.fileCharset(value); 1104 return this; 1105 } 1106 1107 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1108 public Builder maxIndent(int value) { 1109 super.maxIndent(value); 1110 return this; 1111 } 1112 1113 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1114 public Builder quoteChar(char value) { 1115 super.quoteChar(value); 1116 return this; 1117 } 1118 1119 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1120 public Builder quoteCharOverride(char value) { 1121 super.quoteCharOverride(value); 1122 return this; 1123 } 1124 1125 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1126 public Builder sq() { 1127 super.sq(); 1128 return this; 1129 } 1130 1131 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1132 public Builder streamCharset(Charset value) { 1133 super.streamCharset(value); 1134 return this; 1135 } 1136 1137 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1138 public Builder useWhitespace() { 1139 super.useWhitespace(); 1140 return this; 1141 } 1142 1143 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1144 public Builder useWhitespace(boolean value) { 1145 super.useWhitespace(value); 1146 return this; 1147 } 1148 1149 @Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */ 1150 public Builder ws() { 1151 super.ws(); 1152 return this; 1153 } 1154 1155 // </FluentSetters> 1156 } 1157 1158 //------------------------------------------------------------------------------------------------------------------- 1159 // Instance 1160 //------------------------------------------------------------------------------------------------------------------- 1161 1162 final boolean 1163 autoDetectNamespaces, 1164 enableNamespaces, 1165 addNamespaceUrlsToRoot, 1166 addBeanTypesXml; 1167 1168 final Namespace defaultNamespace; 1169 final Namespace[] namespaces; 1170 1171 private final boolean addBeanTypes; 1172 private final Map<ClassMeta<?>,XmlClassMeta> xmlClassMetas = new ConcurrentHashMap<>(); 1173 private final Map<BeanMeta<?>,XmlBeanMeta> xmlBeanMetas = new ConcurrentHashMap<>(); 1174 private final Map<BeanPropertyMeta,XmlBeanPropertyMeta> xmlBeanPropertyMetas = new ConcurrentHashMap<>(); 1175 1176 /** 1177 * Constructor. 1178 * 1179 * @param builder 1180 * The builder for this object. 1181 */ 1182 public XmlSerializer(Builder builder) { 1183 super(builder); 1184 autoDetectNamespaces = ! builder.disableAutoDetectNamespaces; 1185 enableNamespaces = builder.enableNamespaces; 1186 addNamespaceUrlsToRoot = builder.addNamespaceUrisToRoot; 1187 addBeanTypesXml = builder.addBeanTypesXml; 1188 defaultNamespace = builder.defaultNamespace != null ? builder.defaultNamespace : DEFAULT_JUNEAU_NAMESPACE; 1189 namespaces = builder.namespaces != null ? builder.namespaces.toArray(EMPTY_NAMESPACE_ARRAY) : EMPTY_NAMESPACE_ARRAY; 1190 addBeanTypes = addBeanTypesXml || super.isAddBeanTypes(); 1191 } 1192 1193 @Override /* Context */ 1194 public Builder copy() { 1195 return new Builder(this); 1196 } 1197 1198 @Override /* Context */ 1199 public XmlSerializerSession.Builder createSession() { 1200 return XmlSerializerSession.create(this); 1201 } 1202 1203 @Override /* Context */ 1204 public XmlSerializerSession getSession() { 1205 return createSession().build(); 1206 } 1207 1208 //----------------------------------------------------------------------------------------------------------------- 1209 // Extended metadata 1210 //----------------------------------------------------------------------------------------------------------------- 1211 1212 @Override /* XmlMetaProvider */ 1213 public XmlClassMeta getXmlClassMeta(ClassMeta<?> cm) { 1214 XmlClassMeta m = xmlClassMetas.get(cm); 1215 if (m == null) { 1216 m = new XmlClassMeta(cm, this); 1217 xmlClassMetas.put(cm, m); 1218 } 1219 return m; 1220 } 1221 1222 @Override /* XmlMetaProvider */ 1223 public XmlBeanMeta getXmlBeanMeta(BeanMeta<?> bm) { 1224 XmlBeanMeta m = xmlBeanMetas.get(bm); 1225 if (m == null) { 1226 m = new XmlBeanMeta(bm, this); 1227 xmlBeanMetas.put(bm, m); 1228 } 1229 return m; 1230 } 1231 1232 @Override /* XmlMetaProvider */ 1233 public XmlBeanPropertyMeta getXmlBeanPropertyMeta(BeanPropertyMeta bpm) { 1234 XmlBeanPropertyMeta m = xmlBeanPropertyMetas.get(bpm); 1235 if (m == null) { 1236 m = new XmlBeanPropertyMeta(bpm.getDelegateFor(), this); 1237 xmlBeanPropertyMetas.put(bpm, m); 1238 } 1239 return m; 1240 } 1241 1242 //----------------------------------------------------------------------------------------------------------------- 1243 // Properties 1244 //----------------------------------------------------------------------------------------------------------------- 1245 1246 /** 1247 * Add <js>"_type"</js> properties when needed. 1248 * 1249 * @see Builder#addBeanTypesXml() 1250 * @return 1251 * <jk>true</jk> if<js>"_type"</js> properties will be added to beans if their type cannot be inferred 1252 * through reflection. 1253 */ 1254 @Override 1255 protected boolean isAddBeanTypes() { 1256 return addBeanTypes; 1257 } 1258 1259 /** 1260 * Add namespace URLs to the root element. 1261 * 1262 * @see Builder#addNamespaceUrisToRoot() 1263 * @return 1264 * <jk>true</jk> if {@code xmlns:x} attributes are added to the root element for the default and all mapped namespaces. 1265 */ 1266 protected final boolean isAddNamespaceUrlsToRoot() { 1267 return addNamespaceUrlsToRoot; 1268 } 1269 1270 /** 1271 * Auto-detect namespace usage. 1272 * 1273 * @see Builder#disableAutoDetectNamespaces() 1274 * @return 1275 * <jk>true</jk> if namespace usage is detected before serialization. 1276 */ 1277 protected final boolean isAutoDetectNamespaces() { 1278 return autoDetectNamespaces; 1279 } 1280 1281 /** 1282 * Default namespace. 1283 * 1284 * @see Builder#defaultNamespace(Namespace) 1285 * @return 1286 * The default namespace URI for this document. 1287 */ 1288 protected final Namespace getDefaultNamespace() { 1289 return defaultNamespace; 1290 } 1291 1292 /** 1293 * Enable support for XML namespaces. 1294 * 1295 * @see Builder#enableNamespaces() 1296 * @return 1297 * <jk>false</jk> if XML output will not contain any namespaces regardless of any other settings. 1298 */ 1299 protected final boolean isEnableNamespaces() { 1300 return enableNamespaces; 1301 } 1302 1303 /** 1304 * Default namespaces. 1305 * 1306 * @see Builder#namespaces(Namespace...) 1307 * @return 1308 * The default list of namespaces associated with this serializer. 1309 */ 1310 protected final Namespace[] getNamespaces() { 1311 return namespaces; 1312 } 1313 1314 //----------------------------------------------------------------------------------------------------------------- 1315 // Other methods 1316 //----------------------------------------------------------------------------------------------------------------- 1317 1318 @Override /* Context */ 1319 protected JsonMap properties() { 1320 return filteredMap() 1321 .append("autoDetectNamespaces", autoDetectNamespaces) 1322 .append("enableNamespaces", enableNamespaces) 1323 .append("addNamespaceUrlsToRoot", addNamespaceUrlsToRoot) 1324 .append("defaultNamespace", defaultNamespace) 1325 .append("namespaces", namespaces) 1326 .append("addBeanTypes", addBeanTypes); 1327 } 1328}