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