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>' &gt; 640'</js>
063 *    }
064 * <p>
065 *    ...maps to the following XML using the default serializer...
066 * <p class='bxml'>
067 *    <xt>&lt;object&gt;</xt>
068 *       <xt>&lt;name&gt;</xt>John Smith<xt>&lt;/name&gt;</xt>
069 *       <xt>&lt;address&gt;</xt>
070 *          <xt>&lt;streetAddress&gt;</xt>21 2nd Street<xt>&lt;/streetAddress&gt;</xt>
071 *          <xt>&lt;city&gt;</xt>New York<xt>&lt;/city&gt;</xt>
072 *          <xt>&lt;state&gt;</xt>NY<xt>&lt;/state&gt;</xt>
073 *          <xt>&lt;postalCode&gt;</xt>10021<xt>&lt;/postalCode&gt;</xt>
074 *       <xt>&lt;/address&gt;</xt>
075 *       <xt>&lt;phoneNumbers&gt;</xt>
076 *          <xt>&lt;string&gt;</xt>212 555-1111<xt>&lt;/string&gt;</xt>
077 *          <xt>&lt;string&gt;</xt>212 555-2222<xt>&lt;/string&gt;</xt>
078 *       <xt>&lt;/phoneNumbers&gt;</xt>
079 *       <xt>&lt;additionalInfo</xt> <xa>_type</xa>=<xs>'null'</xs><xt>&gt;&lt;/additionalInfo&gt;</xt>
080 *       <xt>&lt;remote&gt;</xt>false<xt>&lt;/remote&gt;</xt>
081 *       <xt>&lt;height&gt;</xt>62.4<xt>&lt;/height&gt;</xt>
082 *       <xt>&lt;fico_x0020_score&gt;</xt> &amp;gt; 640<xt>&lt;/fico_x0020_score&gt;</xt>
083 *    <xt>&lt;/object&gt;</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>&lt;object&gt;</xt>
089 *       <xt>&lt;name</xt> <xa>_type</xa>=<xs>'string'</xs><xt>&gt;</xt>John Smith<xt>&lt;/name&gt;</xt>
090 *       <xt>&lt;address</xt> <xa>_type</xa>=<xs>'object'</xs><xt>&gt;</xt>
091 *          <xt>&lt;streetAddress</xt> <xa>_type</xa>=<xs>'string'</xs><xt>&gt;</xt>21 2nd Street<xt>&lt;/streetAddress&gt;</xt>
092 *          <xt>&lt;city</xt> <xa>_type</xa>=<xs>'string'</xs><xt>&gt;</xt>New York<xt>&lt;/city&gt;</xt>
093 *          <xt>&lt;state</xt> <xa>_type</xa>=<xs>'string'</xs><xt>&gt;</xt>NY<xt>&lt;/state&gt;</xt>
094 *          <xt>&lt;postalCode</xt> <xa>_type</xa>=<xs>'number'</xs><xt>&gt;</xt>10021<xt>&lt;/postalCode&gt;</xt>
095 *       <xt>&lt;/address&gt;</xt>
096 *       <xt>&lt;phoneNumbers</xt> <xa>_type</xa>=<xs>'array'</xs><xt>&gt;</xt>
097 *          <xt>&lt;string&gt;</xt>212 555-1111<xt>&lt;/string&gt;</xt>
098 *          <xt>&lt;string&gt;</xt>212 555-2222<xt>&lt;/string&gt;</xt>
099 *       <xt>&lt;/phoneNumbers&gt;</xt>
100 *       <xt>&lt;additionalInfo</xt> <xa>_type</xa>=<xs>'null'</xs><xt>&gt;&lt;/additionalInfo&gt;</xt>
101 *       <xt>&lt;remote</xt> <xa>_type</xa>=<xs>'boolean'</xs><xt>&gt;</xt>false<xt>&lt;/remote&gt;</xt>
102 *       <xt>&lt;height</xt> <xa>_type</xa>=<xs>'number'</xs><xt>&gt;</xt>62.4<xt>&lt;/height&gt;</xt>
103 *       <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>
104 *    <xt>&lt;/object&gt;</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}