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;
014
015import static org.apache.juneau.Visibility.*;
016import static org.apache.juneau.collections.JsonMap.*;
017import static org.apache.juneau.common.internal.StringUtils.*;
018import static org.apache.juneau.common.internal.ThrowableUtils.*;
019import static org.apache.juneau.internal.ClassUtils.*;
020import static org.apache.juneau.internal.CollectionUtils.*;
021
022import java.beans.*;
023import java.io.*;
024import java.lang.annotation.*;
025import java.lang.reflect.*;
026import java.util.*;
027import java.util.concurrent.*;
028import java.util.stream.*;
029
030import org.apache.juneau.annotation.*;
031import org.apache.juneau.collections.*;
032import org.apache.juneau.cp.*;
033import org.apache.juneau.internal.*;
034import org.apache.juneau.json.*;
035import org.apache.juneau.marshaller.*;
036import org.apache.juneau.reflect.*;
037import org.apache.juneau.serializer.*;
038import org.apache.juneau.swap.*;
039import org.apache.juneau.utils.*;
040
041/**
042 * Bean context.
043 *
044 * <p>
045 * This class servers multiple purposes:
046 * <ul class='spaced-list'>
047 *    <li>
048 *       Provides the ability to wrap beans inside {@link Map} interfaces.
049 *    <li>
050 *       Serves as a repository for metadata on POJOs, such as associated {@link Bean @Bean} annotations,
051 *       {@link PropertyNamer PropertyNamers}, etc...  which are used to tailor how POJOs are serialized and parsed.
052 * </ul>
053 *
054 * <p>
055 * All serializers and parsers use this context so that they can handle POJOs using a common framework.
056 *
057 * <h5 class='topic'>Bean Contexts</h5>
058 *
059 * <p>
060 * Bean contexts are created through the {@link BeanContext#create() BeanContext.create()} and {@link Builder#build()} methods.
061 * <br>These context objects are read-only, reusable, and thread-safe.
062 *
063 * <p>
064 * Each bean context maintains a cache of {@link ClassMeta} objects that describe information about classes encountered.
065 * These <c>ClassMeta</c> objects are time-consuming to construct.
066 * Therefore, instances of {@link BeanContext} that share the same <js>"BeanContext.*"</js> property values share
067 * the same cache.  This allows for efficient reuse of <c>ClassMeta</c> objects so that the information about
068 * classes only needs to be calculated once.
069 * Because of this, many of the properties defined on the {@link BeanContext} class cannot be overridden on the session.
070 *
071 * <h5 class='topic'>Bean Sessions</h5>
072 *
073 * <p>
074 * Whereas <c>BeanContext</c> objects are permanent, unchangeable, cached, and thread-safe,
075 * {@link BeanSession} objects are ephemeral and not thread-safe.
076 * They are meant to be used as quickly-constructed scratchpads for creating bean maps.
077 * {@link BeanMap} objects can only be created through the session.
078 *
079 * <h5 class='topic'>BeanContext configuration properties</h5>
080 *
081 * <p>
082 * <c>BeanContexts</c> have several configuration properties that can be used to tweak behavior on how beans are
083 * handled.  These are denoted as the static <jsf>BEAN_*</jsf> fields on this class.
084 *
085 * <p>
086 * Some settings (e.g. {@link Builder#beansRequireDefaultConstructor()}) are used to differentiate between bean
087 * and non-bean classes.
088 * Attempting to create a bean map around one of these objects will throw a {@link BeanRuntimeException}.
089 * The purpose for this behavior is so that the serializers can identify these non-bean classes and convert them to
090 * plain strings using the {@link Object#toString()} method.
091 *
092 * <p>
093 * Some settings (e.g. {@link Builder#beanFieldVisibility(Visibility)}) are used to determine what kinds of properties are
094 * detected on beans.
095 *
096 * <p>
097 * Some settings (e.g. {@link Builder#beanMapPutReturnsOldValue()}) change the runtime behavior of bean maps.
098 *
099 * <h5 class='section'>Example:</h5>
100 *
101 * <p class='bjava'>
102 *    <jc>// Construct a context from scratch.</jc>
103 *    BeanContext <jv>beanContext</jv> = BeanContext
104 *       .<jsm>create</jsm>()
105 *       .beansRequireDefaultConstructor()
106 *       .notBeanClasses(Foo.<jk>class</jk>)
107 *       .build();
108 * </p>
109 *
110 * <h5 class='topic'>Bean Maps</h5>
111 *
112 * <p>
113 * {@link BeanMap BeanMaps} are wrappers around Java beans that allow properties to be retrieved and
114 * set using the common {@link Map#put(Object,Object)} and {@link Map#get(Object)} methods.
115 *
116 * <p>
117 * Bean maps are created in two ways...
118 * <ol>
119 *    <li>{@link BeanSession#toBeanMap(Object) BeanSession.toBeanMap()} - Wraps an existing bean inside a {@code Map}
120 *       wrapper.
121 *    <li>{@link BeanSession#newBeanMap(Class) BeanSession.newBeanMap()} - Create a new bean instance wrapped in a
122 *       {@code Map} wrapper.
123 * </ol>
124 *
125 * <h5 class='section'>Example:</h5>
126 *
127 * <p class='bjava'>
128 *    <jc>// A sample bean class</jc>
129 *    <jk>public class</jk> Person {
130 *       <jk>public</jk> String getName();
131 *       <jk>public void</jk> setName(String <jv>name</jv>);
132 *       <jk>public int</jk> getAge();
133 *       <jk>public void</jk> setAge(<jk>int</jk> <jv>age</jv>);
134 *    }
135 *
136 *    <jc>// Create a new bean session</jc>
137 *    BeanSession <jv>session</jv> = BeanContext.<jsf>DEFAULT</jsf>.createSession();
138 *
139 *    <jc>// Wrap an existing bean in a new bean map</jc>
140 *    BeanMap&lt;Person&gt; <jv>map1</jv> = <jv>session</jv>.toBeanMap(<jk>new</jk> Person());
141 *    <jv>map1</jv>.put(<js>"name"</js>, <js>"John Smith"</js>);
142 *    <jv>map1</jv>.put(<js>"age"</js>, 45);
143 *
144 *    <jc>// Create a new bean instance wrapped in a new bean map</jc>
145 *    BeanMap&lt;Person&gt; <jv>map2</jv> = <jv>session</jv>.newBeanMap(Person.<jk>class</jk>);
146 *    <jv>map2</jv>.put(<js>"name"</js>, <js>"John Smith"</js>);
147 *    <jv>map2</jv>.put(<js>"age"</js>, 45);
148 *    Person <jv>person</jv> = <jv>map2</jv>.getBean();  <jc>// Get the bean instance that was created.</jc>
149 * </p>
150 *
151 * <h5 class='section'>Notes:</h5><ul>
152 *    <li class='note'>This class is thread safe and reusable.
153 * </ul>
154 *
155 * <h5 class='section'>See Also:</h5><ul>
156 *    <li class='link'><a class="doclink" href="../../../index.html#jm.BeanContexts">Bean Contexts</a>
157 * </ul>
158 */
159@SuppressWarnings({"unchecked","rawtypes"})
160public class BeanContext extends Context {
161
162   //-----------------------------------------------------------------------------------------------------------------
163   // Static
164   //-----------------------------------------------------------------------------------------------------------------
165
166   /*
167    * The default package pattern exclusion list.
168    * Any beans in packages in this list will not be considered beans.
169    */
170   private static final String[] DEFAULT_NOTBEAN_PACKAGES = {
171      "java.lang",
172      "java.lang.annotation",
173      "java.lang.ref",
174      "java.lang.reflect",
175      "java.io",
176      "java.net",
177      "java.nio.*",
178      "java.util.*"
179   };
180
181   /*
182    * The default bean class exclusion list.
183    * Anything in this list will not be considered beans.
184    */
185   private static final Class<?>[] DEFAULT_NOTBEAN_CLASSES = {
186      Map.class,
187      Collection.class,
188      Reader.class,
189      Writer.class,
190      InputStream.class,
191      OutputStream.class,
192      Throwable.class
193   };
194
195
196   /** Default config.  All default settings. */
197   public static final BeanContext DEFAULT = create().build();
198
199   /** Default config.  All default settings except sort bean properties. */
200   public static final BeanContext DEFAULT_SORTED = create().sortProperties().build();
201
202   /** Default reusable unmodifiable session.  Can be used to avoid overhead of creating a session (for creating BeanMaps for example).*/
203   public  static final BeanSession DEFAULT_SESSION = DEFAULT.createSession().unmodifiable().build();
204
205   /**
206    * Creates a new builder for this object.
207    *
208    * @return A new builder.
209    */
210   public static Builder create() {
211      return new Builder();
212   }
213
214   //-----------------------------------------------------------------------------------------------------------------
215   // Builder
216   //-----------------------------------------------------------------------------------------------------------------
217
218   /**
219    * Builder class.
220    */
221   @FluentSetters
222   public static class Builder extends Context.Builder {
223
224      private static final Cache<HashKey,BeanContext> CACHE = Cache.of(HashKey.class, BeanContext.class).build();
225
226      Visibility beanClassVisibility, beanConstructorVisibility, beanMethodVisibility, beanFieldVisibility;
227      boolean disableBeansRequireSomeProperties, beanMapPutReturnsOldValue, beansRequireDefaultConstructor, beansRequireSerializable,
228         beansRequireSettersForGetters, disableIgnoreTransientFields, disableIgnoreUnknownNullBeanProperties, disableIgnoreMissingSetters,
229         disableInterfaceProxies, findFluentSetters, ignoreInvocationExceptionsOnGetters, ignoreInvocationExceptionsOnSetters,
230         ignoreUnknownBeanProperties, ignoreUnknownEnumValues, sortProperties, useEnumNames, useJavaBeanIntrospector;
231      String typePropertyName;
232      MediaType mediaType;
233      Locale locale;
234      TimeZone timeZone;
235      Class<? extends PropertyNamer> propertyNamer;
236      List<Class<?>> beanDictionary;
237      List<Object> swaps;
238      Set<Class<?>> notBeanClasses;
239      Set<String> notBeanPackages;
240
241      /**
242       * Constructor.
243       *
244       * All default settings.
245       */
246      protected Builder() {
247         beanClassVisibility = env("BeanContext.beanClassVisibility", PUBLIC);
248         beanConstructorVisibility = env("BeanContext.beanConstructorVisibility", PUBLIC);
249         beanMethodVisibility = env("BeanContext.beanMethodVisibility", PUBLIC);
250         beanFieldVisibility = env("BeanContext.beanFieldVisibility", PUBLIC);
251         beanDictionary = null;
252         swaps = null;
253         notBeanClasses = null;
254         notBeanPackages = null;
255         disableBeansRequireSomeProperties = env("BeanContext.disableBeansRequireSomeProperties", false);
256         beanMapPutReturnsOldValue = env("BeanContext.beanMapPutReturnsOldValue", false);
257         beansRequireDefaultConstructor = env("BeanContext.beansRequireDefaultConstructor", false);
258         beansRequireSerializable = env("BeanContext.beansRequireSerializable", false);
259         beansRequireSettersForGetters = env("BeanContext.beansRequireSettersForGetters", false);
260         disableIgnoreTransientFields = env("BeanContext.disableIgnoreTransientFields", false);
261         disableIgnoreUnknownNullBeanProperties = env("BeanContext.disableIgnoreUnknownNullBeanProperties", false);
262         disableIgnoreMissingSetters = env("BeanContext.disableIgnoreMissingSetters", false);
263         disableInterfaceProxies = env("BeanContext.disableInterfaceProxies", false);
264         findFluentSetters = env("BeanContext.findFluentSetters", false);
265         ignoreInvocationExceptionsOnGetters = env("BeanContext.ignoreInvocationExceptionsOnGetters", false);
266         ignoreInvocationExceptionsOnSetters = env("BeanContext.ignoreInvocationExceptionsOnSetters", false);
267         ignoreUnknownBeanProperties = env("BeanContext.ignoreUnknownBeanProperties", false);
268         ignoreUnknownEnumValues = env("BeanContext.ignoreUnknownEnumValues", false);
269         sortProperties = env("BeanContext.sortProperties", false);
270         useEnumNames = env("BeanContext.useEnumNames", false);
271         useJavaBeanIntrospector = env("BeanContext.useJavaBeanIntrospector", false);
272         typePropertyName = env("BeanContext.typePropertyName", "_type");
273         mediaType = env("BeanContext.mediaType", (MediaType)null);
274         timeZone = env("BeanContext.timeZone", (TimeZone)null);
275         locale = env("BeanContext.locale", Locale.getDefault());
276         propertyNamer = null;
277      }
278
279      /**
280       * Copy constructor.
281       *
282       * @param copyFrom The bean to copy from.
283       */
284      protected Builder(BeanContext copyFrom) {
285         super(copyFrom);
286         beanClassVisibility = copyFrom.beanClassVisibility;
287         beanConstructorVisibility = copyFrom.beanConstructorVisibility;
288         beanMethodVisibility = copyFrom.beanMethodVisibility;
289         beanFieldVisibility = copyFrom.beanFieldVisibility;
290         beanDictionary = listFrom(copyFrom.beanDictionary, true);
291         swaps = listFrom(copyFrom.swaps, true);
292         notBeanClasses = classSet(copyFrom.notBeanClasses, true);
293         notBeanPackages = sortedSetFrom(copyFrom.notBeanPackages, true);
294         disableBeansRequireSomeProperties = ! copyFrom.beansRequireSomeProperties;
295         beanMapPutReturnsOldValue = copyFrom.beanMapPutReturnsOldValue;
296         beansRequireDefaultConstructor = copyFrom.beansRequireDefaultConstructor;
297         beansRequireSerializable = copyFrom.beansRequireSerializable;
298         beansRequireSettersForGetters = copyFrom.beansRequireSettersForGetters;
299         disableIgnoreTransientFields = ! copyFrom.ignoreTransientFields;
300         disableIgnoreUnknownNullBeanProperties = ! copyFrom.ignoreUnknownNullBeanProperties;
301         disableIgnoreMissingSetters = ! copyFrom.ignoreMissingSetters;
302         disableInterfaceProxies = ! copyFrom.useInterfaceProxies;
303         findFluentSetters = copyFrom.findFluentSetters;
304         ignoreInvocationExceptionsOnGetters = copyFrom.ignoreInvocationExceptionsOnGetters;
305         ignoreInvocationExceptionsOnSetters = copyFrom.ignoreInvocationExceptionsOnSetters;
306         ignoreUnknownBeanProperties = copyFrom.ignoreUnknownBeanProperties;
307         ignoreUnknownEnumValues = copyFrom.ignoreUnknownEnumValues;
308         sortProperties = copyFrom.sortProperties;
309         useEnumNames = copyFrom.useEnumNames;
310         useJavaBeanIntrospector = copyFrom.useJavaBeanIntrospector;
311         typePropertyName = copyFrom.typePropertyName;
312         mediaType = copyFrom.mediaType;
313         timeZone = copyFrom.timeZone;
314         locale = copyFrom.locale;
315         propertyNamer = copyFrom.propertyNamer;
316      }
317
318      /**
319       * Copy constructor.
320       *
321       * @param copyFrom The builder to copy from.
322       */
323      protected Builder(Builder copyFrom) {
324         super(copyFrom);
325         beanClassVisibility = copyFrom.beanClassVisibility;
326         beanConstructorVisibility = copyFrom.beanConstructorVisibility;
327         beanMethodVisibility = copyFrom.beanMethodVisibility;
328         beanFieldVisibility = copyFrom.beanFieldVisibility;
329         beanDictionary = copyOf(copyFrom.beanDictionary);
330         swaps = copyOf(copyFrom.swaps);
331         notBeanClasses = classSet(copyFrom.notBeanClasses);
332         notBeanPackages = sortedSetFrom(copyFrom.notBeanPackages);
333         disableBeansRequireSomeProperties = copyFrom.disableBeansRequireSomeProperties;
334         beanMapPutReturnsOldValue = copyFrom.beanMapPutReturnsOldValue;
335         beansRequireDefaultConstructor = copyFrom.beansRequireDefaultConstructor;
336         beansRequireSerializable = copyFrom.beansRequireSerializable;
337         beansRequireSettersForGetters = copyFrom.beansRequireSettersForGetters;
338         disableIgnoreTransientFields = copyFrom.disableIgnoreTransientFields;
339         disableIgnoreUnknownNullBeanProperties = copyFrom.disableIgnoreUnknownNullBeanProperties;
340         disableIgnoreMissingSetters = copyFrom.disableIgnoreMissingSetters;
341         disableInterfaceProxies = copyFrom.disableInterfaceProxies;
342         findFluentSetters = copyFrom.findFluentSetters;
343         ignoreInvocationExceptionsOnGetters = copyFrom.ignoreInvocationExceptionsOnGetters;
344         ignoreInvocationExceptionsOnSetters = copyFrom.ignoreInvocationExceptionsOnSetters;
345         ignoreUnknownBeanProperties = copyFrom.ignoreUnknownBeanProperties;
346         ignoreUnknownEnumValues = copyFrom.ignoreUnknownEnumValues;
347         sortProperties = copyFrom.sortProperties;
348         useEnumNames = copyFrom.useEnumNames;
349         useJavaBeanIntrospector = copyFrom.useJavaBeanIntrospector;
350         typePropertyName = copyFrom.typePropertyName;
351         mediaType = copyFrom.mediaType;
352         timeZone = copyFrom.timeZone;
353         locale = copyFrom.locale;
354         propertyNamer = copyFrom.propertyNamer;
355      }
356
357      @Override /* Context.Builder */
358      public Builder copy() {
359         return new Builder(this);
360      }
361
362      @Override /* Context.Builder */
363      public BeanContext build() {
364         return cache(CACHE).build(BeanContext.class);
365      }
366
367      @Override /* Context.Builder */
368      public HashKey hashKey() {
369         return HashKey.of(
370            super.hashKey(),
371            beanClassVisibility,
372            beanConstructorVisibility,
373            beanMethodVisibility,
374            beanFieldVisibility,
375            beanDictionary,
376            swaps,
377            notBeanClasses,
378            notBeanPackages,
379            integer(
380               disableBeansRequireSomeProperties,
381               beanMapPutReturnsOldValue,
382               beansRequireDefaultConstructor,
383               beansRequireSerializable,
384               beansRequireSettersForGetters,
385               disableIgnoreTransientFields,
386               disableIgnoreUnknownNullBeanProperties,
387               disableIgnoreMissingSetters,
388               disableInterfaceProxies,
389               findFluentSetters,
390               ignoreInvocationExceptionsOnGetters,
391               ignoreInvocationExceptionsOnSetters,
392               ignoreUnknownBeanProperties,
393               ignoreUnknownEnumValues,
394               sortProperties,
395               useEnumNames,
396               useJavaBeanIntrospector
397            ),
398            typePropertyName,
399            mediaType,
400            timeZone,
401            locale,
402            propertyNamer
403         );
404      }
405
406      private int integer(boolean...values) {
407         int n = 0;
408         for (boolean b : values)
409            n = (n << 1) | (b ? 1 : 0);
410         return n;
411      }
412
413      //-----------------------------------------------------------------------------------------------------------------
414      // Properties
415      //-----------------------------------------------------------------------------------------------------------------
416
417      /**
418       * Minimum bean class visibility.
419       *
420       * <p>
421       * Classes are not considered beans unless they meet the minimum visibility requirements.
422       * For example, if the visibility is <jsf>PUBLIC</jsf> and the bean class is <jk>protected</jk>, then the class
423       * will not be interpreted as a bean class and be serialized as a string.
424       * Use this setting to reduce the visibility requirement.
425       *
426       * <h5 class='section'>Example:</h5>
427       * <p class='bjava'>
428       *    <jc>// A bean with a protected class and one field.</jc>
429       *    <jk>protected class</jk> MyBean {
430       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
431       *    }
432       *
433       *    <jc>// Create a serializer that's capable of serializing the class.</jc>
434       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
435       *       .<jsm>create</jsm>()
436       *       .beanClassVisibility(<jsf>PROTECTED</jsf>)
437       *       .build();
438       *
439       *    <jc>// Produces:  {"foo","bar"}</jc>
440       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
441       * </p>
442       *
443       * <h5 class='section'>Notes:</h5><ul>
444       *    <li class='note'>The {@link Bean @Bean} annotation can be used on a non-public bean class to override this setting.
445       *    <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean class to ignore it as a bean.
446       * </ul>
447       *
448       * <h5 class='section'>See Also:</h5><ul>
449       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanClassVisibility()}
450       * </ul>
451       *
452       * @param value
453       *    The new value for this setting.
454       *    <br>The default is {@link Visibility#PUBLIC}.
455       * @return This object.
456       */
457      @FluentSetter
458      public Builder beanClassVisibility(Visibility value) {
459         beanClassVisibility = value;
460         return this;
461      }
462
463      /**
464       * Minimum bean constructor visibility.
465       *
466       * <p>
467       * Only look for constructors with the specified minimum visibility.
468       *
469       * <p>
470       * This setting affects the logic for finding no-arg constructors for bean.  Normally, only <jk>public</jk> no-arg
471       * constructors are used.  Use this setting if you want to reduce the visibility requirement.
472       *
473       * <h5 class='section'>Example:</h5>
474       * <p class='bjava'>
475       *    <jc>// A bean with a protected constructor and one field.</jc>
476       *    <jk>public class</jk> MyBean {
477       *       <jk>public</jk> String <jf>foo</jf>;
478       *
479       *       <jk>protected</jk> MyBean() {}
480       *    }
481       *
482       *    <jc>// Create a parser capable of calling the protected constructor.</jc>
483       *    ReaderParser <jv>parser</jv> = ReaderParser
484       *       .<jsm>create</jsm>()
485       *       .beanConstructorVisibility(<jsf>PROTECTED</jsf>)
486       *       .build();
487       *
488       *    <jc>// Use it.</jc>
489       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>);
490       * </p>
491       *
492       * <h5 class='section'>Notes:</h5><ul>
493       *    <li class='note'>The {@link Beanc @Beanc} annotation can also be used to expose a non-public constructor.
494       *    <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean constructor to ignore it.
495       * </ul>
496       *
497       * <h5 class='section'>See Also:</h5><ul>
498       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanConstructorVisibility()}
499       * </ul>
500       *
501       * @param value
502       *    The new value for this setting.
503       *    <br>The default is {@link Visibility#PUBLIC}.
504       * @return This object.
505       */
506      @FluentSetter
507      public Builder beanConstructorVisibility(Visibility value) {
508         beanConstructorVisibility = value;
509         return this;
510      }
511
512      /**
513       * Minimum bean field visibility.
514       *
515       * <p>
516       * Only look for bean fields with the specified minimum visibility.
517       *
518       * <p>
519       * This affects which fields on a bean class are considered bean properties.  Normally only <jk>public</jk> fields are considered.
520       * Use this setting if you want to reduce the visibility requirement.
521       *
522       * <h5 class='section'>Example:</h5>
523       * <p class='bjava'>
524       *    <jc>// A bean with a protected field.</jc>
525       *    <jk>public class</jk> MyBean {
526       *       <jk>protected</jk> String <jf>foo</jf> = <js>"bar"</js>;
527       *    }
528       *
529       *    <jc>// Create a serializer that recognizes the protected field.</jc>
530       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
531       *       .<jsm>create</jsm>()
532       *       .beanFieldVisibility(<jsf>PROTECTED</jsf>)
533       *       .build();
534       *
535       *    <jc>// Produces:  {"foo":"bar"}</jc>
536       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
537       * </p>
538       *
539       * <p>
540       * Bean fields can be ignored as properties entirely by setting the value to {@link Visibility#NONE}
541       *
542       * <p class='bjava'>
543       *    <jc>// Disable using fields as properties entirely.</jc>
544       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
545       *       .<jsm>create</jsm>()
546       *       .beanFieldVisibility(<jsf>NONE</jsf>)
547       *       .build();
548       * </p>
549       *
550       * <h5 class='section'>Notes:</h5><ul>
551       *    <li class='note'>The {@link Beanp @Beanp} annotation can also be used to expose a non-public field.
552       *    <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean field to ignore it as a bean property.
553       * </ul>
554       *
555       * <h5 class='section'>See Also:</h5><ul>
556       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanFieldVisibility()}
557       * </ul>
558       *
559       * @param value
560       *    The new value for this setting.
561       *    <br>The default is {@link Visibility#PUBLIC}.
562       * @return This object.
563       */
564      @FluentSetter
565      public Builder beanFieldVisibility(Visibility value) {
566         beanFieldVisibility = value;
567         return this;
568      }
569
570      /**
571       * Bean interceptor.
572       *
573       * <p>
574       * Bean interceptors can be used to intercept calls to getters and setters and alter their values in transit.
575       *
576       * <h5 class='section'>Example:</h5>
577       * <p class='bjava'>
578       *    <jc>// Interceptor that strips out sensitive information.</jc>
579       *    <jk>public class</jk> AddressInterceptor <jk>extends</jk> BeanInterceptor&lt;Address&gt; {
580       *
581       *       <jk>public</jk> Object readProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) {
582       *          <jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>))
583       *             <jk>return</jk> <js>"redacted"</js>;
584       *          <jk>return</jk> <jv>value</jv>;
585       *       }
586       *
587       *       <jk>public</jk> Object writeProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) {
588       *          <jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>) &amp;&amp; <js>"redacted"</js>.equals(<jv>value</jv>))
589       *             <jk>return</jk> TaxInfoUtils.<jsm>lookup</jsm>(<jv>bean</jv>.getStreet(), <jv>bean</jv>.getCity(), <jv>bean</jv>.getState());
590       *          <jk>return</jk> <jv>value</jv>;
591       *       }
592       *    }
593       *
594       *    <jc>// Our bean class.</jc>
595       *    <jk>public class</jk> Address {
596       *       <jk>public</jk> String getTaxInfo() {...}
597       *       <jk>public void</jk> setTaxInfo(String <jv>value</jv>) {...}
598       *    }
599       *
600       *    <jc>// Register filter on serializer or parser.</jc>
601       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
602       *       .<jsm>create</jsm>()
603       *       .beanInterceptor(Address.<jk>class</jk>, AddressInterceptor.<jk>class</jk>)
604       *       .build();
605       *
606       *    <jc>// Produces:  {"taxInfo":"redacted"}</jc>
607       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> Address());
608       * </p>
609       *
610       * <h5 class='section'>See Also:</h5><ul>
611       *    <li class='jc'>{@link BeanInterceptor}
612       *    <li class='ja'>{@link Bean#interceptor() Bean(interceptor)}
613       * </ul>
614       *
615       * @param on The bean that the filter applies to.
616       * @param value
617       *    The new value for this setting.
618       * @return This object.
619       */
620      @FluentSetter
621      public Builder beanInterceptor(Class<?> on, Class<? extends BeanInterceptor<?>> value) {
622         return annotations(BeanAnnotation.create(on).interceptor(value).build());
623      }
624
625      /**
626       * BeanMap.put() returns old property value.
627       *
628       * <p>
629       * When enabled, then the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property
630       * values.  Otherwise, it returns <jk>null</jk>.
631       *
632       * <p>
633       * Disabled by default because it introduces a slight performance penalty during serialization.
634       *
635       * <h5 class='section'>Example:</h5>
636       * <p class='bjava'>
637       *    <jc>// Create a context that creates BeanMaps with normal put() behavior.</jc>
638       *    BeanContext <jv>context</jv> = BeanContext
639       *       .<jsm>create</jsm>()
640       *       .beanMapPutReturnsOldValue()
641       *       .build();
642       *
643       *    BeanMap&lt;MyBean&gt; <jv>myBeanMap</jv> = <jv>context</jv>.createSession().toBeanMap(<jk>new</jk> MyBean());
644       *    <jv>myBeanMap</jv>.put(<js>"foo"</js>, <js>"bar"</js>);
645       *    Object <jv>oldValue</jv> = <jv>myBeanMap</jv>.put(<js>"foo"</js>, <js>"baz"</js>);  <jc>// oldValue == "bar"</jc>
646       * </p>
647       *
648       * <h5 class='section'>See Also:</h5><ul>
649       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanMapPutReturnsOldValue()}
650       * </ul>
651       *
652       * @return This object.
653       */
654      @FluentSetter
655      public Builder beanMapPutReturnsOldValue() {
656         return beanMapPutReturnsOldValue(true);
657      }
658
659      /**
660       * Same as {@link #beanMapPutReturnsOldValue()} but allows you to explicitly specify the value.
661       *
662       * @param value The value for this setting.
663       * @return This object.
664       */
665      @FluentSetter
666      public Builder beanMapPutReturnsOldValue(boolean value) {
667         beanMapPutReturnsOldValue = value;
668         return this;
669      }
670
671      /**
672       * Minimum bean method visibility.
673       *
674       * <p>
675       * Only look for bean methods with the specified minimum visibility.
676       *
677       * <p>
678       * This affects which methods are detected as getters and setters on a bean class. Normally only <jk>public</jk> getters and setters are considered.
679       * Use this setting if you want to reduce the visibility requirement.
680       *
681       * <h5 class='section'>Example:</h5>
682       * <p class='bjava'>
683       *    <jc>// A bean with a protected getter.</jc>
684       *    <jk>public class</jk> MyBean {
685       *       <jk>public</jk> String getFoo() { <jk>return</jk> <js>"foo"</js>; }
686       *       <jk>protected</jk> String getBar() { <jk>return</jk> <js>"bar"</js>; }
687       *    }
688       *
689       *    <jc>// Create a serializer that looks for protected getters and setters.</jc>
690       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
691       *       .<jsm>create</jsm>()
692       *       .beanMethodVisibility(<jsf>PROTECTED</jsf>)
693       *       .build();
694       *
695       *    <jc>// Produces:  {"foo":"foo","bar":"bar"}</jc>
696       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
697       * </p>
698       *
699       * <h5 class='section'>Notes:</h5><ul>
700       *    <li class='note'>The {@link Beanp @Beanp} annotation can also be used to expose a non-public method.
701       *    <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean getter/setter to ignore it as a bean property.
702       * </ul>
703       *
704       * <h5 class='section'>See Also:</h5><ul>
705       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beanMethodVisibility()}
706       * </ul>
707       *
708       * @param value
709       *    The new value for this setting.
710       *    <br>The default is {@link Visibility#PUBLIC}
711       * @return This object.
712       */
713      @FluentSetter
714      public Builder beanMethodVisibility(Visibility value) {
715         beanMethodVisibility = value;
716         return this;
717      }
718
719      /**
720       * Beans require no-arg constructors.
721       *
722       * <p>
723       * When enabled, a Java class must implement a default no-arg constructor to be considered a bean.
724       * Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method.
725       *
726       * <h5 class='section'>Example:</h5>
727       * <p class='bjava'>
728       *    <jc>// A bean without a no-arg constructor.</jc>
729       *    <jk>public class</jk> MyBean {
730       *
731       *       <jc>// A property method.</jc>
732       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
733       *
734       *       <jc>// A no-arg constructor</jc>
735       *       <jk>public</jk> MyBean(String <jv>foo</jv>) {
736       *          <jk>this</jk>.<jf>foo</jf> = <jv>foo</jv>;
737       *       }
738       *
739       *       <ja>@Override</ja>
740       *       <jk>public</jk> String toString() {
741       *          <jk>return</jk> <js>"bar"</js>;
742       *       }
743       *    }
744       *
745       *    <jc>// Create a serializer that ignores beans without default constructors.</jc>
746       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
747       *       .<jsm>create</jsm>()
748       *       .beansRequireDefaultConstructor()
749       *       .build();
750       *
751       *    <jc>// Produces:  "bar"</jc>
752       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
753       * </p>
754       *
755       * <h5 class='section'>Notes:</h5><ul>
756       *    <li class='note'>The {@link Bean @Bean} annotation can be used on a bean class to override this setting.
757       *    <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a class to ignore it as a bean.
758       * </ul>
759       *
760       * <h5 class='section'>See Also:</h5><ul>
761       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beansRequireDefaultConstructor()}
762       * </ul>
763       *
764       * @return This object.
765       */
766      @FluentSetter
767      public Builder beansRequireDefaultConstructor() {
768         return beansRequireDefaultConstructor(true);
769      }
770
771      /**
772       * Same as {@link #beansRequireDefaultConstructor()} but allows you to explicitly specify the value.
773       *
774       * @param value The value for this setting.
775       * @return This object.
776       */
777      @FluentSetter
778      public Builder beansRequireDefaultConstructor(boolean value) {
779         beansRequireDefaultConstructor = value;
780         return this;
781      }
782
783      /**
784       * Beans require Serializable interface.
785       *
786       * <p>
787       * When enabled, a Java class must implement the {@link Serializable} interface to be considered a bean.
788       * Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method.
789       *
790       * <h5 class='section'>Example:</h5>
791       * <p class='bjava'>
792       *    <jc>// A bean without a Serializable interface.</jc>
793       *    <jk>public class</jk> MyBean {
794       *
795       *       <jc>// A property method.</jc>
796       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
797       *
798       *       <ja>@Override</ja>
799       *       <jk>public</jk> String toString() {
800       *          <jk>return</jk> <js>"bar"</js>;
801       *       }
802       *    }
803       *
804       *    <jc>// Create a serializer that ignores beans not implementing Serializable.</jc>
805       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
806       *       .<jsm>create</jsm>()
807       *       .beansRequireSerializable()
808       *       .build();
809       *
810       *    <jc>// Produces:  "bar"</jc>
811       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
812       * </p>
813       *
814       * <h5 class='section'>Notes:</h5><ul>
815       *    <li class='note'>The {@link Bean @Bean} annotation can be used on a bean class to override this setting.
816       *    <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a class to ignore it as a bean.
817       * </ul>
818       *
819       * <h5 class='section'>See Also:</h5><ul>
820       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#beansRequireSerializable()}
821       * </ul>
822       *
823       * @return This object.
824       */
825      @FluentSetter
826      public Builder beansRequireSerializable() {
827         return beansRequireSerializable(true);
828      }
829
830      /**
831       * Same as {@link #beansRequireSerializable()} but allows you to explicitly specify the value.
832       *
833       * @param value The value for this setting.
834       * @return This object.
835       */
836      @FluentSetter
837      public Builder beansRequireSerializable(boolean value) {
838         beansRequireSerializable = value;
839         return this;
840      }
841
842      /**
843       * Beans require setters for getters.
844       *
845       * <p>
846       * When enabled, ignore read-only properties (properties with getters but not setters).
847       *
848       * <h5 class='section'>Example:</h5>
849       * <p class='bjava'>
850       *    <jc>// A bean without a Serializable interface.</jc>
851       *    <jk>public class</jk> MyBean {
852       *
853       *       <jc>// A read/write property.</jc>
854       *       <jk>public</jk> String getFoo() { <jk>return</jk> <js>"foo"</js>; }
855       *       <jk>public void</jk> setFoo(String <jv>foo</jv>) { ... }
856       *
857       *       <jc>// A read-only property.</jc>
858       *       <jk>public</jk> String getBar() { <jk>return</jk> <js>"bar"</js>; }
859       *    }
860       *
861       *    <jc>// Create a serializer that ignores bean properties without setters.</jc>
862       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
863       *       .<jsm>create</jsm>()
864       *       .beansRequireSettersForGetters()
865       *       .build();
866       *
867       *    <jc>// Produces:  {"foo":"foo"}</jc>
868       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
869       * </p>
870       *
871       * <h5 class='section'>Notes:</h5><ul>
872       *    <li class='note'>The {@link Beanp @Beanp} annotation can be used on the getter to override this setting.
873       *    <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on getters to ignore them as bean properties.
874       * </ul>
875       *
876       * @return This object.
877       */
878      @FluentSetter
879      public Builder beansRequireSettersForGetters() {
880         return beansRequireSettersForGetters(true);
881      }
882
883      /**
884       * Same as {@link #beansRequireSettersForGetters()} but allows you to explicitly specify the value.
885       *
886       * @param value The value for this setting.
887       * @return This object.
888       */
889      @FluentSetter
890      public Builder beansRequireSettersForGetters(boolean value) {
891         beansRequireSettersForGetters = value;
892         return this;
893      }
894
895      /**
896       * Beans don't require at least one property.
897       *
898       * <p>
899       * When enabled, then a Java class doesn't need to contain at least 1 property to be considered a bean.
900       * Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method.
901       *
902       * <p>
903       * The {@link Bean @Bean} annotation can be used on a class to override this setting when <jk>true</jk>.
904       *
905       * <h5 class='section'>Example:</h5>
906       * <p class='bjava'>
907       *    <jc>// A bean with no properties.</jc>
908       *    <jk>public class</jk> MyBean {
909       *    }
910       *
911       *    <jc>// Create a serializer that serializes beans even if they have zero properties.</jc>
912       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
913       *       .<jsm>create</jsm>()
914       *       .disableBeansRequireSomeProperties()
915       *       .build();
916       *
917       *    <jc>// Produces:  {}</jc>
918       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
919       * </p>
920       *
921       * <h5 class='section'>Notes:</h5><ul>
922       *    <li class='note'>The {@link Bean @Bean} annotation can be used on the class to force it to be recognized as a bean class
923       *       even if it has no properties.
924       * </ul>
925       *
926       * <h5 class='section'>See Also:</h5><ul>
927       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableBeansRequireSomeProperties()}
928       * </ul>
929       *
930       * @return This object.
931       */
932      @FluentSetter
933      public Builder disableBeansRequireSomeProperties() {
934         return disableBeansRequireSomeProperties(true);
935      }
936
937      /**
938       * Same as {@link #disableBeansRequireSomeProperties()} but allows you to explicitly specify the value.
939       *
940       * @param value The value for this setting.
941       * @return This object.
942       */
943      @FluentSetter
944      public Builder disableBeansRequireSomeProperties(boolean value) {
945         disableBeansRequireSomeProperties = value;
946         return this;
947      }
948
949      /**
950       * Bean property includes.
951       *
952       * <p>
953       * Specifies the set and order of names of properties associated with the bean class.
954       *
955       * <p>
956       * For example, <c>beanProperties(MyBean.<jk>class</jk>, <js>"foo,bar"</js>)</c> means only serialize the <c>foo</c> and
957       * <c>bar</c> properties on the specified bean.  Likewise, parsing will ignore any bean properties not specified
958       * and either throw an exception or silently ignore them depending on whether {@link #ignoreUnknownBeanProperties()}
959       * has been called.
960       *
961       * <p>
962       * This value is entirely optional if you simply want to expose all the getters and public fields on
963       * a class as bean properties.  However, it's useful if you want certain getters to be ignored or you want the properties to be
964       * serialized in a particular order.  Note that on IBM JREs, the property order is the same as the order in the source code,
965       * whereas on Oracle JREs, the order is entirely random.
966       *
967       * <p>
968       * Setting applies to specified class and all subclasses.
969       *
970       * <h5 class='section'>Example:</h5>
971       * <p class='bjava'>
972       *    <jc>// A bean with 3 properties.</jc>
973       *    <jk>public class</jk> MyBean {
974       *       <jk>public</jk> String
975       *          <jf>foo</jf> = <js>"foo"</js>,
976       *          <jf>bar</jf> = <js>"bar"</js>,
977       *          <jf>baz</jf> = <js>"baz"</js>;
978       *    }
979       *
980       *    <jc>// Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class.</jc>
981       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
982       *       .<jsm>create</jsm>()
983       *       .beanProperties(MyBean.<jk>class</jk>, <js>"foo,bar"</js>)
984       *       .build();
985       *
986       *    <jc>// Produces:  {"foo":"foo","bar":"bar"}</jc>
987       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
988       * </p>
989       *
990       * <p>
991       * This method is functionally equivalent to the following code:
992       * <p class='bjava'>
993       *    <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).properties(<jv>properties</jv>).build());
994       * </p>
995       *
996       * <h5 class='section'>See Also:</h5><ul>
997       *    <li class='jma'>{@link Bean#properties()}/{@link Bean#p()} - On an annotation on the bean class itself.
998       * </ul>
999       *
1000       * @param beanClass The bean class.
1001       * @param properties Comma-delimited list of property names.
1002       * @return This object.
1003       */
1004      @FluentSetter
1005      public Builder beanProperties(Class<?> beanClass, String properties) {
1006         return annotations(BeanAnnotation.create(beanClass).p(properties).build());
1007      }
1008
1009      /**
1010       * Bean property includes.
1011       *
1012       * <p>
1013       * Specifies the set and order of names of properties associated with bean classes.
1014       *
1015       * <p>
1016       * For example, <c>beanProperties(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"foo,bar"</js>))</c> means only serialize the <c>foo</c> and
1017       * <c>bar</c> properties on the specified bean.  Likewise, parsing will ignore any bean properties not specified
1018       * and either throw an exception or silently ignore them depending on whether {@link #ignoreUnknownBeanProperties()}
1019       * has been called.
1020       *
1021       * <p>
1022       * This value is entirely optional if you simply want to expose all the getters and public fields on
1023       * a class as bean properties.  However, it's useful if you want certain getters to be ignored or you want the properties to be
1024       * serialized in a particular order.  Note that on IBM JREs, the property order is the same as the order in the source code,
1025       * whereas on Oracle JREs, the order is entirely random.
1026       *
1027       * <p>
1028       * Setting applies to specified class and all subclasses.
1029       *
1030       * <h5 class='section'>Example:</h5>
1031       * <p class='bjava'>
1032       *    <jc>// A bean with 3 properties.</jc>
1033       *    <jk>public class</jk> MyBean {
1034       *       <jk>public</jk> String
1035       *          <jf>foo</jf> = <js>"foo"</js>,
1036       *          <jf>bar</jf> = <js>"bar"</js>,
1037       *          <jf>baz</jf> = <js>"baz"</js>;
1038       *    }
1039       *
1040       *    <jc>// Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class.</jc>
1041       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
1042       *       .<jsm>create</jsm>()
1043       *       .beanProperties(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"foo,bar"</js>))
1044       *       .build();
1045       *
1046       *    <jc>// Produces:  {"foo":"foo","bar":"bar"}</jc>
1047       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
1048       * </p>
1049       *
1050       * <p>
1051       * This method is functionally equivalent to the following code for each entry:
1052       * <p class='bjava'>
1053       *    <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).properties(<jv>value</jv>.toString()).build());
1054       * </p>
1055       *
1056       * <h5 class='section'>See Also:</h5><ul>
1057       *    <li class='jma'>{@link Bean#properties()} / {@link Bean#p()}- On an annotation on the bean class itself.
1058       * </ul>
1059       *
1060       * @param values
1061       *    The values to add to this builder.
1062       *    <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans.
1063       *    <br>Values are comma-delimited lists of property names.  Non-String objects are first converted to Strings.
1064       * @return This object.
1065       */
1066      @FluentSetter
1067      public Builder beanProperties(Map<String,Object> values) {
1068         values.forEach((k,v) -> annotations(BeanAnnotation.create(k).p(stringify(v)).build()));
1069         return this;
1070      }
1071
1072      /**
1073       * Bean property includes.
1074       *
1075       * <p>
1076       * Specifies the set and order of names of properties associated with the bean class.
1077       *
1078       * <p>
1079       * For example, <c>beanProperties(<js>"MyBean"</js>, <js>"foo,bar"</js>)</c> means only serialize the <c>foo</c> and
1080       * <c>bar</c> properties on the specified bean.  Likewise, parsing will ignore any bean properties not specified
1081       * and either throw an exception or silently ignore them depending on whether {@link #ignoreUnknownBeanProperties()}
1082       * has been called.
1083       *
1084       * <p>
1085       * This value is entirely optional if you simply want to expose all the getters and public fields on
1086       * a class as bean properties.  However, it's useful if you want certain getters to be ignored or you want the properties to be
1087       * serialized in a particular order.  Note that on IBM JREs, the property order is the same as the order in the source code,
1088       * whereas on Oracle JREs, the order is entirely random.
1089       *
1090       * <p>
1091       * Setting applies to specified class and all subclasses.
1092       *
1093       * <h5 class='section'>Example:</h5>
1094       * <p class='bjava'>
1095       *    <jc>// A bean with 3 properties.</jc>
1096       *    <jk>public class</jk> MyBean {
1097       *       <jk>public</jk> String
1098       *          <jf>foo</jf> = <js>"foo"</js>,
1099       *          <jf>bar</jf> = <js>"bar"</js>,
1100       *          <jf>baz</jf> = <js>"baz"</js>;
1101       *    }
1102       *
1103       *    <jc>// Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class.</jc>
1104       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
1105       *       .<jsm>create</jsm>()
1106       *       .beanProperties(<js>"MyBean"</js>, <js>"foo,bar"</js>)
1107       *       .build();
1108       *
1109       *    <jc>// Produces:  {"foo":"foo","bar":"bar"}</jc>
1110       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
1111       * </p>
1112       *
1113       * <p>
1114       * This method is functionally equivalent to the following code:
1115       * <p class='bjava'>
1116       *    <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).properties(<jv>properties</jv>).build());
1117       * </p>
1118       *
1119       * <h5 class='section'>See Also:</h5><ul>
1120       *    <li class='jma'>{@link Bean#properties()} / {@link Bean#p()} - On an annotation on the bean class itself.
1121       * </ul>
1122       *
1123       * @param beanClassName
1124       *    The bean class name.
1125       *    <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all beans.
1126       * @param properties Comma-delimited list of property names.
1127       * @return This object.
1128       */
1129      @FluentSetter
1130      public Builder beanProperties(String beanClassName, String properties) {
1131         return annotations(BeanAnnotation.create(beanClassName).p(properties).build());
1132      }
1133
1134      /**
1135       * Bean property excludes.
1136       *
1137       * <p>
1138       * Specifies to exclude the specified list of properties for the specified bean class.
1139       *
1140       * <p>
1141       * Same as {@link #beanProperties(Class, String)} except you specify a list of bean property names that you want to exclude from
1142       * serialization.
1143       *
1144       * <p>
1145       * Setting applies to specified class and all subclasses.
1146       *
1147       * <h5 class='section'>Example:</h5>
1148       * <p class='bjava'>
1149       *    <jc>// A bean with 3 properties.</jc>
1150       *    <jk>public class</jk> MyBean {
1151       *       <jk>public</jk> String
1152       *          <jf>foo</jf> = <js>"foo"</js>,
1153       *          <jf>bar</jf> = <js>"bar"</js>,
1154       *          <jf>baz</jf> = <js>"baz"</js>;
1155       *    }
1156       *
1157       *    <jc>// Create a serializer that excludes the "bar" and "baz" properties on the MyBean class.</jc>
1158       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
1159       *       .<jsm>create</jsm>()
1160       *       .beanPropertiesExcludes(MyBean.<jk>class</jk>, <js>"bar,baz"</js>)
1161       *       .build();
1162       *
1163       *    <jc>// Produces:  {"foo":"foo"}</jc>
1164       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
1165       * </p>
1166       *
1167       * <p>
1168       * This method is functionally equivalent to the following code:
1169       * <p class='bjava'>
1170       *    <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).excludeProperties(<jv>properties</jv>).build());
1171       * </p>
1172       *
1173       * <h5 class='section'>See Also:</h5><ul>
1174       *    <li class='jma'>{@link Bean#excludeProperties()} / {@link Bean#xp()}
1175       * </ul>
1176       *
1177       * @param beanClass The bean class.
1178       * @param properties Comma-delimited list of property names.
1179       * @return This object.
1180       */
1181      @FluentSetter
1182      public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) {
1183         return annotations(BeanAnnotation.create(beanClass).xp(properties).build());
1184      }
1185
1186      /**
1187       * Bean property excludes.
1188       *
1189       * <p>
1190       * Specifies to exclude the specified list of properties for the specified bean classes.
1191       *
1192       * <p>
1193       * Same as {@link #beanProperties(Map)} except you specify a list of bean property names that you want to exclude from
1194       * serialization.
1195       *
1196       * <p>
1197       * Setting applies to specified class and all subclasses.
1198       *
1199       * <h5 class='section'>Example:</h5>
1200       * <p class='bjava'>
1201       *    <jc>// A bean with 3 properties.</jc>
1202       *    <jk>public class</jk> MyBean {
1203       *       <jk>public</jk> String
1204       *          <jf>foo</jf> = <js>"foo"</js>,
1205       *          <jf>bar</jf> = <js>"bar"</js>,
1206       *          <jf>baz</jf> = <js>"baz"</js>;
1207       *    }
1208       *
1209       *    <jc>// Create a serializer that excludes the "bar" and "baz" properties on the MyBean class.</jc>
1210       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
1211       *       .<jsm>create</jsm>()
1212       *       .beanPropertiesExcludes(AMap.of(<js>"MyBean"</js>, <js>"bar,baz"</js>))
1213       *       .build();
1214       *
1215       *    <jc>// Produces:  {"foo":"foo"}</jc>
1216       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
1217       * </p>
1218       *
1219       * <p>
1220       * This method is functionally equivalent to the following code for each entry:
1221       * <p class='bjava'>
1222       *    <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).excludeProperties(<jv>value</jv>.toString()).build());
1223       * </p>
1224       *
1225       * <h5 class='section'>See Also:</h5><ul>
1226       *    <li class='jma'>{@link Bean#excludeProperties()} / {@link Bean#xp()}
1227       * </ul>
1228       *
1229       * @param values
1230       *    The values to add to this builder.
1231       *    <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans.
1232       *    <br>Values are comma-delimited lists of property names.  Non-String objects are first converted to Strings.
1233       * @return This object.
1234       */
1235      @FluentSetter
1236      public Builder beanPropertiesExcludes(Map<String,Object> values) {
1237         values.forEach((k,v) -> annotations(BeanAnnotation.create(k).xp(stringify(v)).build()));
1238         return this;
1239      }
1240
1241      /**
1242       * Bean property excludes.
1243       *
1244       * <p>
1245       * Specifies to exclude the specified list of properties for the specified bean class.
1246       *
1247       * <p>
1248       * Same as {@link #beanPropertiesExcludes(String, String)} except you specify a list of bean property names that you want to exclude from
1249       * serialization.
1250       *
1251       * <p>
1252       * Setting applies to specified class and all subclasses.
1253       *
1254       * <h5 class='section'>Example:</h5>
1255       * <p class='bjava'>
1256       *    <jc>// A bean with 3 properties.</jc>
1257       *    <jk>public class</jk> MyBean {
1258       *       <jk>public</jk> String
1259       *          <jf>foo</jf> = <js>"foo"</js>,
1260       *          <jf>bar</jf> = <js>"bar"</js>,
1261       *          <jf>baz</jf> = <js>"baz"</js>;
1262       *    }
1263       *
1264       *    <jc>// Create a serializer that excludes the "bar" and "baz" properties on the MyBean class.</jc>
1265       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
1266       *       .<jsm>create</jsm>()
1267       *       .beanPropertiesExcludes(<js>"MyBean"</js>, <js>"bar,baz"</js>)
1268       *       .build();
1269       *
1270       *    <jc>// Produces:  {"foo":"foo"}</jc>
1271       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
1272       * </p>
1273       *
1274       * <p>
1275       * This method is functionally equivalent to the following code:
1276       * <p class='bjava'>
1277       *    <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).excludeProperties(<jv>properties</jv>).build());
1278       * </p>
1279       *
1280       * <h5 class='section'>See Also:</h5><ul>
1281       *    <li class='jma'>{@link Bean#excludeProperties()} / {@link Bean#xp()}
1282       * </ul>
1283       *
1284       * @param beanClassName
1285       *    The bean class name.
1286       *    <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all bean classes.
1287       * @param properties Comma-delimited list of property names.
1288       * @return This object.
1289       */
1290      @FluentSetter
1291      public Builder beanPropertiesExcludes(String beanClassName, String properties) {
1292         return annotations(BeanAnnotation.create(beanClassName).xp(properties).build());
1293      }
1294
1295      /**
1296       * Read-only bean properties.
1297       *
1298       * <p>
1299       * Specifies one or more properties on a bean that are read-only despite having valid getters.
1300       * Serializers will serialize such properties as usual, but parsers will silently ignore them.
1301       * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties
1302       * for both serializers and parsers.
1303       *
1304       * <h5 class='section'>Example:</h5>
1305       * <p class='bjava'>
1306       *    <jc>// A bean with 3 properties.</jc>
1307       *    <jk>public class</jk> MyBean {
1308       *       <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>;
1309       *    }
1310       *
1311       *    <jc>// Create a serializer with read-only property settings.</jc>
1312       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
1313       *       .<jsm>create</jsm>()
1314       *       .beanPropertiesReadOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>)
1315       *       .build();
1316       *
1317       *    <jc>// All 3 properties will be serialized.</jc>
1318       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
1319       *
1320       *    <jc>// Create a parser with read-only property settings.</jc>
1321       *    ReaderParser <jv>parser</jv> = JsonParser
1322       *       .<jsm>create</jsm>()
1323       *       .beanPropertiesReadOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>)
1324       *       .ignoreUnknownBeanProperties()
1325       *       .build();
1326       *
1327       *    <jc>// Parser ignores bar and baz properties.</jc>
1328       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>);
1329       * </p>
1330       *
1331       * <p>
1332       * This method is functionally equivalent to the following code:
1333       * <p class='bjava'>
1334       *    <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).readOnlyProperties(<jv>properties</jv>).build());
1335       * </p>
1336       *
1337       * <h5 class='section'>See Also:</h5><ul>
1338       *    <li class='jma'>{@link Bean#readOnlyProperties()} / {@link Bean#ro()}
1339       * </ul>
1340       *
1341       * @param beanClass The bean class.
1342       * @param properties Comma-delimited list of property names.
1343       * @return This object.
1344       */
1345      @FluentSetter
1346      public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) {
1347         return annotations(BeanAnnotation.create(beanClass).ro(properties).build());
1348      }
1349
1350      /**
1351       * Read-only bean properties.
1352       *
1353       * <p>
1354       * Specifies one or more properties on beans that are read-only despite having valid getters.
1355       * Serializers will serialize such properties as usual, but parsers will silently ignore them.
1356       * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties
1357       * for both serializers and parsers.
1358       *
1359       * <h5 class='section'>Example:</h5>
1360       * <p class='bjava'>
1361       *    <jc>// A bean with 3 properties.</jc>
1362       *    <jk>public class</jk> MyBean {
1363       *       <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>;
1364       *    }
1365       *
1366       *    <jc>// Create a serializer with read-only property settings.</jc>
1367       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
1368       *       .<jsm>create</jsm>()
1369       *       .beanPropertiesReadOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>))
1370       *       .build();
1371       *
1372       *    <jc>// All 3 properties will be serialized.</jc>
1373       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
1374       *
1375       *    <jc>// Create a parser with read-only property settings.</jc>
1376       *    ReaderParser <jv>parser</jv> = JsonParser
1377       *       .<jsm>create</jsm>()
1378       *       .beanPropertiesReadOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>))
1379       *       .ignoreUnknownBeanProperties()
1380       *       .build();
1381       *
1382       *    <jc>// Parser ignores bar and baz properties.</jc>
1383       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>);
1384       * </p>
1385       *
1386       * <p>
1387       * This method is functionally equivalent to the following code for each entry:
1388       * <p class='bjava'>
1389       *    <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).readOnlyProperties(<jv>value</jv>.toString()).build());
1390       * </p>
1391       *
1392       * <h5 class='section'>See Also:</h5><ul>
1393       *    <li class='jma'>{@link Bean#readOnlyProperties()} / {@link Bean#ro()}
1394       * </ul>
1395       *
1396       * @param values
1397       *    The values to add to this builder.
1398       *    <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans.
1399       *    <br>Values are comma-delimited lists of property names.  Non-String objects are first converted to Strings.
1400       * @return This object.
1401       */
1402      @FluentSetter
1403      public Builder beanPropertiesReadOnly(Map<String,Object> values) {
1404         values.forEach((k,v) -> annotations(BeanAnnotation.create(k).ro(stringify(v)).build()));
1405         return this;
1406      }
1407
1408      /**
1409       * Read-only bean properties.
1410       *
1411       * <p>
1412       * Specifies one or more properties on a bean that are read-only despite having valid getters.
1413       * Serializers will serialize such properties as usual, but parsers will silently ignore them.
1414       * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties
1415       * for both serializers and parsers.
1416       *
1417       * <h5 class='section'>Example:</h5>
1418       * <p class='bjava'>
1419       *    <jc>// A bean with 3 properties.</jc>
1420       *    <jk>public class</jk> MyBean {
1421       *       <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>;
1422       *    }
1423       *
1424       *    <jc>// Create a serializer with read-only property settings.</jc>
1425       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
1426       *       .<jsm>create</jsm>()
1427       *       .beanPropertiesReadOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>)
1428       *       .build();
1429       *
1430       *    <jc>// All 3 properties will be serialized.</jc>
1431       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
1432       *
1433       *    <jc>// Create a parser with read-only property settings.</jc>
1434       *    ReaderParser <jv>parser</jv> = JsonParser
1435       *       .<jsm>create</jsm>()
1436       *       .beanPropertiesReadOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>)
1437       *       .ignoreUnknownBeanProperties()
1438       *       .build();
1439       *
1440       *    <jc>// Parser ignores bar and baz properties.</jc>
1441       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>);
1442       * </p>
1443       *
1444       * <p>
1445       * This method is functionally equivalent to the following code:
1446       * <p class='bjava'>
1447       *    <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).readOnlyProperties(<jv>properties</jv>).build());
1448       * </p>
1449       *
1450       * <h5 class='section'>See Also:</h5><ul>
1451       *    <li class='jma'>{@link Bean#readOnlyProperties()} / {@link Bean#ro()}
1452       * </ul>
1453       *
1454       * @param beanClassName
1455       *    The bean class name.
1456       *    <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all bean classes.
1457       * @param properties Comma-delimited list of property names.
1458       * @return This object.
1459       */
1460      @FluentSetter
1461      public Builder beanPropertiesReadOnly(String beanClassName, String properties) {
1462         return annotations(BeanAnnotation.create(beanClassName).ro(properties).build());
1463      }
1464
1465      /**
1466       * Write-only bean properties.
1467       *
1468       * <p>
1469       * Specifies one or more properties on a bean that are write-only despite having valid setters.
1470       * Parsers will parse such properties as usual, but serializers will silently ignore them.
1471       * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties
1472       * for both serializers and parsers.
1473       *
1474       * <h5 class='section'>Example:</h5>
1475       * <p class='bjava'>
1476       *    <jc>// A bean with 3 properties.</jc>
1477       *    <jk>public class</jk> MyBean {
1478       *       <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>;
1479       *    }
1480       *
1481       *    <jc>// Create a serializer with write-only property settings.</jc>
1482       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
1483       *       .<jsm>create</jsm>()
1484       *       .beanPropertiesWriteOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>)
1485       *       .build();
1486       *
1487       *    <jc>// Only foo will be serialized.</jc>
1488       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
1489       *
1490       *    <jc>// Create a parser with write-only property settings.</jc>
1491       *    ReaderParser <jv>parser</jv> = JsonParser
1492       *       .<jsm>create</jsm>()
1493       *       .beanPropertiesWriteOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>)
1494       *       .build();
1495       *
1496       *    <jc>// Parser parses all 3 properties.</jc>
1497       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>);
1498       * </p>
1499       *
1500       * <p>
1501       * This method is functionally equivalent to the following code:
1502       * <p class='bjava'>
1503       *    <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).writeOnlyProperties(<jv>properties</jv>).build());
1504       * </p>
1505       *
1506       * <h5 class='section'>See Also:</h5><ul>
1507       *    <li class='jma'>{@link Bean#writeOnlyProperties()} / {@link Bean#wo()}
1508       * </ul>
1509       *
1510       * @param beanClass The bean class.
1511       * @param properties Comma-delimited list of property names.
1512       * @return This object.
1513       */
1514      @FluentSetter
1515      public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) {
1516         return annotations(BeanAnnotation.create(beanClass).wo(properties).build());
1517      }
1518
1519      /**
1520       * Write-only bean properties.
1521       *
1522       * <p>
1523       * Specifies one or more properties on a bean that are write-only despite having valid setters.
1524       * Parsers will parse such properties as usual, but serializers will silently ignore them.
1525       * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties
1526       * for both serializers and parsers.
1527       *
1528       * <h5 class='section'>Example:</h5>
1529       * <p class='bjava'>
1530       *    <jc>// A bean with 3 properties.</jc>
1531       *    <jk>public class</jk> MyBean {
1532       *       <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>;
1533       *    }
1534       *
1535       *    <jc>// Create a serializer with write-only property settings.</jc>
1536       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
1537       *       .<jsm>create</jsm>()
1538       *       .beanPropertiesWriteOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>))
1539       *       .build();
1540       *
1541       *    <jc>// Only foo will be serialized.</jc>
1542       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
1543       *
1544       *    <jc>// Create a parser with write-only property settings.</jc>
1545       *    ReaderParser <jv>parser</jv> = JsonParser
1546       *       .<jsm>create</jsm>()
1547       *       .beanPropertiesWriteOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>))
1548       *       .build();
1549       *
1550       *    <jc>// Parser parses all 3 properties.</jc>
1551       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>);
1552       * </p>
1553       *
1554       * <p>
1555       * This method is functionally equivalent to the following code for each entry:
1556       * <p class='bjava'>
1557       *    <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).writeOnlyProperties(<jv>value</jv>.toString()).build());
1558       * </p>
1559       *
1560       * <h5 class='section'>See Also:</h5><ul>
1561       *    <li class='jma'>{@link Bean#writeOnlyProperties()} / {@link Bean#wo()}
1562       * </ul>
1563       *
1564       * @param values
1565       *    The values to add to this builder.
1566       *    <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans.
1567       *    <br>Values are comma-delimited lists of property names.  Non-String objects are first converted to Strings.
1568       * @return This object.
1569       */
1570      @FluentSetter
1571      public Builder beanPropertiesWriteOnly(Map<String,Object> values) {
1572         values.forEach((k,v) -> annotations(BeanAnnotation.create(k).wo(stringify(v)).build()));
1573         return this;
1574      }
1575
1576      /**
1577       * Write-only bean properties.
1578       *
1579       * <p>
1580       * Specifies one or more properties on a bean that are write-only despite having valid setters.
1581       * Parsers will parse such properties as usual, but serializers will silently ignore them.
1582       * Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties
1583       * for both serializers and parsers.
1584       *
1585       * <h5 class='section'>Example:</h5>
1586       * <p class='bjava'>
1587       *    <jc>// A bean with 3 properties.</jc>
1588       *    <jk>public class</jk> MyBean {
1589       *       <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>;
1590       *    }
1591       *
1592       *    <jc>// Create a serializer with write-only property settings.</jc>
1593       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
1594       *       .<jsm>create</jsm>()
1595       *       .beanPropertiesWriteOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>)
1596       *       .build();
1597       *
1598       *    <jc>// Only foo will be serialized.</jc>
1599       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
1600       *
1601       *    <jc>// Create a parser with write-only property settings.</jc>
1602       *    ReaderParser <jv>parser</jv> = JsonParser
1603       *       .<jsm>create</jsm>()
1604       *       .beanPropertiesWriteOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>)
1605       *       .build();
1606       *
1607       *    <jc>// Parser parses all 3 properties.</jc>
1608       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>);
1609       * </p>
1610       *
1611       * <p>
1612       * This method is functionally equivalent to the following code:
1613       * <p class='bjava'>
1614       *    <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).writeOnlyProperties(<jv>properties</jv>).build());
1615       * </p>
1616       *
1617       * <h5 class='section'>See Also:</h5><ul>
1618       *    <li class='jma'>{@link Bean#writeOnlyProperties()} / {@link Bean#wo()}
1619       * </ul>
1620       *
1621       * @param beanClassName
1622       *    The bean class name.
1623       *    <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all bean classes.
1624       * @param properties Comma-delimited list of property names.
1625       * @return This object.
1626       */
1627      @FluentSetter
1628      public Builder beanPropertiesWriteOnly(String beanClassName, String properties) {
1629         return annotations(BeanAnnotation.create(beanClassName).wo(properties).build());
1630      }
1631
1632      /**
1633       * Bean dictionary.
1634       *
1635       * <p>
1636       * The list of classes that make up the bean dictionary in this bean context.
1637       *
1638       * <p>
1639       * Values are prepended to the list so that later calls can override classes of earlier calls.
1640       *
1641       * <p>
1642       * A dictionary is a name/class mapping used to find class types during parsing when they cannot be inferred
1643       * through reflection.  The names are defined through the {@link Bean#typeName() @Bean(typeName)} annotation defined
1644       * on the bean class.  For example, if a class <c>Foo</c> has a type-name of <js>"myfoo"</js>, then it would end up
1645       * serialized as <js>"{_type:'myfoo',...}"</js> in JSON
1646       * or <js>"&lt;myfoo&gt;...&lt;/myfoo&gt;"</js> in XML.
1647       *
1648       * <p>
1649       * This setting tells the parsers which classes to look for when resolving <js>"_type"</js> attributes.
1650       *
1651       * <p>
1652       * Values can consist of any of the following types:
1653       * <ul>
1654       *    <li>Any bean class that specifies a value for {@link Bean#typeName() @Bean(typeName)}.
1655       *    <li>Any subclass of {@link BeanDictionaryList} containing a collection of bean classes with type name annotations.
1656       *    <li>Any subclass of {@link BeanDictionaryMap} containing a mapping of type names to classes without type name annotations.
1657       *    <li>Any array or collection of the objects above.
1658       * </ul>
1659       *
1660       * <h5 class='section'>Example:</h5>
1661       * <p class='bjava'>
1662       *    <jc>// POJOs with @Bean(name) annotations.</jc>
1663       *    <ja>@Bean</ja>(typeName=<js>"foo"</js>)
1664       *    <jk>public class</jk> Foo {...}
1665       *    <ja>@Bean</ja>(typeName=<js>"bar"</js>)
1666       *    <jk>public class</jk> Bar {...}
1667       *
1668       *    <jc>// Create a parser and tell it which classes to try to resolve.</jc>
1669       *    ReaderParser <jv>parser</jv> = JsonParser
1670       *       .<jsm>create</jsm>()
1671       *       .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>)
1672       *       .addBeanTypes()
1673       *       .build();
1674       *
1675       *    <jc>// A bean with a field with an indeterminate type.</jc>
1676       *    <jk>public class</jk> MyBean {
1677       *       <jk>public</jk> Object <jf>mySimpleField</jf>;
1678       *    }
1679       *
1680       *    <jc>// Parse bean.</jc>
1681       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{mySimpleField:{_type:'foo',...}}"</js>, MyBean.<jk>class</jk>);
1682       * </p>
1683       *
1684       * <p>
1685       * Another option is to use the {@link Bean#dictionary()} annotation on the POJO class itself:
1686       *
1687       * <p class='bjava'>
1688       *    <jc>// Instead of by parser, define a bean dictionary on a class through an annotation.</jc>
1689       *    <jc>// This applies to all properties on this class and all subclasses.</jc>
1690       *    <ja>@Bean</ja>(dictionary={Foo.<jk>class</jk>,Bar.<jk>class</jk>})
1691       *    <jk>public class</jk> MyBean {
1692       *       <jk>public</jk> Object <jf>mySimpleField</jf>;  <jc>// May contain Foo or Bar object.</jc>
1693       *       <jk>public</jk> Map&lt;String,Object&gt; <jf>myMapField</jf>;  <jc>// May contain Foo or Bar objects.</jc>
1694       *    }
1695       * </p>
1696       *
1697       * <p>
1698       *    A typical usage is to allow for HTML documents to be parsed back into HTML beans:
1699       * <p class='bjava'>
1700       *    <jc>// Use the predefined HTML5 bean dictionary which is a BeanDictionaryList.</jc>
1701       *    ReaderParser <jv>parser</jv> = HtmlParser
1702       *       .<jsm>create</jsm>()
1703       *       .dictionary(HtmlBeanDictionary.<jk>class</jk>)
1704       *       .build();
1705       *
1706       *    <jc>// Parse an HTML body into HTML beans.</jc>
1707       *    Body <jv>body</jv> = <jv>parser</jv>.parse(<js>"&lt;body&gt;&lt;ul&gt;&lt;li&gt;foo&lt;/li&gt;&lt;li&gt;bar&lt;/li&gt;&lt;/ul&gt;"</js>, Body.<jk>class</jk>);
1708       * </p>
1709       *
1710       * <h5 class='section'>See Also:</h5><ul>
1711       *    <li class='ja'>{@link org.apache.juneau.annotation.Bean#dictionary()}
1712       *    <li class='ja'>{@link org.apache.juneau.annotation.Beanp#dictionary()}
1713       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#dictionary()}
1714       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#dictionary_replace()}
1715       *    <li class='jm'>{@link org.apache.juneau.BeanContext.Builder#beanDictionary(Class...)}
1716       * </ul>
1717       *
1718       * @param values
1719       *    The values to add to this setting.
1720       * @return This object.
1721       */
1722      @FluentSetter
1723      public Builder beanDictionary(Class<?>...values) {
1724         return beanDictionary(alist(values));
1725      }
1726
1727      /**
1728       * Same as {@link #beanDictionary(Class...)} but allows you to pass in a collection of classes.
1729       *
1730       * @param values
1731       *    The values to add to this setting.
1732       * @return This object.
1733       * @see #beanDictionary(Class...)
1734       */
1735      @FluentSetter
1736      public Builder beanDictionary(Collection<Class<?>> values) {
1737         beanDictionary().addAll(0, values);
1738         return this;
1739      }
1740
1741      /**
1742       * Returns the bean dictionary list.
1743       *
1744       * <p>
1745       * Gives access to the inner list if you need to make more than simple additions via {@link #beanDictionary(Class...)}.
1746       *
1747       * @return The bean dictionary list.
1748       * @see #beanDictionary(Class...)
1749       */
1750      public List<Class<?>> beanDictionary() {
1751         if (beanDictionary == null)
1752            beanDictionary = list();
1753         return beanDictionary;
1754      }
1755
1756      /**
1757       * Bean dictionary.
1758       *
1759       * <p>
1760       * This is identical to {@link #beanDictionary(Class...)}, but specifies a dictionary within the context of
1761       * a single class as opposed to globally.
1762       *
1763       * <h5 class='section'>Example:</h5>
1764       * <p class='bjava'>
1765       *    <jc>// POJOs with @Bean(name) annotations.</jc>
1766       *    <ja>@Bean</ja>(typeName=<js>"foo"</js>)
1767       *    <jk>public class</jk> Foo {...}
1768       *    <ja>@Bean</ja>(typeName=<js>"bar"</js>)
1769       *    <jk>public class</jk> Bar {...}
1770       *
1771       *    <jc>// A bean with a field with an indeterminate type.</jc>
1772       *    <jk>public class</jk> MyBean {
1773       *       <jk>public</jk> Object <jf>mySimpleField</jf>;
1774       *    }
1775       *
1776       *    <jc>// Create a parser and tell it which classes to try to resolve.</jc>
1777       *    ReaderParser <jv>parser</jv> = JsonParser
1778       *       .<jsm>create</jsm>()
1779       *       .dictionaryOn(MyBean.<jk>class</jk>, Foo.<jk>class</jk>, Bar.<jk>class</jk>)
1780       *       .build();
1781       *
1782       *    <jc>// Parse bean.</jc>
1783       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{mySimpleField:{_type:'foo',...}}"</js>, MyBean.<jk>class</jk>);
1784       * </p>
1785       *
1786       * <p>
1787       * This is functionally equivalent to the {@link Bean#dictionary()} annotation.
1788       *
1789       * <h5 class='section'>See Also:</h5><ul>
1790       *    <li class='jma'>{@link Bean#dictionary()}
1791       *    <li class='jm'>{@link #beanDictionary(Class...)}
1792       * </ul>
1793       *
1794       * @param on The class that the dictionary values apply to.
1795       * @param values
1796       *    The new values for this setting.
1797       * @return This object.
1798       */
1799      @FluentSetter
1800      public Builder dictionaryOn(Class<?> on, Class<?>...values) {
1801         return annotations(BeanAnnotation.create(on).dictionary(values).build());
1802      }
1803
1804      /**
1805       * POJO example.
1806       *
1807       * <p>
1808       * Specifies an example of the specified class.
1809       *
1810       * <p>
1811       * Examples are used in cases such as POJO examples in Swagger documents.
1812       *
1813       * <h5 class='section'>Example:</h5>
1814       * <p class='bjava'>
1815       *    <jc>// Create a serializer that excludes the 'foo' and 'bar' properties on the MyBean class.</jc>
1816       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
1817       *       .<jsm>create</jsm>()
1818       *       .example(MyBean.<jk>class</jk>, <jk>new</jk> MyBean().setFoo(<js>"foo"</js>).setBar(123))
1819       *       .build();
1820       * </p>
1821       *
1822       * <p>
1823       * This is a shorthand method for the following code:
1824       * <p class='bjava'>
1825       *       <jv>builder</jv>.annotations(MarshalledAnnotation.<jsm>create</jsm>(<jv>pojoClass</jv>).example(Json5.<jsf>DEFAULT</jsf>.toString(<jv>object</jv>)).build())
1826       * </p>
1827       *
1828       * <h5 class='section'>Notes:</h5><ul>
1829       *    <li class='note'>Using this method assumes the serialized form of the object is the same as that produced
1830       *       by the default serializer.  This may not be true based on settings or swaps on the constructed serializer.
1831       * </ul>
1832       *
1833       * <p>
1834       * POJO examples can also be defined on classes via the following:
1835       * <ul class='spaced-list'>
1836       *    <li>The {@link Marshalled#example()} annotation on the class itself.
1837       *    <li>A static field annotated with {@link Example @Example}.
1838       *    <li>A static method annotated with {@link Example @Example} with zero arguments or one {@link BeanSession} argument.
1839       *    <li>A static method with name <c>example</c> with no arguments or one {@link BeanSession} argument.
1840       * </ul>
1841       *
1842       * @param <T> The POJO class.
1843       * @param pojoClass The POJO class.
1844       * @param o
1845       *    An instance of the POJO class used for examples.
1846       * @return This object.
1847       */
1848      @FluentSetter
1849      public <T> Builder example(Class<T> pojoClass, T o) {
1850         return annotations(MarshalledAnnotation.create(pojoClass).example(Json5.of(o)).build());
1851      }
1852
1853      /**
1854       * POJO example.
1855       *
1856       * <p>
1857       * Specifies an example in JSON of the specified class.
1858       *
1859       * <p>
1860       * Examples are used in cases such as POJO examples in Swagger documents.
1861       *
1862       * <p>
1863       * Setting applies to specified class and all subclasses.
1864       *
1865       * <h5 class='section'>Example:</h5>
1866       * <p class='bjava'>
1867       *    <jc>// Create a serializer that excludes the 'foo' and 'bar' properties on the MyBean class.</jc>
1868       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
1869       *       .<jsm>create</jsm>()
1870       *       .example(MyBean.<jk>class</jk>, <js>"{foo:'bar'}"</js>)
1871       *       .build();
1872       * </p>
1873       *
1874       * <p>
1875       * This is a shorthand method for the following code:
1876       * <p class='bjava'>
1877       *    <jv>builder</jv>.annotations(MarshalledAnnotation.<jsm>create</jsm>(<jv>pojoClass</jv>).example(<jv>json</jv>).build())
1878       * </p>
1879       *
1880       * <p>
1881       * POJO examples can also be defined on classes via the following:
1882       * <ul class='spaced-list'>
1883       *    <li>A static field annotated with {@link Example @Example}.
1884       *    <li>A static method annotated with {@link Example @Example} with zero arguments or one {@link BeanSession} argument.
1885       *    <li>A static method with name <c>example</c> with no arguments or one {@link BeanSession} argument.
1886       * </ul>
1887       *
1888       * <h5 class='section'>See Also:</h5><ul>
1889       *    <li class='ja'>{@link Marshalled#example()}
1890       * </ul>
1891       *
1892       * @param <T> The POJO class type.
1893       * @param pojoClass The POJO class.
1894       * @param json The JSON 5 representation of the example.
1895       * @return This object.
1896       */
1897      @FluentSetter
1898      public <T> Builder example(Class<T> pojoClass, String json) {
1899         return annotations(MarshalledAnnotation.create(pojoClass).example(json).build());
1900      }
1901
1902      /**
1903       * Find fluent setters.
1904       *
1905       * <p>
1906       * When enabled, fluent setters are detected on beans during parsing.
1907       *
1908       * <p>
1909       * Fluent setters must have the following attributes:
1910       * <ul>
1911       *    <li>Public.
1912       *    <li>Not static.
1913       *    <li>Take in one parameter.
1914       *    <li>Return the bean itself.
1915       * </ul>
1916       *
1917       * <h5 class='section'>Example:</h5>
1918       * <p class='bjava'>
1919       *    <jc>// A bean with a fluent setter.</jc>
1920       *    <jk>public class</jk> MyBean {
1921       *       <jk>public</jk> MyBean foo(String <jv>value</jv>) {...}
1922       *    }
1923       *
1924       *    <jc>// Create a parser that finds fluent setters.</jc>
1925       *    ReaderParser <jv>parser</jv> = JsonParser
1926       *       .<jsm>create</jsm>()
1927       *       .findFluentSetters()
1928       *       .build();
1929       *
1930       *    <jc>// Parse into bean using fluent setter.</jc>
1931       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>);
1932       * </p>
1933       *
1934       * <h5 class='section'>Notes:</h5><ul>
1935       *    <li class='note'>The {@link Beanp @Beanp} annotation can also be used on methods to individually identify them as fluent setters.
1936       *    <li class='note'>The {@link Bean#findFluentSetters() @Bean.fluentSetters()} annotation can also be used on classes to specify to look for fluent setters.
1937       * </ul>
1938       *
1939       * <h5 class='section'>See Also:</h5><ul>
1940       *    <li class='ja'>{@link org.apache.juneau.annotation.Bean#findFluentSetters()}
1941       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#findFluentSetters()}
1942       * </ul>
1943       *
1944       * @return This object.
1945       */
1946      @FluentSetter
1947      public Builder findFluentSetters() {
1948         return findFluentSetters(true);
1949      }
1950
1951      /**
1952       * Same as {@link #findFluentSetters()} but allows you to explicitly specify the value.
1953       *
1954       * @param value The value for this setting.
1955       * @return This object.
1956       */
1957      @FluentSetter
1958      public Builder findFluentSetters(boolean value) {
1959         findFluentSetters = value;
1960         return this;
1961      }
1962
1963      /**
1964       * Find fluent setters.
1965       *
1966       * <p>
1967       * Identical to {@link #findFluentSetters()} but enables it on a specific class only.
1968       *
1969       * <h5 class='section'>Example:</h5>
1970       * <p class='bjava'>
1971       *    <jc>// A bean with a fluent setter.</jc>
1972       *    <jk>public class</jk> MyBean {
1973       *       <jk>public</jk> MyBean foo(String <jv>value</jv>) {...}
1974       *    }
1975       *
1976       *    <jc>// Create a parser that finds fluent setters.</jc>
1977       *    ReaderParser <jv>parser</jv> = JsonParser
1978       *       .<jsm>create</jsm>()
1979       *       .findFluentSetters(MyBean.<jk>class</jk>)
1980       *       .build();
1981       *
1982       *    <jc>// Parse into bean using fluent setter.</jc>
1983       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>);
1984       * </p>
1985       *
1986       * <h5 class='section'>Notes:</h5><ul>
1987       *    <li class='note'>This method is functionally equivalent to using the {@link Bean#findFluentSetters()} annotation.
1988       * </ul>
1989       *
1990       * <h5 class='section'>See Also:</h5><ul>
1991       *    <li class='ja'>{@link Bean#findFluentSetters()}
1992       *    <li class='jm'>{@link #findFluentSetters()}
1993       * </ul>
1994       *
1995       * @param on The class that this applies to.
1996       * @return This object.
1997       */
1998      @FluentSetter
1999      public Builder findFluentSetters(Class<?> on) {
2000         return annotations(BeanAnnotation.create(on).findFluentSetters(true).build());
2001      }
2002
2003      /**
2004       * Ignore invocation errors on getters.
2005       *
2006       * <p>
2007       * When enabled, errors thrown when calling bean getter methods will silently be ignored.
2008       * Otherwise, a {@code BeanRuntimeException} is thrown.
2009       *
2010       * <h5 class='section'>Example:</h5>
2011       * <p class='bjava'>
2012       *    <jc>// A bean with a property that throws an exception.</jc>
2013       *    <jk>public class</jk> MyBean {
2014       *       <jk>public</jk> String getFoo() {
2015       *          <jk>throw new</jk> RuntimeException(<js>"foo"</js>);
2016       *       }
2017       *    }
2018       *
2019       *    <jc>// Create a serializer that ignores bean getter exceptions.</jc>
2020       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
2021       *       .<jsm>create</jsm>()
2022       *       .ingoreInvocationExceptionsOnGetters()
2023       *       .build();
2024       *
2025       *    <jc>// Exception is ignored.</jc>
2026       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
2027       * </p>
2028       *
2029       * <h5 class='section'>See Also:</h5><ul>
2030       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#ignoreInvocationExceptionsOnGetters()}
2031       * </ul>
2032       *
2033       * @return This object.
2034       */
2035      @FluentSetter
2036      public Builder ignoreInvocationExceptionsOnGetters() {
2037         return ignoreInvocationExceptionsOnGetters(true);
2038      }
2039
2040      /**
2041       * Same as {@link #ignoreInvocationExceptionsOnGetters()} but allows you to explicitly specify the value.
2042       *
2043       * @param value The value for this setting.
2044       * @return This object.
2045       */
2046      @FluentSetter
2047      public Builder ignoreInvocationExceptionsOnGetters(boolean value) {
2048         ignoreInvocationExceptionsOnGetters = value;
2049         return this;
2050      }
2051
2052      /**
2053       * Ignore invocation errors on setters.
2054       *
2055       * <p>
2056       * When enabled, errors thrown when calling bean setter methods will silently be ignored.
2057       * Otherwise, a {@code BeanRuntimeException} is thrown.
2058       *
2059       * <h5 class='section'>Example:</h5>
2060       * <p class='bjava'>
2061       *    <jc>// A bean with a property that throws an exception.</jc>
2062       *    <jk>public class</jk> MyBean {
2063       *       <jk>public void</jk> setFoo(String <jv>foo</jv>) {
2064       *          <jk>throw new</jk> RuntimeException(<js>"foo"</js>);
2065       *       }
2066       *    }
2067       *
2068       *    <jc>// Create a parser that ignores bean setter exceptions.</jc>
2069       *    ReaderParser <jv>parser</jv> = JsonParser
2070       *       .<jsm>create</jsm>()
2071       *       .ignoreInvocationExceptionsOnSetters()
2072       *       .build();
2073       *
2074       *    <jc>// Exception is ignored.</jc>
2075       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>);
2076       * </p>
2077       *
2078       * <h5 class='section'>See Also:</h5><ul>
2079       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#ignoreInvocationExceptionsOnSetters()}
2080       * </ul>
2081       *
2082       * @return This object.
2083       */
2084      @FluentSetter
2085      public Builder ignoreInvocationExceptionsOnSetters() {
2086         return ignoreInvocationExceptionsOnSetters(true);
2087      }
2088
2089      /**
2090       * Same as {@link #ignoreInvocationExceptionsOnSetters()} but allows you to explicitly specify the value.
2091       *
2092       * @param value The value for this setting.
2093       * @return This object.
2094       */
2095      @FluentSetter
2096      public Builder ignoreInvocationExceptionsOnSetters(boolean value) {
2097         ignoreInvocationExceptionsOnSetters = value;
2098         return this;
2099      }
2100
2101      /**
2102       * Don't silently ignore missing setters.
2103       *
2104       * <p>
2105       * When enabled, trying to set a value on a bean property without a setter will throw a {@link BeanRuntimeException}.
2106       * Otherwise, it will be silently ignored.
2107       *
2108       * <h5 class='section'>Example:</h5>
2109       * <p class='bjava'>
2110       *    <jc>// A bean with a property with a getter but not a setter.</jc>
2111       *    <jk>public class</jk> MyBean {
2112       *       <jk>public void</jk> getFoo() {
2113       *          <jk>return</jk> <js>"foo"</js>;
2114       *       }
2115       *    }
2116       *
2117       *    <jc>// Create a parser that throws an exception if a setter is not found but a getter is.</jc>
2118       *    ReaderParser <jv>parser</jv> = JsonParser
2119       *       .<jsm>create</jsm>()
2120       *       .disableIgnoreMissingSetters()
2121       *       .build();
2122       *
2123       *    <jc>// Throws a ParseException.</jc>
2124       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>);
2125       * </p>
2126       *
2127       * <h5 class='section'>Notes:</h5><ul>
2128       *    <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on getters and fields to ignore them.
2129       * </ul>
2130       *
2131       * <h5 class='section'>See Also:</h5><ul>
2132       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableIgnoreMissingSetters()}
2133       * </ul>
2134       *
2135       * @return This object.
2136       */
2137      @FluentSetter
2138      public Builder disableIgnoreMissingSetters() {
2139         return disableIgnoreMissingSetters(true);
2140      }
2141
2142      /**
2143       * Same as {@link #disableIgnoreMissingSetters()} but allows you to explicitly specify the value.
2144       *
2145       * @param value The value for this setting.
2146       * @return This object.
2147       */
2148      @FluentSetter
2149      public Builder disableIgnoreMissingSetters(boolean value) {
2150         disableIgnoreMissingSetters = value;
2151         return this;
2152      }
2153
2154      /**
2155       * Don't ignore transient fields.
2156       *
2157       * <p>
2158       * When enabled, methods and fields marked as <jk>transient</jk> will not be ignored as bean properties.
2159       *
2160       * <h5 class='section'>Example:</h5>
2161       * <p class='bjava'>
2162       *    <jc>// A bean with a transient field.</jc>
2163       *    <jk>public class</jk> MyBean {
2164       *       <jk>public transient</jk> String <jf>foo</jf> = <js>"foo"</js>;
2165       *    }
2166       *
2167       *    <jc>// Create a serializer that doesn't ignore transient fields.</jc>
2168       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
2169       *       .<jsm>create</jsm>()
2170       *       .disableIgnoreTransientFields()
2171       *       .build();
2172       *
2173       *    <jc>// Produces:  {"foo":"foo"}</jc>
2174       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
2175       * </p>
2176       *
2177       * <h5 class='section'>Notes:</h5><ul>
2178       *    <li class='note'>The {@link Beanp @Beanp} annotation can also be used on transient fields to keep them from being ignored.
2179       * </ul>
2180       *
2181       * <h5 class='section'>See Also:</h5><ul>
2182       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableIgnoreTransientFields()}
2183       * </ul>
2184       *
2185       * @return This object.
2186       */
2187      @FluentSetter
2188      public Builder disableIgnoreTransientFields() {
2189         return disableIgnoreTransientFields(true);
2190      }
2191
2192      /**
2193       * Same as {@link #disableIgnoreTransientFields()} but allows you to explicitly specify the value.
2194       *
2195       * @param value The value for this setting.
2196       * @return This object.
2197       */
2198      @FluentSetter
2199      public Builder disableIgnoreTransientFields(boolean value) {
2200         disableIgnoreTransientFields = value;
2201         return this;
2202      }
2203
2204      /**
2205       * Ignore unknown properties.
2206       *
2207       * <p>
2208       * When enabled, trying to set a value on a non-existent bean property will silently be ignored.
2209       * Otherwise, a {@code BeanRuntimeException} is thrown.
2210       *
2211       * <h5 class='section'>Example:</h5>
2212       * <p class='bjava'>
2213       *    <jc>// A bean with a single property.</jc>
2214       *    <jk>public class</jk> MyBean {
2215       *       <jk>public</jk> String <jf>foo</jf>;
2216       *    }
2217       *
2218       *    <jc>// Create a parser that ignores missing bean properties.</jc>
2219       *    ReaderParser <jv>parser</jv> = JsonParser
2220       *       .<jsm>create</jsm>()
2221       *       .ignoreUnknownBeanProperties()
2222       *       .build();
2223       *
2224       *    <jc>// Doesn't throw an exception on unknown 'bar' property.</jc>
2225       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar'}"</js>, MyBean.<jk>class</jk>);
2226       * </p>
2227       *
2228       * <h5 class='section'>See Also:</h5><ul>
2229       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#ignoreUnknownBeanProperties()}
2230       * </ul>
2231       *
2232       * @return This object.
2233       */
2234      @FluentSetter
2235      public Builder ignoreUnknownBeanProperties() {
2236         return ignoreUnknownBeanProperties(true);
2237      }
2238
2239      /**
2240       * Same as {@link #ignoreUnknownBeanProperties()} but allows you to explicitly specify the value.
2241       *
2242       * @param value The value for this setting.
2243       * @return This object.
2244       */
2245      @FluentSetter
2246      public Builder ignoreUnknownBeanProperties(boolean value) {
2247         ignoreUnknownBeanProperties = value;
2248         return this;
2249      }
2250
2251      /**
2252       * Ignore unknown properties.
2253       *
2254       * <p>
2255       * When enabled, unknown enum values will be set to <jk>null</jk> instead of throwing an exception.
2256       *
2257       * <h5 class='section'>See Also:</h5><ul>
2258       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#ignoreUnknownEnumValues()}
2259       * </ul>
2260       *
2261       * @return This object.
2262       */
2263      @FluentSetter
2264      public Builder ignoreUnknownEnumValues() {
2265         return ignoreUnknownEnumValues(true);
2266      }
2267
2268      /**
2269       * Same as {@link #ignoreUnknownEnumValues()} but allows you to explicitly specify the value.
2270       *
2271       * @param value The value for this setting.
2272       * @return This object.
2273       */
2274      @FluentSetter
2275      public Builder ignoreUnknownEnumValues(boolean value) {
2276         ignoreUnknownEnumValues = value;
2277         return this;
2278      }
2279
2280      /**
2281       * Don't ignore unknown properties with null values.
2282       *
2283       * <p>
2284       * When enabled, trying to set a <jk>null</jk> value on a non-existent bean property will throw a {@link BeanRuntimeException}.
2285       * Otherwise it will be silently ignored.
2286       *
2287       * <h5 class='section'>Example:</h5>
2288       * <p class='bjava'>
2289       *    <jc>// A bean with a single property.</jc>
2290       *    <jk>public class</jk> MyBean {
2291       *       <jk>public</jk> String <jf>foo</jf>;
2292       *    }
2293       *
2294       *    <jc>// Create a parser that throws an exception on an unknown property even if the value being set is null.</jc>
2295       *    ReaderParser <jv>parser</jv> = JsonParser
2296       *       .<jsm>create</jsm>()
2297       *       .disableIgnoreUnknownNullBeanProperties()
2298       *       .build();
2299       *
2300       *    <jc>// Throws a BeanRuntimeException wrapped in a ParseException on the unknown 'bar' property.</jc>
2301       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:null}"</js>, MyBean.<jk>class</jk>);
2302       * </p>
2303       *
2304       * <h5 class='section'>See Also:</h5><ul>
2305       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableIgnoreUnknownNullBeanProperties()}
2306       * </ul>
2307       *
2308       * @return This object.
2309       */
2310      @FluentSetter
2311      public Builder disableIgnoreUnknownNullBeanProperties() {
2312         return disableIgnoreUnknownNullBeanProperties(true);
2313      }
2314
2315      /**
2316       * Same as {@link #disableIgnoreUnknownNullBeanProperties()} but allows you to explicitly specify the value.
2317       *
2318       * @param value The value for this setting.
2319       * @return This object.
2320       */
2321      @FluentSetter
2322      public Builder disableIgnoreUnknownNullBeanProperties(boolean value) {
2323         disableIgnoreUnknownNullBeanProperties = value;
2324         return this;
2325      }
2326
2327      /**
2328       * Implementation classes.
2329       *
2330       * <p>
2331       * For interfaces and abstract classes this method can be used to specify an implementation class for the
2332       * interface/abstract class so that instances of the implementation class are used when instantiated (e.g. during a
2333       * parse).
2334       *
2335       * <h5 class='section'>Example:</h5>
2336       * <p class='bjava'>
2337       *    <jc>// A bean interface.</jc>
2338       *    <jk>public interface</jk> MyBean {
2339       *       ...
2340       *    }
2341       *
2342       *    <jc>// A bean implementation.</jc>
2343       *    <jk>public class</jk> MyBeanImpl <jk>implements</jk> MyBean {
2344       *       ...
2345       *    }
2346
2347       *    <jc>// Create a parser that instantiates MyBeanImpls when parsing MyBeans.</jc>
2348       *    ReaderParser <jv>parser</jv> = JsonParser
2349       *       .<jsm>create</jsm>()
2350       *       .implClass(MyBean.<jk>class</jk>, MyBeanImpl.<jk>class</jk>)
2351       *       .build();
2352       *
2353       *    <jc>// Instantiates a MyBeanImpl,</jc>
2354       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"..."</js>, MyBean.<jk>class</jk>);
2355       * </p>
2356       *
2357       * @param interfaceClass The interface class.
2358       * @param implClass The implementation class.
2359       * @return This object.
2360       */
2361      @FluentSetter
2362      public Builder implClass(Class<?> interfaceClass, Class<?> implClass) {
2363         return annotations(MarshalledAnnotation.create(interfaceClass).implClass(implClass).build());
2364      }
2365
2366      /**
2367       * Implementation classes.
2368       *
2369       * <p>
2370       * For interfaces and abstract classes this method can be used to specify an implementation class for the
2371       * interface/abstract class so that instances of the implementation class are used when instantiated (e.g. during a
2372       * parse).
2373       *
2374       * <h5 class='section'>Example:</h5>
2375       * <p class='bjava'>
2376       *    <jc>// A bean with a single property.</jc>
2377       *    <jk>public interface</jk> MyBean {
2378       *       ...
2379       *    }
2380       *
2381       *    <jc>// A bean with a single property.</jc>
2382       *    <jk>public class</jk> MyBeanImpl <jk>implements</jk> MyBean {
2383       *       ...
2384       *    }
2385
2386       *    <jc>// Create a parser that instantiates MyBeanImpls when parsing MyBeans.</jc>
2387       *    ReaderParser <jv>parser</jv> = JsonParser
2388       *       .<jsm>create</jsm>()
2389       *       .implClasses(AMap.<jsm>of</jsm>(MyBean.<jk>class</jk>, MyBeanImpl.<jk>class</jk>))
2390       *       .build();
2391       *
2392       *    <jc>// Instantiates a MyBeanImpl,</jc>
2393       *    MyBean <jv>myBean</jv> = <jv>parser</jv>.parse(<js>"..."</js>, MyBean.<jk>class</jk>);
2394       * </p>
2395       *
2396       * @param values
2397       *    The new value for this setting.
2398       * @return This object.
2399       */
2400      @FluentSetter
2401      public Builder implClasses(Map<Class<?>,Class<?>> values) {
2402         values.forEach((k,v) -> annotations(MarshalledAnnotation.create(k).implClass(v).build()));
2403         return this;
2404      }
2405
2406      /**
2407       * Identifies a class to be used as the interface class for the specified class and all subclasses.
2408       *
2409       * <p>
2410       * When specified, only the list of properties defined on the interface class will be used during serialization.
2411       * Additional properties on subclasses will be ignored.
2412       *
2413       * <p class='bjava'>
2414       *    <jc>// Parent class or interface</jc>
2415       *    <jk>public abstract class</jk> A {
2416       *       <jk>public</jk> String <jf>foo</jf> = <js>"foo"</js>;
2417       *    }
2418       *
2419       *    <jc>// Sub class</jc>
2420       *    <jk>public class</jk> A1 <jk>extends</jk> A {
2421       *       <jk>public</jk> String <jf>bar</jf> = <js>"bar"</js>;
2422       *    }
2423       *
2424       *    <jc>// Create a serializer and define our interface class mapping.</jc>
2425       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
2426       *       .<jsm>create</jsm>()
2427       *       .interfaceClass(A1.<jk>class</jk>, A.<jk>class</jk>)
2428       *       .build();
2429       *
2430       *    <jc>// Produces "{"foo":"foo"}"</jc>
2431       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> A1());
2432       * </p>
2433       *
2434       * <p>
2435       * This annotation can be used on the parent class so that it filters to all child classes, or can be set
2436       * individually on the child classes.
2437       *
2438       * <h5 class='section'>Notes:</h5><ul>
2439       *    <li class='note'>The {@link Bean#interfaceClass() @Bean(interfaceClass)} annotation is the equivalent annotation-based solution.
2440       * </ul>
2441       *
2442       * @param on The class that the interface class applies to.
2443       * @param value
2444       *    The new value for this setting.
2445       * @return This object.
2446       */
2447      @FluentSetter
2448      public Builder interfaceClass(Class<?> on, Class<?> value) {
2449         return annotations(BeanAnnotation.create(on).interfaceClass(value).build());
2450      }
2451
2452      /**
2453       * Identifies a set of interfaces.
2454       *
2455       * <p>
2456       * When specified, only the list of properties defined on the interface class will be used during serialization
2457       * of implementation classes.  Additional properties on subclasses will be ignored.
2458       *
2459       * <p class='bjava'>
2460       *    <jc>// Parent class or interface</jc>
2461       *    <jk>public abstract class</jk> A {
2462       *       <jk>public</jk> String <jf>foo</jf> = <js>"foo"</js>;
2463       *    }
2464       *
2465       *    <jc>// Sub class</jc>
2466       *    <jk>public class</jk> A1 <jk>extends</jk> A {
2467       *       <jk>public</jk> String <jf>bar</jf> = <js>"bar"</js>;
2468       *    }
2469       *
2470       *    <jc>// Create a serializer and define our interface class mapping.</jc>
2471       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
2472       *       .<jsm>create</jsm>()
2473       *       .interfaces(A.<jk>class</jk>)
2474       *       .build();
2475       *
2476       *    <jc>// Produces "{"foo":"foo"}"</jc>
2477       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> A1());
2478       * </p>
2479       *
2480       * <p>
2481       * This annotation can be used on the parent class so that it filters to all child classes, or can be set
2482       * individually on the child classes.
2483       *
2484       * <h5 class='section'>Notes:</h5><ul>
2485       *    <li class='note'>The {@link Bean#interfaceClass() @Bean(interfaceClass)} annotation is the equivalent annotation-based solution.
2486       * </ul>
2487       *
2488       * @param value
2489       *    The new value for this setting.
2490       * @return This object.
2491       */
2492      @FluentSetter
2493      public Builder interfaces(Class<?>...value) {
2494         for (Class<?> v : value)
2495            annotations(BeanAnnotation.create(v).interfaceClass(v).build());
2496         return this;
2497      }
2498
2499      /**
2500       * <i><l>Context</l> configuration property:&emsp;</i>  Locale.
2501       *
2502       * <p>
2503       * Specifies the default locale for serializer and parser sessions when not specified via {@link BeanSession.Builder#locale(Locale)}.
2504       * Typically used for POJO swaps that need to deal with locales such as swaps that convert <l>Date</l> and <l>Calendar</l>
2505       * objects to strings by accessing it via the session passed into the {@link ObjectSwap#swap(BeanSession, Object)} and
2506       * {@link ObjectSwap#unswap(BeanSession, Object, ClassMeta, String)} methods.
2507       *
2508       * <h5 class='section'>Example:</h5>
2509       * <p class='bjava'>
2510       *    <jc>// Define a POJO swap that skips serializing beans if we're in the UK.</jc>
2511       *    <jk>public class</jk> MyBeanSwap <jk>extends</jk> StringSwap&lt;MyBean&gt; {
2512       *       <ja>@Override</ja>
2513       *       <jk>public</jk> String swap(BeanSession <jv>session</jv>, MyBean <jv>bean</jv>) <jk>throws</jk> Exception {
2514       *          <jk>if</jk> (<jv>session</jv>.getLocale().equals(Locale.<jsf>UK</jsf>))
2515       *             <jk>return null</jk>;
2516       *          <jk>return</jk> <jv>bean</jv>.toString();
2517       *       }
2518       *    }
2519       *
2520       *    <jc>// Create a serializer that uses the specified locale if it's not passed in through session args.</jc>
2521       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
2522       *       .<jsm>create</jsm>()
2523       *       .locale(Locale.<jsf>UK</jsf>)
2524       *       .swaps(MyBeanSwap.<jk>class</jk>)
2525       *       .build();
2526       * </p>
2527       *
2528       * <h5 class='section'>See Also:</h5><ul>
2529       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#locale()}
2530       *    <li class='jm'>{@link org.apache.juneau.BeanSession.Builder#locale(Locale)}
2531       * </ul>
2532       *
2533       * @param value The new value for this property.
2534       * @return This object.
2535       */
2536      @FluentSetter
2537      public Builder locale(Locale value) {
2538         locale = value;
2539         return this;
2540      }
2541
2542      /**
2543       * <i><l>Context</l> configuration property:&emsp;</i>  Media type.
2544       *
2545       * <p>
2546       * Specifies the default media type for serializer and parser sessions when not specified via {@link BeanSession.Builder#mediaType(MediaType)}.
2547       * Typically used for POJO swaps that need to serialize the same POJO classes differently depending on
2548       * the specific requested media type.   For example, a swap could handle a request for media types <js>"application/json"</js>
2549       * and <js>"application/json+foo"</js> slightly differently even though they're both being handled by the same JSON
2550       * serializer or parser.
2551       *
2552       * <h5 class='section'>Example:</h5>
2553       * <p class='bjava'>
2554       *    <jc>// Define a POJO swap that skips serializing beans if the media type is application/json.</jc>
2555       *    <jk>public class</jk> MyBeanSwap <jk>extends</jk> StringSwap&lt;MyBean&gt; {
2556       *       <ja>@Override</ja>
2557       *       <jk>public</jk> String swap(BeanSession <jv>session</jv>, MyBean <jv>bean</jv>) <jk>throws</jk> Exception {
2558       *          <jk>if</jk> (<jv>session</jv>.getMediaType().equals(<js>"application/json"</js>))
2559       *             <jk>return null</jk>;
2560       *          <jk>return</jk> <jv>bean</jv>.toString();
2561       *       }
2562       *    }
2563       *
2564       *    <jc>// Create a serializer that uses the specified media type if it's not passed in through session args.</jc>
2565       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
2566       *       .<jsm>create</jsm>()
2567       *       .mediaType(MediaType.<jsf>JSON</jsf>)
2568       *       .build();
2569       * </p>
2570       *
2571       * <h5 class='section'>See Also:</h5><ul>
2572       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#mediaType()}
2573       *    <li class='jm'>{@link org.apache.juneau.BeanSession.Builder#mediaType(MediaType)}
2574       * </ul>
2575       *
2576       * @param value The new value for this property.
2577       * @return This object.
2578       */
2579      @FluentSetter
2580      public Builder mediaType(MediaType value) {
2581         mediaType = value;
2582         return this;
2583      }
2584
2585      /**
2586       * Bean class exclusions.
2587       *
2588       * <p>
2589       * List of classes that should not be treated as beans even if they appear to be bean-like.
2590       * Not-bean classes are converted to <c>Strings</c> during serialization.
2591       *
2592       * <p>
2593       * Values can consist of any of the following types:
2594       * <ul>
2595       *    <li>Classes.
2596       *    <li>Arrays and collections of classes.
2597       * </ul>
2598       *
2599       * <h5 class='section'>Example:</h5>
2600       * <p class='bjava'>
2601       *    <jc>// A bean with a single property.</jc>
2602       *    <jk>public class</jk> MyBean {
2603       *       <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
2604       *
2605       *       <jk>public</jk> String toString() {
2606       *          <jk>return</jk> <js>"baz"</js>;
2607       *       }
2608       *    }
2609       *
2610       *    <jc>// Create a serializer that doesn't treat MyBean as a bean class.</jc>
2611       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
2612       *       .<jsm>create</jsm>()
2613       *       .notBeanClasses(MyBean.<jk>class</jk>)
2614       *       .build();
2615       *
2616       *    <jc>// Produces "baz" instead of {"foo":"bar"}</jc>
2617       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
2618       * </p>
2619       *
2620       * <h5 class='section'>Notes:</h5><ul>
2621       *    <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on classes to prevent them from being recognized as beans.
2622       * </ul>
2623       *
2624       * <h5 class='section'>See Also:</h5><ul>
2625       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanIgnore}
2626       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#notBeanClasses()}
2627       * </ul>
2628       *
2629       * @param values
2630       *    The values to add to this setting.
2631       *    <br>Values can consist of any of the following types:
2632       *    <ul>
2633       *       <li>Classes.
2634       *       <li>Arrays and collections of classes.
2635       *    </ul>
2636       * @return This object.
2637       */
2638      @FluentSetter
2639      public Builder notBeanClasses(Class<?>...values) {
2640         return notBeanClasses(alist(values));
2641      }
2642
2643      /**
2644       * Same as {@link #notBeanClasses(Class...)} but allows you to pass in a collection of classes.
2645       *
2646       * @param values
2647       *    The values to add to this setting.
2648       * @return This object.
2649       * @see #notBeanClasses(Class...)
2650       */
2651      @FluentSetter
2652      public Builder notBeanClasses(Collection<Class<?>> values) {
2653         notBeanClasses().addAll(values);
2654         return this;
2655      }
2656
2657      /**
2658       * Returns the list of not-bean classes.
2659       *
2660       * <p>
2661       * Gives access to the inner list if you need to make more than simple additions via {@link #notBeanClasses(Class...)}.
2662       *
2663       * @return The list of not-bean classes.
2664       * @see #notBeanClasses(Class...)
2665       */
2666      public Set<Class<?>> notBeanClasses() {
2667         if (notBeanClasses == null)
2668            notBeanClasses = classSet();
2669         return notBeanClasses;
2670      }
2671
2672      /**
2673       * Bean package exclusions.
2674       *
2675       * <p>
2676       * Used as a convenient way of defining the {@link #notBeanClasses(Class...)} property for entire packages.
2677       * Any classes within these packages will be serialized to strings using {@link Object#toString()}.
2678       *
2679       * <p>
2680       * Note that you can specify suffix patterns to include all subpackages.
2681       *
2682       * <p>
2683       * Values can consist of any of the following types:
2684       * <ul>
2685       *    <li>Strings.
2686       *    <li>Arrays and collections of strings.
2687       * </ul>
2688       *
2689       * <h5 class='section'>Example:</h5>
2690       * <p class='bjava'>
2691       *    <jc>// Create a serializer that ignores beans in the specified packages.</jc>
2692       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
2693       *       .<jsm>create</jsm>()
2694       *       .notBeanPackages(<js>"org.apache.foo"</js>, <js>"org.apache.bar.*"</js>)
2695       *       .build();
2696       * </p>
2697       *
2698       * @param values
2699       *    The values to add to this setting.
2700       *    <br>Values can consist of any of the following types:
2701       *    <ul>
2702       *       <li>{@link Package} objects.
2703       *       <li>Strings.
2704       *       <li>Arrays and collections of anything in this list.
2705       *    </ul>
2706       * @return This object.
2707       */
2708      @FluentSetter
2709      public Builder notBeanPackages(String...values) {
2710         return notBeanPackages(alist(values));
2711      }
2712
2713      /**
2714       * Same as {@link #notBeanPackages(String...)} but allows you to pass in a collection of classes.
2715       *
2716       * @param values
2717       *    The values to add to this setting.
2718       * @return This object.
2719       * @see #notBeanPackages(String...)
2720       */
2721      @FluentSetter
2722      public Builder notBeanPackages(Collection<String> values) {
2723         notBeanPackages().addAll(values);
2724         return this;
2725      }
2726
2727      /**
2728       * Returns the list of not-bean Java package names.
2729       *
2730       * <p>
2731       * Gives access to the inner list if you need to make more than simple additions via {@link #notBeanPackages(String...)}.
2732       *
2733       * @return The list of not-bean Java package names.
2734       * @see #notBeanPackages(String...)
2735       */
2736      public Set<String> notBeanPackages() {
2737         if (notBeanPackages == null)
2738            notBeanPackages = new TreeSet<>();
2739         return notBeanPackages;
2740      }
2741
2742      /**
2743       * Bean property namer
2744       *
2745       * <p>
2746       * The class to use for calculating bean property names.
2747       *
2748       * <p>
2749       * Predefined classes:
2750       * <ul>
2751       *    <li>{@link BasicPropertyNamer} - Default.
2752       *    <li>{@link PropertyNamerDLC} - Dashed-lower-case names.
2753       *    <li>{@link PropertyNamerULC} - Dashed-upper-case names.
2754       * </ul>
2755       *
2756       * <h5 class='section'>Example:</h5>
2757       * <p class='bjava'>
2758       *    <jc>// A bean with a single property.</jc>
2759       *    <jk>public class</jk> MyBean {
2760       *       <jk>public</jk> String <jf>fooBarBaz</jf> = <js>"fooBarBaz"</js>;
2761       *    }
2762       *
2763       *    <jc>// Create a serializer that uses Dashed-Lower-Case property names.</jc>
2764       *    <jc>// (e.g. "foo-bar-baz" instead of "fooBarBaz")</jc>
2765       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
2766       *       .<jsm>create</jsm>()
2767       *       .propertyNamer(PropertyNamerDLC.<jk>class</jk>)
2768       *       .build();
2769       *
2770       *    <jc>// Produces:  {"foo-bar-baz":"fooBarBaz"}</jc>
2771       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
2772       * </p>
2773       *
2774       * @param value
2775       *    The new value for this setting.
2776       *    <br>The default is {@link BasicPropertyNamer}.
2777       * @return This object.
2778       */
2779      @FluentSetter
2780      public Builder propertyNamer(Class<? extends PropertyNamer> value) {
2781         propertyNamer = value;
2782         return this;
2783      }
2784
2785      /**
2786       * Bean property namer
2787       *
2788       * <p>
2789       * Same as {@link #propertyNamer(Class)} but allows you to specify a namer for a specific class.
2790       *
2791       * <h5 class='section'>Example:</h5>
2792       * <p class='bjava'>
2793       *    <jc>// A bean with a single property.</jc>
2794       *    <jk>public class</jk> MyBean {
2795       *       <jk>public</jk> String <jf>fooBarBaz</jf> = <js>"fooBarBaz"</js>;
2796       *    }
2797       *
2798       *    <jc>// Create a serializer that uses Dashed-Lower-Case property names for the MyBean class only.</jc>
2799       *    <jc>// (e.g. "foo-bar-baz" instead of "fooBarBaz")</jc>
2800       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
2801       *       .<jsm>create</jsm>()
2802       *       .propertyNamer(MyBean.<jk>class</jk>, PropertyNamerDLC.<jk>class</jk>)
2803       *       .build();
2804       *
2805       *    <jc>// Produces:  {"foo-bar-baz":"fooBarBaz"}</jc>
2806       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
2807       * </p>
2808       *
2809       * <h5 class='section'>See Also:</h5><ul>
2810       *    <li class='ja'>{@link Bean#propertyNamer() Bean(propertyNamer)}
2811       *    <li class='jm'>{@link #propertyNamer(Class)}
2812       * </ul>
2813       *
2814       * @param on The class that the namer applies to.
2815       * @param value
2816       *    The new value for this setting.
2817       *    <br>The default is {@link BasicPropertyNamer}.
2818       * @return This object.
2819       */
2820      @FluentSetter
2821      public Builder propertyNamer(Class<?> on, Class<? extends PropertyNamer> value) {
2822         return annotations(BeanAnnotation.create(on).propertyNamer(value).build());
2823      }
2824
2825      /**
2826       * Sort bean properties.
2827       *
2828       * <p>
2829       * When enabled, all bean properties will be serialized and access in alphabetical order.
2830       * Otherwise, the natural order of the bean properties is used which is dependent on the JVM vendor.
2831       * On IBM JVMs, the bean properties are ordered based on their ordering in the Java file.
2832       * On Oracle JVMs, the bean properties are not ordered (which follows the official JVM specs).
2833       *
2834       * <p>
2835       * this setting is disabled by default so that IBM JVM users don't have to use {@link Bean @Bean} annotations
2836       * to force bean properties to be in a particular order and can just alter the order of the fields/methods
2837       * in the Java file.
2838       *
2839       * <h5 class='section'>Example:</h5>
2840       * <p class='bjava'>
2841       *    <jc>// A bean with 3 properties.</jc>
2842       *    <jk>public class</jk> MyBean {
2843       *       <jk>public</jk> String <jf>c</jf> = <js>"1"</js>;
2844       *       <jk>public</jk> String <jf>b</jf> = <js>"2"</js>;
2845       *       <jk>public</jk> String <jf>a</jf> = <js>"3"</js>;
2846       *    }
2847       *
2848       *    <jc>// Create a serializer that sorts bean properties.</jc>
2849       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
2850       *       .<jsm>create</jsm>()
2851       *       .sortProperties()
2852       *       .build();
2853       *
2854       *    <jc>// Produces:  {"a":"3","b":"2","c":"1"}</jc>
2855       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
2856       * </p>
2857       *
2858       * <h5 class='section'>Notes:</h5><ul>
2859       *    <li class='note'>The {@link Bean#sort() @Bean.sort()} annotation can also be used to sort properties on just a single class.
2860       * </ul>
2861       *
2862       * @return This object.
2863       */
2864      @FluentSetter
2865      public Builder sortProperties() {
2866         sortProperties = true;
2867         return sortProperties(true);
2868      }
2869
2870      /**
2871       * Same as {@link #sortProperties()} but allows you to explicitly specify the value.
2872       *
2873       * @param value The value for this setting.
2874       * @return This object.
2875       */
2876      @FluentSetter
2877      public Builder sortProperties(boolean value) {
2878         sortProperties = value;
2879         return this;
2880      }
2881
2882      /**
2883       * Sort bean properties.
2884       *
2885       * <p>
2886       * Same as {@link #sortProperties()} but allows you to specify individual bean classes instead of globally.
2887       *
2888       * <h5 class='section'>Example:</h5>
2889       * <p class='bjava'>
2890       *    <jc>// A bean with 3 properties.</jc>
2891       *    <jk>public class</jk> MyBean {
2892       *       <jk>public</jk> String <jf>c</jf> = <js>"1"</js>;
2893       *       <jk>public</jk> String <jf>b</jf> = <js>"2"</js>;
2894       *       <jk>public</jk> String <jf>a</jf> = <js>"3"</js>;
2895       *    }
2896       *
2897       *    <jc>// Create a serializer that sorts properties on MyBean.</jc>
2898       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
2899       *       .<jsm>create</jsm>()
2900       *       .sortProperties(MyBean.<jk>class</jk>)
2901       *       .build();
2902       *
2903       *    <jc>// Produces:  {"a":"3","b":"2","c":"1"}</jc>
2904       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
2905       * </p>
2906       *
2907       * <h5 class='section'>See Also:</h5><ul>
2908       *    <li class='ja'>{@link Bean#sort() Bean(sort)}
2909       *    <li class='jm'>{@link #sortProperties()}
2910       * </ul>
2911       *
2912       * @param on The bean classes to sort properties on.
2913       * @return This object.
2914       */
2915      @FluentSetter
2916      public Builder sortProperties(Class<?>...on) {
2917         for (Class<?> c : on)
2918            annotations(BeanAnnotation.create(c).sort(true).build());
2919         return this;
2920      }
2921
2922      /**
2923       * Identifies a stop class for the annotated class.
2924       *
2925       * <p>
2926       * Identical in purpose to the stop class specified by {@link Introspector#getBeanInfo(Class, Class)}.
2927       * Any properties in the stop class or in its base classes will be ignored during analysis.
2928       *
2929       * <p>
2930       * For example, in the following class hierarchy, instances of <c>C3</c> will include property <c>p3</c>,
2931       * but not <c>p1</c> or <c>p2</c>.
2932       *
2933       * <h5 class='section'>Example:</h5>
2934       * <p class='bjava'>
2935       *    <jk>public class</jk> C1 {
2936       *       <jk>public int</jk> getP1();
2937       *    }
2938       *
2939       *    <jk>public class</jk> C2 <jk>extends</jk> C1 {
2940       *       <jk>public int</jk> getP2();
2941       *    }
2942       *
2943       *    <jk>public class</jk> C3 <jk>extends</jk> C2 {
2944       *       <jk>public int</jk> getP3();
2945       *    }
2946       *
2947       *    <jc>// Create a serializer specifies a stop class for C3.</jc>
2948       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
2949       *       .<jsm>create</jsm>()
2950       *       .stopClass(C3.<jk>class</jk>, C2.<jk>class</jk>)
2951       *       .build();
2952       *
2953       *    <jc>// Produces:  {"p3":"..."}</jc>
2954       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> C3());
2955       * </p>
2956       *
2957       * @param on The class on which the stop class is being applied.
2958       * @param value
2959       *    The new value for this setting.
2960       * @return This object.
2961       */
2962      @FluentSetter
2963      public Builder stopClass(Class<?> on, Class<?> value) {
2964         return annotations(BeanAnnotation.create(on).stopClass(value).build());
2965      }
2966
2967      /**
2968       * Java object swaps.
2969       *
2970       * <p>
2971       * Swaps are used to "swap out" non-serializable classes with serializable equivalents during serialization,
2972       * and "swap in" the non-serializable class during parsing.
2973       *
2974       * <p>
2975       * An example of a swap would be a <c>Calendar</c> object that gets swapped out for an ISO8601 string.
2976       *
2977       * <p>
2978       * Multiple swaps can be associated with a single class.
2979       * When multiple swaps are applicable to the same class, the media type pattern defined by
2980       * {@link ObjectSwap#forMediaTypes()} or {@link Swap#mediaTypes() @Swap(mediaTypes)} are used to come up with the best match.
2981       *
2982       * <p>
2983       * Values can consist of any of the following types:
2984       * <ul>
2985       *    <li>Any subclass of {@link ObjectSwap}.
2986       *    <li>Any instance of {@link ObjectSwap}.
2987       *    <li>Any surrogate class.  A shortcut for defining a {@link SurrogateSwap}.
2988       *    <li>Any array or collection of the objects above.
2989       * </ul>
2990       *
2991       * <h5 class='section'>Example:</h5>
2992       * <p class='bjava'>
2993       *    <jc>// Sample swap for converting Dates to ISO8601 strings.</jc>
2994       *    <jk>public class</jk> MyDateSwap <jk>extends</jk> StringSwap&lt;Date&gt; {
2995       *       <jc>// ISO8601 formatter.</jc>
2996       *       <jk>private</jk> DateFormat <jf>format</jf> = <jk>new</jk> SimpleDateFormat(<js>"yyyy-MM-dd'T'HH:mm:ssZ"</js>);
2997       *
2998       *       <ja>@Override</ja>
2999       *       <jk>public</jk> String swap(BeanSession <jv>session</jv>, Date <jv>date</jv>) {
3000       *          <jk>return</jk> <jf>format</jf>.format(<jv>date</jv>);
3001       *       }
3002       *
3003       *       <ja>@Override</ja>
3004       *       <jk>public</jk> Date unswap(BeanSession <jv>session</jv>, String <jv>string</jv>, ClassMeta <jv>hint</jv>) <jk>throws</jk> Exception {
3005       *          <jk>return</jk> <jf>format</jf>.parse(<jv>string</jv>);
3006       *       }
3007       *    }
3008       *
3009       *    <jc>// Sample bean with a Date field.</jc>
3010       *    <jk>public class</jk> MyBean {
3011       *       <jk>public</jk> Date <jf>date</jf> = <jk>new</jk> Date(112, 2, 3, 4, 5, 6);
3012       *    }
3013       *
3014       *    <jc>// Create a serializer that uses our date swap.</jc>
3015       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
3016       *       .<jsm>create</jsm>()
3017       *       .swaps(MyDateSwap.<jk>class</jk>)
3018       *       .build();
3019       *
3020       *    <jc>// Produces:  {"date":"2012-03-03T04:05:06-0500"}</jc>
3021       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
3022       *
3023       *    <jc>// Create a serializer that uses our date swap.</jc>
3024       *    ReaderParser <jv>parser</jv> = JsonParser
3025       *       .<jsm>create</jsm>()
3026       *       .swaps(MyDateSwap.<jk>class</jk>)
3027       *       .build();
3028       *
3029       *    <jc>// Use our parser to parse a bean.</jc>
3030       *    MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>);
3031       * </p>
3032       *
3033       * <h5 class='section'>Notes:</h5><ul>
3034       *    <li class='note'>The {@link Swap @Swap} annotation can also be used on classes to identify swaps for the class.
3035       *    <li class='note'>The {@link Swap @Swap} annotation can also be used on bean methods and fields to identify swaps for values of those bean properties.
3036       * </ul>
3037       *
3038       * @param values
3039       *    The values to add to this setting.
3040       *    <br>Values can consist of any of the following types:
3041       *    <ul>
3042       *       <li>Any subclass of {@link ObjectSwap}.
3043       *       <li>Any surrogate class.  A shortcut for defining a {@link SurrogateSwap}.
3044       *       <li>Any array or collection of the objects above.
3045       *    </ul>
3046       * @return This object.
3047       */
3048      @FluentSetter
3049      public Builder swaps(Class<?>...values) {
3050         return swaps(alist(values));
3051      }
3052
3053      /**
3054       * Same as {@link #swaps(Class...)} but allows you to pass in a collection of classes.
3055       *
3056       * @param values
3057       *    The values to add to this setting.
3058       * @return This object.
3059       * @see #swaps(Class...)
3060       */
3061      @FluentSetter
3062      public Builder swaps(Collection<Class<?>> values) {
3063         swaps().addAll(0, values);
3064         return this;
3065      }
3066
3067      /**
3068       * A shortcut for defining a {@link FunctionalSwap}.
3069       *
3070       * <h5 class='section'>Example:</h5>
3071       * <p class='bjava'>
3072       *    <jc>// Create a serializer that performs a custom format for DAte objects.</jc>
3073       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
3074       *       .<jsm>create</jsm>()
3075       *       .swap(Date.<jk>class</jk>, String.<jk>class</jk>, <jv>x</jv> -&gt; <jsm>format</jsm>(<jv>x</jv>))
3076       *       .build();
3077       * </p>
3078       *
3079       * @param <T> The object type being swapped out.
3080       * @param <S> The object type being swapped in.
3081       * @param normalClass The object type being swapped out.
3082       * @param swappedClass The object type being swapped in.
3083       * @param swapFunction The function to convert the object.
3084       * @return This object.
3085       */
3086      @FluentSetter
3087      public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) {
3088         return swap(normalClass, swappedClass, swapFunction, null);
3089      }
3090
3091      /**
3092       * A shortcut for defining a {@link FunctionalSwap}.
3093       *
3094       * <h5 class='section'>Example:</h5>
3095       * <p class='bjava'>
3096       *    <jc>// Create a serializer that performs a custom format for Date objects.</jc>
3097       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
3098       *       .<jsm>create</jsm>()
3099       *       .swap(Date.<jk>class</jk>, String.<jk>class</jk>, <jv>x</jv> -&gt; <jsm>format</jsm>(<jv>x</jv>), <jv>x</jv> -&gt; <jsm>parse</jsm>(<jv>x</jv>))
3100       *       .build();
3101       * </p>
3102       *
3103       * @param <T> The object type being swapped out.
3104       * @param <S> The object type being swapped in.
3105       * @param normalClass The object type being swapped out.
3106       * @param swappedClass The object type being swapped in.
3107       * @param swapFunction The function to convert the object during serialization.
3108       * @param unswapFunction The function to convert the object during parsing.
3109       * @return This object.
3110       */
3111      @FluentSetter
3112      public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) {
3113         swaps().add(0, new FunctionalSwap<>(normalClass, swappedClass, swapFunction, unswapFunction));
3114         return this;
3115      }
3116
3117      /**
3118       * Returns the bean swaps list.
3119       *
3120       * <p>
3121       * Gives access to the inner list if you need to make more than simple additions via {@link #swaps(Class...)}.
3122       *
3123       * @return The bean swaps list.
3124       * @see #swaps(Class...)
3125       */
3126      public List<Object> swaps() {
3127         if (swaps == null)
3128            swaps = list();
3129         return swaps;
3130      }
3131
3132      /**
3133       * <i><l>Context</l> configuration property:&emsp;</i>  TimeZone.
3134       *
3135       * <p>
3136       * Specifies the default time zone for serializer and parser sessions when not specified via {@link BeanSession.Builder#timeZone(TimeZone)}.
3137       * Typically used for POJO swaps that need to deal with timezones such as swaps that convert <l>Date</l> and <l>Calendar</l>
3138       * objects to strings by accessing it via the session passed into the {@link ObjectSwap#swap(BeanSession, Object)} and
3139       * {@link ObjectSwap#unswap(BeanSession, Object, ClassMeta, String)} methods.
3140       *
3141       * <h5 class='section'>Example:</h5>
3142       * <p class='bjava'>
3143       *    <jc>// Define a POJO swap that skips serializing beans if the time zone is GMT.</jc>
3144       *    <jk>public class</jk> MyBeanSwap <jk>extends</jk> StringSwap&lt;MyBean&gt; {
3145       *       <ja>@Override</ja>
3146       *       <jk>public</jk> String swap(BeanSession <jv>session</jv>, MyBean <jv>bean</jv>) <jk>throws</jk> Exception {
3147       *          <jk>if</jk> (<jv>session</jv>.getTimeZone().equals(TimeZone.<jsf>GMT</jsf>))
3148       *             <jk>return null</jk>;
3149       *          <jk>return</jk> <jv>bean</jv>.toString();
3150       *       }
3151       *    }
3152       *
3153       *    <jc>// Create a serializer that uses GMT if the timezone is not specified in the session args.</jc>
3154       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
3155       *       .<jsm>create</jsm>()
3156       *       .timeZone(TimeZone.<jsf>GMT</jsf>)
3157       *       .build();
3158       * </p>
3159       *
3160       * <h5 class='section'>See Also:</h5><ul>
3161       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#timeZone()}
3162       *    <li class='jm'>{@link org.apache.juneau.BeanSession.Builder#timeZone(TimeZone)}
3163       * </ul>
3164       *
3165       * @param value The new value for this property.
3166       * @return This object.
3167       */
3168      @FluentSetter
3169      public Builder timeZone(TimeZone value) {
3170         timeZone = value;
3171         return this;
3172      }
3173
3174      /**
3175       * An identifying name for this class.
3176       *
3177       * <p>
3178       * The name is used to identify the class type during parsing when it cannot be inferred through reflection.
3179       * For example, if a bean property is of type <c>Object</c>, then the serializer will add the name to the
3180       * output so that the class can be determined during parsing.
3181       *
3182       * <p>
3183       * It is also used to specify element names in XML.
3184       *
3185       * <h5 class='section'>Example:</h5>
3186       * <p class='bjava'>
3187       *    <jc>// Use _type='mybean' to identify this bean.</jc>
3188       *    <jk>public class</jk> MyBean {...}
3189       *
3190       *    <jc>// Create a serializer and specify the type name..</jc>
3191       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
3192       *       .<jsm>create</jsm>()
3193       *       .typeName(MyBean.<jk>class</jk>, <js>"mybean"</js>)
3194       *       .build();
3195       *
3196       *    <jc>// Produces:  {"_type":"mybean",...}</jc>
3197       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
3198       * </p>
3199       *
3200       * <h5 class='section'>Notes:</h5><ul>
3201       *    <li class='note'>Equivalent to the {@link Bean#typeName() Bean(typeName)} annotation.
3202       * </ul>
3203       *
3204       * <h5 class='section'>See Also:</h5><ul>
3205       *    <li class='jc'>{@link Bean#typeName() Bean(typeName)}
3206       *    <li class='jm'>{@link #beanDictionary(Class...)}
3207       * </ul>
3208       *
3209       * @param on
3210       *    The class the type name is being defined on.
3211       * @param value
3212       *    The new value for this setting.
3213       * @return This object.
3214       */
3215      @FluentSetter
3216      public Builder typeName(Class<?> on, String value) {
3217         return annotations(BeanAnnotation.create(on).typeName(value).build());
3218      }
3219
3220      /**
3221       * Bean type property name.
3222       *
3223       * <p>
3224       * This specifies the name of the bean property used to store the dictionary name of a bean type so that the
3225       * parser knows the data type to reconstruct.
3226       *
3227       * <h5 class='section'>Example:</h5>
3228       * <p class='bjava'>
3229       *    <jc>// POJOs with @Bean(name) annotations.</jc>
3230       *    <ja>@Bean</ja>(typeName=<js>"foo"</js>)
3231       *    <jk>public class</jk> Foo {...}
3232       *    <ja>@Bean</ja>(typeName=<js>"bar"</js>)
3233       *    <jk>public class</jk> Bar {...}
3234       *
3235       *    <jc>// Create a serializer that uses 't' instead of '_type' for dictionary names.</jc>
3236       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
3237       *       .<jsm>create</jsm>()
3238       *       .typePropertyName(<js>"t"</js>)
3239       *       .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>)
3240       *       .build();
3241       *
3242       *    <jc>// Create a serializer that uses 't' instead of '_type' for dictionary names.</jc>
3243       *    ReaderParser <jv>parser</jv> = JsonParser
3244       *       .<jsm>create</jsm>()
3245       *       .typePropertyName(<js>"t"</js>)
3246       *       .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>)
3247       *       .build();
3248       *
3249       *    <jc>// A bean with a field with an indeterminate type.</jc>
3250       *    <jk>public class</jk> MyBean {
3251       *       <jk>public</jk> Object <jf>mySimpleField</jf>;
3252       *    }
3253       *
3254       *    <jc>// Produces "{mySimpleField:{t:'foo',...}}".</jc>
3255       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
3256       *
3257       *    <jc>// Parse bean.</jc>
3258       *    MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>);
3259       * </p>
3260       *
3261       * <h5 class='section'>See Also:</h5><ul>
3262       *    <li class='ja'>{@link org.apache.juneau.annotation.Bean#typePropertyName()}
3263       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#typePropertyName()}
3264       * </ul>
3265       *
3266       * @param value
3267       *    The new value for this setting.
3268       *    <br>The default is <js>"_type"</js>.
3269       * @return This object.
3270       */
3271      @FluentSetter
3272      public Builder typePropertyName(String value) {
3273         typePropertyName = value;
3274         return this;
3275      }
3276
3277      /**
3278       * Bean type property name.
3279       *
3280       * <p>
3281       * Same as {@link #typePropertyName(String)} except targets a specific bean class instead of globally.
3282       *
3283       * <h5 class='section'>Example:</h5>
3284       * <p class='bjava'>
3285       *    <jc>// POJOs with @Bean(name) annotations.</jc>
3286       *    <ja>@Bean</ja>(typeName=<js>"foo"</js>)
3287       *    <jk>public class</jk> Foo {...}
3288       *    <ja>@Bean</ja>(typeName=<js>"bar"</js>)
3289       *    <jk>public class</jk> Bar {...}
3290       *
3291       *    <jc>// A bean with a field with an indeterminate type.</jc>
3292       *    <jk>public class</jk> MyBean {
3293       *       <jk>public</jk> Object <jf>mySimpleField</jf>;
3294       *    }
3295       *
3296       *    <jc>// Create a serializer that uses 't' instead of '_type' for dictionary names.</jc>
3297       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
3298       *       .<jsm>create</jsm>()
3299       *       .typePropertyName(MyBean.<jk>class</jk>, <js>"t"</js>)
3300       *       .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>)
3301       *       .build();
3302       *
3303       *    <jc>// Produces "{mySimpleField:{t:'foo',...}}".</jc>
3304       *    String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
3305       * </p>
3306       *
3307       * <h5 class='section'>See Also:</h5><ul>
3308       *    <li class='ja'>{@link Bean#typePropertyName() Bean(typePropertyName)}
3309       * </ul>
3310       *
3311       * @param on The class the type property name applies to.
3312       * @param value
3313       *    The new value for this setting.
3314       *    <br>The default is <js>"_type"</js>.
3315       * @return This object.
3316       */
3317      @FluentSetter
3318      public Builder typePropertyName(Class<?> on, String value) {
3319         return annotations(BeanAnnotation.create(on).typePropertyName(value).build());
3320      }
3321
3322      /**
3323       * Use enum names.
3324       *
3325       * <p>
3326       * When enabled, enums are always serialized by name, not using {@link Object#toString()}.
3327       *
3328       * <h5 class='section'>Example:</h5>
3329       * <p class='bjava'>
3330       *    <jc>// Create a serializer with debug enabled.</jc>
3331       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
3332       *       .<jsm>create</jsm>()
3333       *       .useEnumNames()
3334       *       .build();
3335       *
3336       *    <jc>// Enum with overridden toString().</jc>
3337       *    <jc>// Will be serialized as ONE/TWO/THREE even though there's a toString() method.</jc>
3338       *    <jk>public enum</jk> Option {
3339       *       <jsf>ONE</jsf>(1),
3340       *       <jsf>TWO</jsf>(2),
3341       *       <jsf>THREE</jsf>(3);
3342       *
3343       *       <jk>private int</jk> <jf>value</jf>;
3344       *
3345       *       Option(<jk>int</jk> <jv>value</jv>) {
3346       *          <jk>this</jk>.<jf>value</jf> = <jv>value</jv>;
3347       *       }
3348       *
3349       *       <ja>@Override</ja>
3350       *       <jk>public</jk> String toString() {
3351       *          <jk>return</jk> String.<jsm>valueOf</jsm>(<jf>value</jf>);
3352       *       }
3353       *    }
3354       * </p>
3355       *
3356       * @return This object.
3357       */
3358      @FluentSetter
3359      public Builder useEnumNames() {
3360         return useEnumNames(true);
3361      }
3362
3363      /**
3364       * Same as {@link #useEnumNames()} but allows you to explicitly specify the value.
3365       *
3366       * @param value The value for this setting.
3367       * @return This object.
3368       */
3369      @FluentSetter
3370      public Builder useEnumNames(boolean value) {
3371         useEnumNames = value;
3372         return this;
3373      }
3374
3375      /**
3376       * Don't use interface proxies.
3377       *
3378       * <p>
3379       * When enabled, interfaces will be instantiated as proxy classes through the use of an
3380       * {@link InvocationHandler} if there is no other way of instantiating them.
3381       * Otherwise, throws a {@link BeanRuntimeException}.
3382       *
3383       * <h5 class='section'>See Also:</h5><ul>
3384       *    <li class='ja'>{@link org.apache.juneau.annotation.BeanConfig#disableInterfaceProxies()}
3385       * </ul>
3386       *
3387       * @return This object.
3388       */
3389      @FluentSetter
3390      public Builder disableInterfaceProxies() {
3391         return disableInterfaceProxies(true);
3392      }
3393
3394      /**
3395       * Same as {@link #disableInterfaceProxies()} but allows you to explicitly specify the value.
3396       *
3397       * @param value The value for this setting.
3398       * @return This object.
3399       */
3400      @FluentSetter
3401      public Builder disableInterfaceProxies(boolean value) {
3402         disableInterfaceProxies = value;
3403         return this;
3404      }
3405
3406      /**
3407       * Use Java Introspector.
3408       *
3409       * <p>
3410       * Using the built-in Java bean introspector will not pick up fields or non-standard getters/setters.
3411       * <br>Most {@link Bean @Bean} annotations will be ignored.
3412       *
3413       * <h5 class='section'>Example:</h5>
3414       * <p class='bjava'>
3415       *    <jc>// Create a serializer that only uses the built-in java bean introspector for finding properties.</jc>
3416       *    WriterSerializer <jv>serializer</jv> = JsonSerializer
3417       *       .<jsm>create</jsm>()
3418       *       .useJavaBeanIntrospector()
3419       *       .build();
3420       * </p>
3421       *
3422       * @return This object.
3423       */
3424      @FluentSetter
3425      public Builder useJavaBeanIntrospector() {
3426         return useJavaBeanIntrospector(true);
3427      }
3428
3429      /**
3430       * Same as {@link #useJavaBeanIntrospector()} but allows you to explicitly specify the value.
3431       *
3432       * @param value The value for this setting.
3433       * @return This object.
3434       */
3435      @FluentSetter
3436      public Builder useJavaBeanIntrospector(boolean value) {
3437         useJavaBeanIntrospector = value;
3438         return this;
3439      }
3440
3441      // <FluentSetters>
3442
3443      @Override /* GENERATED - org.apache.juneau.Context.Builder */
3444      public Builder annotations(Annotation...values) {
3445         super.annotations(values);
3446         return this;
3447      }
3448
3449      @Override /* GENERATED - org.apache.juneau.Context.Builder */
3450      public Builder apply(AnnotationWorkList work) {
3451         super.apply(work);
3452         return this;
3453      }
3454
3455      @Override /* GENERATED - org.apache.juneau.Context.Builder */
3456      public Builder applyAnnotations(java.lang.Class<?>...fromClasses) {
3457         super.applyAnnotations(fromClasses);
3458         return this;
3459      }
3460
3461      @Override /* GENERATED - org.apache.juneau.Context.Builder */
3462      public Builder applyAnnotations(Method...fromMethods) {
3463         super.applyAnnotations(fromMethods);
3464         return this;
3465      }
3466
3467      @Override /* GENERATED - org.apache.juneau.Context.Builder */
3468      public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) {
3469         super.cache(value);
3470         return this;
3471      }
3472
3473      @Override /* GENERATED - org.apache.juneau.Context.Builder */
3474      public Builder debug() {
3475         super.debug();
3476         return this;
3477      }
3478
3479      @Override /* GENERATED - org.apache.juneau.Context.Builder */
3480      public Builder debug(boolean value) {
3481         super.debug(value);
3482         return this;
3483      }
3484
3485      @Override /* GENERATED - org.apache.juneau.Context.Builder */
3486      public Builder impl(Context value) {
3487         super.impl(value);
3488         return this;
3489      }
3490
3491      @Override /* GENERATED - org.apache.juneau.Context.Builder */
3492      public Builder type(Class<? extends org.apache.juneau.Context> value) {
3493         super.type(value);
3494         return this;
3495      }
3496
3497      // </FluentSetters>
3498
3499      //-----------------------------------------------------------------------------------------------------------------
3500      // Helpers
3501      //-----------------------------------------------------------------------------------------------------------------
3502
3503      private static Set<Class<?>> classSet() {
3504         return new TreeSet<>(Comparator.comparing(Class::getName));
3505      }
3506
3507      private static Set<Class<?>> classSet(Collection<Class<?>> copy) {
3508         return classSet(copy, false);
3509      }
3510
3511      private static Set<Class<?>> classSet(Collection<Class<?>> copy, boolean nullIfEmpty) {
3512         if (copy == null || (nullIfEmpty && copy.isEmpty()))
3513            return null;
3514         Set<Class<?>> x = classSet();
3515         x.addAll(copy);
3516         return x;
3517      }
3518   }
3519
3520   //-----------------------------------------------------------------------------------------------------------------
3521   // Instance
3522   //-----------------------------------------------------------------------------------------------------------------
3523
3524   final boolean
3525      beansRequireDefaultConstructor,
3526      beansRequireSerializable,
3527      beansRequireSettersForGetters,
3528      beansRequireSomeProperties,
3529      beanMapPutReturnsOldValue,
3530      useInterfaceProxies,
3531      ignoreUnknownBeanProperties,
3532      ignoreUnknownNullBeanProperties,
3533      ignoreUnknownEnumValues,
3534      ignoreMissingSetters,
3535      ignoreTransientFields,
3536      ignoreInvocationExceptionsOnGetters,
3537      ignoreInvocationExceptionsOnSetters,
3538      useJavaBeanIntrospector,
3539      useEnumNames,
3540      sortProperties,
3541      findFluentSetters;
3542   final Visibility
3543      beanConstructorVisibility,
3544      beanClassVisibility,
3545      beanMethodVisibility,
3546      beanFieldVisibility;
3547   final String typePropertyName;
3548   final Locale locale;
3549   final TimeZone timeZone;
3550   final MediaType mediaType;
3551   final Class<? extends PropertyNamer> propertyNamer;
3552   final List<Class<?>> beanDictionary, notBeanClasses;
3553   final List<Object> swaps;
3554   final List<String> notBeanPackages;
3555   final HashKey hashKey;
3556
3557   final Map<Class,ClassMeta> cmCache;
3558
3559   private final String[] notBeanPackageNames, notBeanPackagePrefixes;
3560   private final BeanRegistry beanRegistry;
3561   private final PropertyNamer propertyNamerBean;
3562   private final ObjectSwap[] swapArray;
3563   private final Class<?>[] notBeanClassesArray;
3564   private final ClassMeta<Object> cmObject;  // Reusable ClassMeta that represents general Objects.
3565   private final ClassMeta<String> cmString;  // Reusable ClassMeta that represents general Strings.
3566   private final ClassMeta<Class> cmClass;  // Reusable ClassMeta that represents general Classes.
3567
3568   private final BeanSession defaultSession;
3569   private volatile WriterSerializer beanToStringSerializer;
3570
3571   /**
3572    * Constructor.
3573    *
3574    * @param builder The builder for this object.
3575    */
3576   public BeanContext(Builder builder) {
3577      super(builder);
3578
3579      hashKey = builder.hashKey();
3580
3581      beanConstructorVisibility = builder.beanConstructorVisibility;
3582      beanClassVisibility = builder.beanClassVisibility;
3583      beanMethodVisibility = builder.beanMethodVisibility;
3584      beanFieldVisibility = builder.beanFieldVisibility;
3585      beansRequireDefaultConstructor = builder.beansRequireDefaultConstructor;
3586      beansRequireSerializable = builder.beansRequireSerializable;
3587      beansRequireSettersForGetters = builder.beansRequireSettersForGetters;
3588      beansRequireSomeProperties = ! builder.disableBeansRequireSomeProperties;
3589      beanMapPutReturnsOldValue = builder.beanMapPutReturnsOldValue;
3590      useEnumNames = builder.useEnumNames;
3591      useInterfaceProxies = ! builder.disableInterfaceProxies;
3592      ignoreUnknownBeanProperties = builder.ignoreUnknownBeanProperties;
3593      ignoreUnknownNullBeanProperties = ! builder.disableIgnoreUnknownNullBeanProperties;
3594      ignoreUnknownEnumValues = builder.ignoreUnknownEnumValues;
3595      ignoreMissingSetters = ! builder.disableIgnoreMissingSetters;
3596      ignoreTransientFields = ! builder.disableIgnoreTransientFields;
3597      ignoreInvocationExceptionsOnGetters = builder.ignoreInvocationExceptionsOnGetters;
3598      ignoreInvocationExceptionsOnSetters = builder.ignoreInvocationExceptionsOnSetters;
3599      useJavaBeanIntrospector = builder.useJavaBeanIntrospector;
3600      sortProperties = builder.sortProperties;
3601      findFluentSetters = builder.findFluentSetters;
3602      typePropertyName = builder.typePropertyName != null ? builder.typePropertyName : "_type";
3603      locale = builder.locale != null ? builder.locale : Locale.getDefault();
3604      timeZone = builder.timeZone;
3605      mediaType = builder.mediaType;
3606      beanDictionary = optional(builder.beanDictionary).map(Collections::unmodifiableList).orElse(emptyList());
3607      swaps = optional(builder.swaps).map(Collections::unmodifiableList).orElse(emptyList());
3608      notBeanClasses = optional(builder.notBeanClasses).map(ArrayList::new).map(Collections::unmodifiableList).orElse(emptyList());
3609      notBeanPackages = optional(builder.notBeanPackages).map(ArrayList::new).map(Collections::unmodifiableList).orElse(emptyList());
3610      propertyNamer = builder.propertyNamer != null ? builder.propertyNamer : BasicPropertyNamer.class;
3611
3612      notBeanClassesArray = notBeanClasses.isEmpty() ? DEFAULT_NOTBEAN_CLASSES : Stream.of(notBeanClasses, alist(DEFAULT_NOTBEAN_CLASSES)).flatMap(Collection::stream).toArray(Class[]::new);
3613
3614      String[] _notBeanPackages = notBeanPackages.isEmpty() ? DEFAULT_NOTBEAN_PACKAGES : Stream.of(notBeanPackages, alist(DEFAULT_NOTBEAN_PACKAGES)).flatMap(Collection::stream).toArray(String[]::new);
3615      notBeanPackageNames = Stream.of(_notBeanPackages).filter(x -> ! x.endsWith(".*")).toArray(String[]::new);
3616      notBeanPackagePrefixes = Stream.of(_notBeanPackages).filter(x -> x.endsWith(".*")).map(x -> x.substring(0, x.length()-2)).toArray(String[]::new);
3617
3618      try {
3619         propertyNamerBean = propertyNamer.getDeclaredConstructor().newInstance();
3620      } catch (Exception e) {
3621         throw asRuntimeException(e);
3622      }
3623
3624      LinkedList<ObjectSwap<?,?>> _swaps = new LinkedList<>();
3625      swaps.forEach(x -> {
3626         if (x instanceof ObjectSwap) {
3627            _swaps.add((ObjectSwap<?,?>)x);
3628         } else {
3629            ClassInfo ci = ClassInfo.of((Class<?>)x);
3630            if (ci.isChildOf(ObjectSwap.class))
3631               _swaps.add(BeanCreator.of(ObjectSwap.class).type(ci).run());
3632            else if (ci.isChildOf(Surrogate.class))
3633               _swaps.addAll(SurrogateSwap.findObjectSwaps(ci.inner(), this));
3634            else
3635               throw new BasicRuntimeException("Invalid class {0} specified in BeanContext.swaps property.  Must be a subclass of ObjectSwap or Surrogate.", ci.inner());
3636         }
3637      });
3638      swapArray = _swaps.toArray(new ObjectSwap[_swaps.size()]);
3639
3640      cmCache = new ConcurrentHashMap<>();
3641      cmCache.put(String.class, new ClassMeta(String.class, this, findObjectSwaps(String.class), findChildObjectSwaps(String.class)));
3642      cmCache.put(Object.class, new ClassMeta(Object.class, this, findObjectSwaps(Object.class), findChildObjectSwaps(Object.class)));
3643      cmString = cmCache.get(String.class);
3644      cmObject = cmCache.get(Object.class);
3645      cmClass = cmCache.get(Class.class);
3646
3647      beanRegistry = new BeanRegistry(this, null);
3648      defaultSession = createSession().unmodifiable().build();
3649   }
3650
3651   @Override /* Context */
3652   public Builder copy() {
3653      return new Builder(this);
3654   }
3655
3656   @Override /* Context */
3657   public BeanSession.Builder createSession() {
3658      return BeanSession.create(this);
3659   }
3660
3661   @Override /* Context */
3662   public BeanSession getSession() {
3663      return defaultSession;
3664   }
3665
3666   /**
3667    * Returns <jk>true</jk> if the specified bean context shares the same cache as this bean context.
3668    *
3669    * <p>
3670    * Useful for testing purposes.
3671    *
3672    * @param bc The bean context to compare to.
3673    * @return <jk>true</jk> if the bean contexts have equivalent settings and thus share caches.
3674    */
3675   public final boolean hasSameCache(BeanContext bc) {
3676      return bc.cmCache == this.cmCache;
3677   }
3678
3679   /**
3680    * Wraps an object inside a {@link BeanMap} object (a modifiable {@link Map}).
3681    *
3682    * <p>
3683    * This is a shortcut for the following code:  <c>createSession().build().toBeanMap(<jv>object</jv>);</c>
3684    *
3685    * <h5 class='section'>Example:</h5>
3686    * <p class='bjava'>
3687    *    <jc>// Construct a bean map around a bean instance</jc>
3688    *    BeanMap&lt;Person&gt; <jv>beanMap</jv> = BeanContext.<jsf>DEFAULT</jsf>.toBeanMap(<jk>new</jk> Person());
3689    * </p>
3690    *
3691    * @param <T> The class of the object being wrapped.
3692    * @param object The object to wrap in a map interface.  Must not be null.
3693    * @return The wrapped object.
3694    * @see BeanSession#toBeanMap(Object)
3695    */
3696   public <T> BeanMap<T> toBeanMap(T object) {
3697      return defaultSession.toBeanMap(object);
3698   }
3699
3700   /**
3701    * Creates a new {@link BeanMap} object (a modifiable {@link Map}) of the given class with uninitialized
3702    * property values.
3703    *
3704    * <p>
3705    * This is a shortcut for the following code:  <c>createSession().build().newBeanMap(<jv>_class</jv>);</c>
3706    *
3707    * <h5 class='section'>Example:</h5>
3708    * <p class='bjava'>
3709    *    <jc>// Construct a new bean map wrapped around a new Person object</jc>
3710    *    BeanMap&lt;Person&gt; <jv>beanMap</jv> = BeanContext.<jsf>DEFAULT</jsf>.newBeanMap(Person.<jk>class</jk>);
3711    * </p>
3712    *
3713    * @param <T> The class of the object being wrapped.
3714    * @param c The name of the class to create a new instance of.
3715    * @return A new instance of the class.
3716    * @see BeanSession#newBeanMap(Class)
3717    */
3718   public <T> BeanMap<T> newBeanMap(Class<T> c) {
3719      return defaultSession.newBeanMap(c);
3720   }
3721
3722   /**
3723    * Converts the specified value to the specified class type.
3724    *
3725    * <p>
3726    * This is a shortcut for the following code:  <c>createSession().build().convertToType(<jv>value</jv>, <jv>type</jv>);</c>
3727    *
3728    * @param <T> The class type to convert the value to.
3729    * @param value The value to convert.
3730    * @param type The class type to convert the value to.
3731    * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type.
3732    * @return The converted value.
3733    * @see BeanSession#convertToType(Object, Class)
3734    */
3735   public final <T> T convertToType(Object value, Class<T> type) throws InvalidDataConversionException {
3736      return defaultSession.convertToType(value, type);
3737   }
3738
3739   /**
3740    * Same as {@link #convertToType(Object, Class)}, except used for instantiating inner member classes that must
3741    * be instantiated within another class instance.
3742    *
3743    * <p>
3744    * This is a shortcut for the following code:  <c>createSession().build().convertToMemberType(<jv>outer</jv>, <jv>value</jv>, <jv>type</jv>);</c>
3745    *
3746    * @param <T> The class type to convert the value to.
3747    * @param outer
3748    *    If class is a member class, this is the instance of the containing class.
3749    *    Should be <jk>null</jk> if not a member class.
3750    * @param value The value to convert.
3751    * @param type The class type to convert the value to.
3752    * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type.
3753    * @return The converted value.
3754    * @see BeanSession#convertToMemberType(Object, Object, Class)
3755    */
3756   public final <T> T convertToMemberType(Object outer, Object value, Class<T> type) throws InvalidDataConversionException {
3757      return defaultSession.convertToMemberType(outer, value, getClassMeta(type));
3758   }
3759
3760   /**
3761    * Same as {@link #convertToType(Object, Class)}, but allows for complex data types consisting of collections or maps.
3762    *
3763    * <p>
3764    * This is a shortcut for the following code:  <c>createSession().build().convertToType(<jv>value</jv>, <jv>type</jv>, <jv>args</jv>);</c>
3765    *
3766    * @param <T> The class type to convert the value to.
3767    * @param value The value to be converted.
3768    * @param type The target object type.
3769    * @param args The target object parameter types.
3770    * @return The converted type.
3771    * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type.
3772    * @see BeanSession#convertToType(Object, Type, Type...)
3773    */
3774   public final <T> T convertToType(Object value, Type type, Type...args) throws InvalidDataConversionException {
3775      return (T)defaultSession.convertToMemberType(null, value, getClassMeta(type, args));
3776   }
3777
3778   /**
3779    * Determines whether the specified class is ignored as a bean class based on the various exclusion parameters
3780    * specified on this context class.
3781    *
3782    * @param c The class type being tested.
3783    * @return <jk>true</jk> if the specified class matches any of the exclusion parameters.
3784    */
3785   protected final boolean isNotABean(Class<?> c) {
3786      if (c.isArray() || c.isPrimitive() || c.isEnum() || c.isAnnotation())
3787         return true;
3788      Package p = c.getPackage();
3789      if (p != null) {
3790         for (String p2 : notBeanPackageNames)
3791            if (p.getName().equals(p2))
3792               return true;
3793         for (String p2 : notBeanPackagePrefixes)
3794            if (p.getName().startsWith(p2))
3795               return true;
3796      }
3797      ClassInfo ci = ClassInfo.of(c);
3798      for (Class exclude : notBeanClassesArray)
3799         if (ci.isChildOf(exclude))
3800            return true;
3801      return false;
3802   }
3803
3804   /**
3805    * Returns <jk>true</jk> if the specified object is a bean.
3806    *
3807    * @param o The object to test.
3808    * @return <jk>true</jk> if the specified object is a bean.  <jk>false</jk> if the bean is <jk>null</jk>.
3809    */
3810   public boolean isBean(Object o) {
3811      if (o == null)
3812         return false;
3813      return getClassMetaForObject(o).isBean();
3814   }
3815
3816   /**
3817    * Returns the {@link BeanMeta} class for the specified class.
3818    *
3819    * @param <T> The class type to get the meta-data on.
3820    * @param c The class to get the meta-data on.
3821    * @return
3822    *    The {@link BeanMeta} for the specified class, or <jk>null</jk> if the class is not a bean per the settings on
3823    *    this context.
3824    */
3825   public final <T> BeanMeta<T> getBeanMeta(Class<T> c) {
3826      if (c == null)
3827         return null;
3828      return getClassMeta(c).getBeanMeta();
3829   }
3830
3831   /**
3832    * Construct a {@code ClassMeta} wrapper around a {@link Class} object.
3833    *
3834    * @param <T> The class type being wrapped.
3835    * @param type The class to resolve.
3836    * @return
3837    *    If the class is not an array, returns a cached {@link ClassMeta} object.
3838    *    Otherwise, returns a new {@link ClassMeta} object every time.
3839    */
3840   public final <T> ClassMeta<T> getClassMeta(Class<T> type) {
3841      return getClassMeta(type, true);
3842   }
3843
3844   /**
3845    * Construct a {@code ClassMeta} wrapper around a {@link Class} object.
3846    *
3847    * @param <T> The class type being wrapped.
3848    * @param type The class to resolve.
3849    * @param waitForInit
3850    *    When enabled, wait for the ClassMeta constructor to finish before returning.
3851    * @return
3852    *    If the class is not an array, returns a cached {@link ClassMeta} object.
3853    *    Otherwise, returns a new {@link ClassMeta} object every time.
3854    */
3855   final <T> ClassMeta<T> getClassMeta(Class<T> type, boolean waitForInit) {
3856
3857      // This can happen if we have transforms defined against String or Object.
3858      if (cmCache == null)
3859         return null;
3860
3861      ClassMeta<T> cm = cmCache.get(type);
3862      if (cm == null) {
3863
3864         synchronized (this) {
3865            // Make sure someone didn't already set it while this thread was blocked.
3866            cm = cmCache.get(type);
3867            if (cm == null)
3868               cm = new ClassMeta<>(type, this, findObjectSwaps(type), findChildObjectSwaps(type));
3869         }
3870      }
3871      if (waitForInit)
3872         cm.waitForInit();
3873      return cm;
3874   }
3875
3876   /**
3877    * Used to resolve <c>ClassMetas</c> of type <c>Collection</c> and <c>Map</c> that have
3878    * <c>ClassMeta</c> values that themselves could be collections or maps.
3879    *
3880    * <p>
3881    * <c>Collection</c> meta objects are assumed to be followed by zero or one meta objects indicating the element type.
3882    *
3883    * <p>
3884    * <c>Map</c> meta objects are assumed to be followed by zero or two meta objects indicating the key and value types.
3885    *
3886    * <p>
3887    * The array can be arbitrarily long to indicate arbitrarily complex data structures.
3888    *
3889    * <h5 class='section'>Examples:</h5>
3890    * <ul>
3891    *    <li><code>getClassMeta(String.<jk>class</jk>);</code> - A normal type.
3892    *    <li><code>getClassMeta(List.<jk>class</jk>);</code> - A list containing objects.
3893    *    <li><code>getClassMeta(List.<jk>class</jk>, String.<jk>class</jk>);</code> - A list containing strings.
3894    *    <li><code>getClassMeta(LinkedList.<jk>class</jk>, String.<jk>class</jk>);</code> - A linked-list containing
3895    *       strings.
3896    *    <li><code>getClassMeta(LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);</code> -
3897    *       A linked-list containing linked-lists of strings.
3898    *    <li><code>getClassMeta(Map.<jk>class</jk>);</code> - A map containing object keys/values.
3899    *    <li><code>getClassMeta(Map.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);</code> - A map
3900    *       containing string keys/values.
3901    *    <li><code>getClassMeta(Map.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);</code> -
3902    *       A map containing string keys and values of lists containing beans.
3903    * </ul>
3904    *
3905    * @param <T>
3906    *    The class to resolve.
3907    * @param type
3908    *    The class to resolve.
3909    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
3910    * @param args
3911    *    The type arguments of the class if it's a collection or map.
3912    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
3913    *    <br>Ignored if the main type is not a map or collection.
3914    * @return The resolved class meta.
3915    */
3916   public final <T> ClassMeta<T> getClassMeta(Type type, Type...args) {
3917      if (type == null)
3918         return null;
3919      ClassMeta<T> cm = type instanceof Class ? getClassMeta((Class)type) : resolveClassMeta(type, null);
3920      if (args.length == 0)
3921         return cm;
3922      ClassMeta<?>[] cma = new ClassMeta[args.length+1];
3923      cma[0] = cm;
3924      for (int i = 0; i < Array.getLength(args); i++) {
3925         Type arg = (Type)Array.get(args, i);
3926         cma[i+1] = arg instanceof Class ? getClassMeta((Class)arg) : resolveClassMeta(arg, null);
3927      }
3928      return (ClassMeta<T>) getTypedClassMeta(cma, 0);
3929   }
3930
3931   /*
3932    * Resolves the 'genericized' class meta at the specified position in the ClassMeta array.
3933    */
3934   private ClassMeta<?> getTypedClassMeta(ClassMeta<?>[] c, int pos) {
3935      ClassMeta<?> cm = c[pos++];
3936      if (cm.isCollection() || cm.isOptional()) {
3937         ClassMeta<?> ce = c.length == pos ? object() : getTypedClassMeta(c, pos);
3938         return (ce.isObject() ? cm : new ClassMeta(cm, null, null, ce));
3939      } else if (cm.isMap()) {
3940         ClassMeta<?> ck = c.length == pos ? object() : c[pos++];
3941         ClassMeta<?> cv = c.length == pos ? object() : getTypedClassMeta(c, pos);
3942         return (ck.isObject() && cv.isObject() ? cm : new ClassMeta(cm, ck, cv, null));
3943      }
3944      return cm;
3945   }
3946
3947   final ClassMeta resolveClassMeta(Type o, Map<Class<?>,Class<?>[]> typeVarImpls) {
3948      if (o == null)
3949         return null;
3950
3951      if (o instanceof ClassMeta) {
3952         ClassMeta<?> cm = (ClassMeta)o;
3953
3954         // This classmeta could have been created by a different context.
3955         // Need to re-resolve it to pick up ObjectSwaps and stuff on this context.
3956         if (cm.getBeanContext() == this)
3957            return cm;
3958         if (cm.isMap())
3959            return getClassMeta(cm.innerClass, cm.getKeyType(), cm.getValueType());
3960         if (cm.isCollection() || cm.isOptional())
3961            return getClassMeta(cm.innerClass, cm.getElementType());
3962         return getClassMeta(cm.innerClass);
3963      }
3964
3965      Class c = resolve(o, typeVarImpls);
3966
3967      // This can happen when trying to resolve the "E getFirst()" method on LinkedList, whose type is a TypeVariable
3968      // These should just resolve to Object.
3969      if (c == null)
3970         return object();
3971
3972      ClassMeta rawType = getClassMeta(c);
3973
3974      // If this is a Map or Collection, and the parameter types aren't part
3975      // of the class definition itself (e.g. class AddressBook extends List<Person>),
3976      // then we need to figure out the parameters.
3977      if (rawType.isMap() || rawType.isCollection() || rawType.isOptional()) {
3978         ClassMeta[] params = findParameters(o, c);
3979         if (params == null)
3980            return rawType;
3981         if (rawType.isMap()) {
3982            if (params.length != 2 || (params[0].isObject() && params[1].isObject()))
3983               return rawType;
3984            return new ClassMeta(rawType, params[0], params[1], null);
3985         }
3986         if (rawType.isCollection() || rawType.isOptional()) {
3987            if (params.length != 1 || params[0].isObject())
3988               return rawType;
3989            return new ClassMeta(rawType, null, null, params[0]);
3990         }
3991      }
3992
3993      if (rawType.isArray()) {
3994         if (o instanceof GenericArrayType) {
3995            GenericArrayType gat = (GenericArrayType)o;
3996            ClassMeta elementType = resolveClassMeta(gat.getGenericComponentType(), typeVarImpls);
3997            return new ClassMeta(rawType, null, null, elementType);
3998         }
3999      }
4000
4001      return rawType;
4002   }
4003
4004   /**
4005    * Convert a Type to a Class if possible.
4006    * Return null if not possible.
4007    */
4008   final Class resolve(Type t, Map<Class<?>,Class<?>[]> typeVarImpls) {
4009
4010      if (t instanceof Class)
4011         return (Class)t;
4012
4013      if (t instanceof ParameterizedType)
4014         // A parameter (e.g. <String>.
4015         return (Class)((ParameterizedType)t).getRawType();
4016
4017      if (t instanceof GenericArrayType) {
4018         // An array parameter (e.g. <byte[]>).
4019         Type gatct = ((GenericArrayType)t).getGenericComponentType();
4020
4021         if (gatct instanceof Class)
4022            return Array.newInstance((Class)gatct, 0).getClass();
4023
4024         if (gatct instanceof ParameterizedType)
4025            return Array.newInstance((Class)((ParameterizedType)gatct).getRawType(), 0).getClass();
4026
4027         if (gatct instanceof GenericArrayType)
4028            return Array.newInstance(resolve(gatct, typeVarImpls), 0).getClass();
4029
4030         return null;
4031
4032      } else if (t instanceof TypeVariable) {
4033         if (typeVarImpls != null) {
4034            TypeVariable tv = (TypeVariable)t;
4035            String varName = tv.getName();
4036            int varIndex = -1;
4037            Class gc = (Class)tv.getGenericDeclaration();
4038            TypeVariable[] tvv = gc.getTypeParameters();
4039            for (int i = 0; i < tvv.length; i++) {
4040               if (tvv[i].getName().equals(varName)) {
4041                  varIndex = i;
4042               }
4043            }
4044            if (varIndex != -1) {
4045
4046               // If we couldn't find a type variable implementation, that means
4047               // the type was defined at runtime (e.g. Bean b = new Bean<Foo>();)
4048               // in which case the type is lost through erasure.
4049               // Assume java.lang.Object as the type.
4050               if (! typeVarImpls.containsKey(gc))
4051                  return null;
4052
4053               return typeVarImpls.get(gc)[varIndex];
4054            }
4055         }
4056      }
4057      return null;
4058   }
4059
4060   final ClassMeta[] findParameters(Type o, Class c) {
4061      if (o == null)
4062         o = c;
4063
4064      // Loop until we find a ParameterizedType
4065      if (! (o instanceof ParameterizedType)) {
4066         loop: do {
4067            o = c.getGenericSuperclass();
4068            if (o instanceof ParameterizedType)
4069               break loop;
4070            for (Type t : c.getGenericInterfaces()) {
4071               o = t;
4072               if (o instanceof ParameterizedType)
4073                  break loop;
4074            }
4075            c = c.getSuperclass();
4076         } while (c != null);
4077      }
4078
4079      if (o instanceof ParameterizedType) {
4080         ParameterizedType pt = (ParameterizedType)o;
4081         if (! pt.getRawType().equals(Enum.class)) {
4082            List<ClassMeta<?>> l = new LinkedList<>();
4083            for (Type pt2 : pt.getActualTypeArguments()) {
4084               if (pt2 instanceof WildcardType || pt2 instanceof TypeVariable)
4085                  return null;
4086               l.add(resolveClassMeta(pt2, null));
4087            }
4088            if (l.isEmpty())
4089               return null;
4090            return l.toArray(new ClassMeta[l.size()]);
4091         }
4092      }
4093
4094      return null;
4095   }
4096
4097   /**
4098    * Shortcut for calling {@code getClassMeta(o.getClass())}.
4099    *
4100    * @param <T> The class of the object being passed in.
4101    * @param o The class to find the class type for.
4102    * @return The ClassMeta object, or <jk>null</jk> if {@code o} is <jk>null</jk>.
4103    */
4104   public final <T> ClassMeta<T> getClassMetaForObject(T o) {
4105      if (o == null)
4106         return null;
4107      return (ClassMeta<T>)getClassMeta(o.getClass());
4108   }
4109
4110
4111   /**
4112    * Used for determining the class type on a method or field where a {@code @Beanp} annotation may be present.
4113    *
4114    * @param <T> The class type we're wrapping.
4115    * @param p The property annotation on the type if there is one.
4116    * @param t The type.
4117    * @param typeVarImpls
4118    *    Contains known resolved type parameters on the specified class so that we can result
4119    *    {@code ParameterizedTypes} and {@code TypeVariables}.
4120    *    Can be <jk>null</jk> if the information is not known.
4121    * @return The new {@code ClassMeta} object wrapped around the {@code Type} object.
4122    */
4123   protected final <T> ClassMeta<T> resolveClassMeta(Beanp p, Type t, Map<Class<?>,Class<?>[]> typeVarImpls) {
4124      ClassMeta<T> cm = resolveClassMeta(t, typeVarImpls);
4125      ClassMeta<T> cm2 = cm;
4126
4127      if (p != null) {
4128
4129         if (isNotVoid(p.type()))
4130            cm2 = resolveClassMeta(p.type(), typeVarImpls);
4131
4132         if (cm2.isMap()) {
4133            Class<?>[] pParams = (p.params().length == 0 ? new Class[]{Object.class, Object.class} : p.params());
4134            if (pParams.length != 2)
4135               throw new BasicRuntimeException("Invalid number of parameters specified for Map (must be 2): {0}", pParams.length);
4136            ClassMeta<?> keyType = resolveType(pParams[0], cm2.getKeyType(), cm.getKeyType());
4137            ClassMeta<?> valueType = resolveType(pParams[1], cm2.getValueType(), cm.getValueType());
4138            if (keyType.isObject() && valueType.isObject())
4139               return cm2;
4140            return new ClassMeta<>(cm2, keyType, valueType, null);
4141         }
4142
4143         if (cm2.isCollection() || cm2.isOptional()) {
4144            Class<?>[] pParams = (p.params().length == 0 ? new Class[]{Object.class} : p.params());
4145            if (pParams.length != 1)
4146               throw new BasicRuntimeException("Invalid number of parameters specified for {1} (must be 1): {0}", pParams.length, (cm2.isCollection() ? "Collection" : cm2.isOptional() ? "Optional" : "Array"));
4147            ClassMeta<?> elementType = resolveType(pParams[0], cm2.getElementType(), cm.getElementType());
4148            if (elementType.isObject())
4149               return cm2;
4150            return new ClassMeta<>(cm2, null, null, elementType);
4151         }
4152
4153         return cm2;
4154      }
4155
4156      return cm;
4157   }
4158
4159   private ClassMeta<?> resolveType(Type...t) {
4160      for (Type tt : t) {
4161         if (tt != null) {
4162            ClassMeta<?> cm = getClassMeta(tt);
4163            if (tt != cmObject)
4164               return cm;
4165         }
4166      }
4167      return cmObject;
4168   }
4169
4170   /**
4171    * Returns the {@link ObjectSwap} associated with the specified class, or <jk>null</jk> if there is no POJO swap
4172    * associated with the class.
4173    *
4174    * @param <T> The class associated with the swap.
4175    * @param c The class associated with the swap.
4176    * @return The swap associated with the class, or null if there is no association.
4177    */
4178   private final <T> ObjectSwap[] findObjectSwaps(Class<T> c) {
4179      // Note:  On first
4180      if (c != null) {
4181         List<ObjectSwap> l = list();
4182         for (ObjectSwap f : swapArray)
4183            if (f.getNormalClass().isParentOf(c))
4184               l.add(f);
4185         return l.size() == 0 ? null : l.toArray(new ObjectSwap[l.size()]);
4186      }
4187      return null;
4188   }
4189
4190   /**
4191    * Checks whether a class has a {@link ObjectSwap} associated with it in this bean context.
4192    *
4193    * @param c The class to check.
4194    * @return <jk>true</jk> if the specified class or one of its subclasses has a {@link ObjectSwap} associated with it.
4195    */
4196   private final ObjectSwap[] findChildObjectSwaps(Class<?> c) {
4197      if (c == null || swapArray.length == 0)
4198         return null;
4199      List<ObjectSwap> l = null;
4200      for (ObjectSwap f : swapArray) {
4201         if (f.getNormalClass().isChildOf(c)) {
4202            if (l == null)
4203               l = list();
4204            l.add(f);
4205         }
4206      }
4207      return l == null ? null : l.toArray(new ObjectSwap[l.size()]);
4208   }
4209
4210   /**
4211    * Returns a reusable {@link ClassMeta} representation for the class <c>Object</c>.
4212    *
4213    * <p>
4214    * This <c>ClassMeta</c> is often used to represent "any object type" when an object type is not known.
4215    *
4216    * <p>
4217    * This method is identical to calling <code>getClassMeta(Object.<jk>class</jk>)</code> but uses a cached copy to
4218    * avoid a hashmap lookup.
4219    *
4220    * @return The {@link ClassMeta} object associated with the <c>Object</c> class.
4221    */
4222   protected final ClassMeta<Object> object() {
4223      return cmObject;
4224   }
4225
4226   /**
4227    * Returns a reusable {@link ClassMeta} representation for the class <c>String</c>.
4228    *
4229    * <p>
4230    * This <c>ClassMeta</c> is often used to represent key types in maps.
4231    *
4232    * <p>
4233    * This method is identical to calling <code>getClassMeta(String.<jk>class</jk>)</code> but uses a cached copy to
4234    * avoid a hashmap lookup.
4235    *
4236    * @return The {@link ClassMeta} object associated with the <c>String</c> class.
4237    */
4238   protected final ClassMeta<String> string() {
4239      return cmString;
4240   }
4241
4242   /**
4243    * Returns a reusable {@link ClassMeta} representation for the class <c>Class</c>.
4244    *
4245    * <p>
4246    * This <c>ClassMeta</c> is often used to represent key types in maps.
4247    *
4248    * <p>
4249    * This method is identical to calling <code>getClassMeta(Class.<jk>class</jk>)</code> but uses a cached copy to
4250    * avoid a hashmap lookup.
4251    *
4252    * @return The {@link ClassMeta} object associated with the <c>String</c> class.
4253    */
4254   protected final ClassMeta<Class> _class() {
4255      return cmClass;
4256   }
4257
4258   /**
4259    * Returns the lookup table for resolving bean types by name.
4260    *
4261    * @return The lookup table for resolving bean types by name.
4262    */
4263   protected final BeanRegistry getBeanRegistry() {
4264      return beanRegistry;
4265   }
4266
4267   //-----------------------------------------------------------------------------------------------------------------
4268   // Properties
4269   //-----------------------------------------------------------------------------------------------------------------
4270
4271   /**
4272    * Minimum bean class visibility.
4273    *
4274    * @see BeanContext.Builder#beanClassVisibility(Visibility)
4275    * @return
4276    *    Classes are not considered beans unless they meet the minimum visibility requirements.
4277    */
4278   public final Visibility getBeanClassVisibility() {
4279      return beanClassVisibility;
4280   }
4281
4282   /**
4283    * Minimum bean constructor visibility.
4284    *
4285    * @see BeanContext.Builder#beanConstructorVisibility(Visibility)
4286    * @return
4287    *    Only look for constructors with this specified minimum visibility.
4288    */
4289   public final Visibility getBeanConstructorVisibility() {
4290      return beanConstructorVisibility;
4291   }
4292
4293   /**
4294    * Bean dictionary.
4295    *
4296    * @see BeanContext.Builder#beanDictionary()
4297    * @return
4298    *    The list of classes that make up the bean dictionary in this bean context.
4299    */
4300   public final List<Class<?>> getBeanDictionary() {
4301      return beanDictionary;
4302   }
4303
4304   /**
4305    * Minimum bean field visibility.
4306    *
4307    *
4308    * @see BeanContext.Builder#beanFieldVisibility(Visibility)
4309    * @return
4310    *    Only look for bean fields with this specified minimum visibility.
4311    */
4312   public final Visibility getBeanFieldVisibility() {
4313      return beanFieldVisibility;
4314   }
4315
4316   /**
4317    * BeanMap.put() returns old property value.
4318    *
4319    * @see BeanContext.Builder#beanMapPutReturnsOldValue()
4320    * @return
4321    *    <jk>true</jk> if the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property values.
4322    *    <br>Otherwise, it returns <jk>null</jk>.
4323    */
4324   public final boolean isBeanMapPutReturnsOldValue() {
4325      return beanMapPutReturnsOldValue;
4326   }
4327
4328   /**
4329    * Minimum bean method visibility.
4330    *
4331    * @see BeanContext.Builder#beanMethodVisibility(Visibility)
4332    * @return
4333    *    Only look for bean methods with this specified minimum visibility.
4334    */
4335   public final Visibility getBeanMethodVisibility() {
4336      return beanMethodVisibility;
4337   }
4338
4339   /**
4340    * Beans require no-arg constructors.
4341    *
4342    * @see BeanContext.Builder#beansRequireDefaultConstructor()
4343    * @return
4344    *    <jk>true</jk> if a Java class must implement a default no-arg constructor to be considered a bean.
4345    *    <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method.
4346    */
4347   public final boolean isBeansRequireDefaultConstructor() {
4348      return beansRequireDefaultConstructor;
4349   }
4350
4351   /**
4352    * Beans require Serializable interface.
4353    *
4354    * @see BeanContext.Builder#beansRequireSerializable()
4355    * @return
4356    *    <jk>true</jk> if a Java class must implement the {@link Serializable} interface to be considered a bean.
4357    *    <br>Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method.
4358    */
4359   public final boolean isBeansRequireSerializable() {
4360      return beansRequireSerializable;
4361   }
4362
4363   /**
4364    * Beans require setters for getters.
4365    *
4366    * @see BeanContext.Builder#beansRequireSettersForGetters()
4367    * @return
4368    *    <jk>true</jk> if only getters that have equivalent setters will be considered as properties on a bean.
4369    *    <br>Otherwise, they are ignored.
4370    */
4371   public final boolean isBeansRequireSettersForGetters() {
4372      return beansRequireSettersForGetters;
4373   }
4374
4375   /**
4376    * Beans require at least one property.
4377    *
4378    * @see BeanContext.Builder#disableBeansRequireSomeProperties()
4379    * @return
4380    *    <jk>true</jk> if a Java class doesn't need to contain at least 1 property to be considered a bean.
4381    *    <br>Otherwise, the bean is serialized as a string using the {@link Object#toString()} method.
4382    */
4383   public final boolean isBeansRequireSomeProperties() {
4384      return beansRequireSomeProperties;
4385   }
4386
4387   /**
4388    * Bean type property name.
4389    *
4390    * @see BeanContext.Builder#typePropertyName(String)
4391    * @return
4392    * The name of the bean property used to store the dictionary name of a bean type so that the parser knows the data type to reconstruct.
4393    */
4394   public final String getBeanTypePropertyName() {
4395      return typePropertyName;
4396   }
4397
4398   /**
4399    * Find fluent setters.
4400    *
4401    * <h5 class='section'>Description:</h5>
4402    * <p>
4403    *
4404    * @see BeanContext.Builder#findFluentSetters()
4405    * @return
4406    *    <jk>true</jk> if fluent setters are detected on beans.
4407    */
4408   public final boolean isFindFluentSetters() {
4409      return findFluentSetters;
4410   }
4411
4412   /**
4413    * Ignore invocation errors on getters.
4414    *
4415    * @see BeanContext.Builder#ignoreInvocationExceptionsOnGetters()
4416    * @return
4417    *    <jk>true</jk> if errors thrown when calling bean getter methods are silently ignored.
4418    */
4419   public final boolean isIgnoreInvocationExceptionsOnGetters() {
4420      return ignoreInvocationExceptionsOnGetters;
4421   }
4422
4423   /**
4424    * Ignore invocation errors on setters.
4425    *
4426    * @see BeanContext.Builder#ignoreInvocationExceptionsOnSetters()
4427    * @return
4428    *    <jk>true</jk> if errors thrown when calling bean setter methods are silently ignored.
4429    */
4430   public final boolean isIgnoreInvocationExceptionsOnSetters() {
4431      return ignoreInvocationExceptionsOnSetters;
4432   }
4433
4434   /**
4435    * Silently ignore missing setters.
4436    *
4437    * @see BeanContext.Builder#disableIgnoreMissingSetters()
4438    * @return
4439    *    <jk>true</jk> if trying to set a value on a bean property without a setter should throw a {@link BeanRuntimeException}.
4440    */
4441   public final boolean isIgnoreMissingSetters() {
4442      return ignoreMissingSetters;
4443   }
4444
4445   /**
4446    * Ignore transient fields.
4447    *
4448    * @see BeanContext.Builder#disableIgnoreTransientFields()
4449    * @return
4450    *    <jk>true</jk> if fields and methods marked as transient should not be ignored.
4451    */
4452   protected final boolean isIgnoreTransientFields() {
4453      return ignoreTransientFields;
4454   }
4455
4456   /**
4457    * Ignore unknown properties.
4458    *
4459    * @see BeanContext.Builder#ignoreUnknownBeanProperties()
4460    * @return
4461    *    <jk>true</jk> if trying to set a value on a non-existent bean property is silently ignored.
4462    *    <br>Otherwise, a {@code RuntimeException} is thrown.
4463    */
4464   public final boolean isIgnoreUnknownBeanProperties() {
4465      return ignoreUnknownBeanProperties;
4466   }
4467
4468   /**
4469    * Ignore unknown enum values.
4470    *
4471    * @see BeanContext.Builder#ignoreUnknownEnumValues()
4472    * @return
4473    *    <jk>true</jk> if unknown enum values should be set as <jk>null</jk> instead of throwing an exception.
4474    */
4475   public final boolean isIgnoreUnknownEnumValues() {
4476      return ignoreUnknownEnumValues;
4477   }
4478
4479   /**
4480    * Ignore unknown properties with null values.
4481    *
4482    * @see BeanContext.Builder#disableIgnoreUnknownNullBeanProperties()
4483    * @return
4484    *    <jk>true</jk> if trying to set a <jk>null</jk> value on a non-existent bean property should throw a {@link BeanRuntimeException}.
4485    */
4486   public final boolean isIgnoreUnknownNullBeanProperties() {
4487      return ignoreUnknownNullBeanProperties;
4488   }
4489
4490   /**
4491    * Bean class exclusions.
4492    *
4493    * @see BeanContext.Builder#notBeanClasses(Class...)
4494    * @return
4495    *    The list of classes that are explicitly not beans.
4496    */
4497   protected final Class<?>[] getNotBeanClasses() {
4498      return notBeanClassesArray;
4499   }
4500
4501   /**
4502    * Bean package exclusions.
4503    *
4504    * @see BeanContext.Builder#notBeanPackages(String...)
4505    * @return
4506    *    The list of fully-qualified package names to exclude from being classified as beans.
4507    */
4508   public final String[] getNotBeanPackagesNames() {
4509      return notBeanPackageNames;
4510   }
4511
4512   /**
4513    * Bean package exclusions.
4514    *
4515    * @see BeanContext.Builder#notBeanPackages(String...)
4516    * @return
4517    *    The list of package name prefixes to exclude from being classified as beans.
4518    */
4519   protected final String[] getNotBeanPackagesPrefixes() {
4520      return notBeanPackagePrefixes;
4521   }
4522
4523   /**
4524    * Java object swaps.
4525    *
4526    * @see BeanContext.Builder#swaps(Class...)
4527    * @return
4528    *    The list POJO swaps defined.
4529    */
4530   public final ObjectSwap<?,?>[] getSwaps() {
4531      return swapArray;
4532   }
4533
4534   /**
4535    * Bean property namer.
4536    *
4537    * @see BeanContext.Builder#propertyNamer(Class)
4538    * @return
4539    *    The interface used to calculate bean property names.
4540    */
4541   public final PropertyNamer getPropertyNamer() {
4542      return propertyNamerBean;
4543   }
4544
4545   /**
4546    * Sort bean properties.
4547    *
4548    * @see BeanContext.Builder#sortProperties()
4549    * @return
4550    *    <jk>true</jk> if all bean properties will be serialized and access in alphabetical order.
4551    */
4552   public final boolean isSortProperties() {
4553      return sortProperties;
4554   }
4555
4556   /**
4557    * Use enum names.
4558    *
4559    * @see BeanContext.Builder#useEnumNames()
4560    * @return
4561    *    <jk>true</jk> if enums are always serialized by name, not using {@link Object#toString()}.
4562    */
4563   public final boolean isUseEnumNames() {
4564      return useEnumNames;
4565   }
4566
4567   /**
4568    * Use interface proxies.
4569    *
4570    * @see BeanContext.Builder#disableInterfaceProxies()
4571    * @return
4572    *    <jk>true</jk> if interfaces will be instantiated as proxy classes through the use of an
4573    *    {@link InvocationHandler} if there is no other way of instantiating them.
4574    */
4575   public final boolean isUseInterfaceProxies() {
4576      return useInterfaceProxies;
4577   }
4578
4579   /**
4580    * Use Java Introspector.
4581    *
4582    * @see BeanContext.Builder#useJavaBeanIntrospector()
4583    * @return
4584    *    <jk>true</jk> if the built-in Java bean introspector should be used for bean introspection.
4585    */
4586   public final boolean isUseJavaBeanIntrospector() {
4587      return useJavaBeanIntrospector;
4588   }
4589
4590   /**
4591    * Locale.
4592    *
4593    * @see BeanContext.Builder#locale(Locale)
4594    * @return
4595    *    The default locale for serializer and parser sessions.
4596    */
4597   public final Locale getDefaultLocale() {
4598      return locale;
4599   }
4600
4601   /**
4602    * Media type.
4603    *
4604    * @see BeanContext.Builder#mediaType(MediaType)
4605    * @return
4606    *    The default media type value for serializer and parser sessions.
4607    */
4608   public final MediaType getDefaultMediaType() {
4609      return mediaType;
4610   }
4611
4612   /**
4613    * Time zone.
4614    *
4615    * @see BeanContext.Builder#timeZone(TimeZone)
4616    * @return
4617    *    The default timezone for serializer and parser sessions.
4618    */
4619   public final TimeZone getDefaultTimeZone() {
4620      return timeZone;
4621   }
4622
4623   /**
4624    * Returns the serializer to use for serializing beans when using the {@link BeanSession#convertToType(Object, Class)}
4625    * and related methods.
4626    *
4627    * @return The serializer.  May be <jk>null</jk> if all initialization has occurred.
4628    */
4629   protected WriterSerializer getBeanToStringSerializer() {
4630      if (beanToStringSerializer == null) {
4631         if (JsonSerializer.DEFAULT == null)
4632            return null;
4633         this.beanToStringSerializer = JsonSerializer.create().beanContext(this).sq().simpleAttrs().build();
4634      }
4635      return beanToStringSerializer;
4636   }
4637
4638   //-----------------------------------------------------------------------------------------------------------------
4639   // Other methods
4640   //-----------------------------------------------------------------------------------------------------------------
4641
4642   @Override /* Context */
4643   protected JsonMap properties() {
4644      return filteredMap()
4645         .append("id", System.identityHashCode(this))
4646         .append("beanClassVisibility", beanClassVisibility)
4647         .append("beanConstructorVisibility", beanConstructorVisibility)
4648         .append("beanDictionary", beanDictionary)
4649         .append("beanFieldVisibility", beanFieldVisibility)
4650         .append("beanMethodVisibility", beanMethodVisibility)
4651         .append("beansRequireDefaultConstructor", beansRequireDefaultConstructor)
4652         .append("beansRequireSerializable", beansRequireSerializable)
4653         .append("beansRequireSettersForGetters", beansRequireSettersForGetters)
4654         .append("beansRequireSomeProperties", beansRequireSomeProperties)
4655         .append("ignoreTransientFields", ignoreTransientFields)
4656         .append("ignoreInvocationExceptionsOnGetters", ignoreInvocationExceptionsOnGetters)
4657         .append("ignoreInvocationExceptionsOnSetters", ignoreInvocationExceptionsOnSetters)
4658         .append("ignoreUnknownBeanProperties", ignoreUnknownBeanProperties)
4659         .append("ignoreUnknownNullBeanProperties", ignoreUnknownNullBeanProperties)
4660         .append("notBeanClasses", notBeanClasses)
4661         .append("notBeanPackageNames", notBeanPackageNames)
4662         .append("notBeanPackagePrefixes", notBeanPackagePrefixes)
4663         .append("swaps", swaps)
4664         .append("sortProperties", sortProperties)
4665         .append("useEnumNames", useEnumNames)
4666         .append("useInterfaceProxies", useInterfaceProxies)
4667         .append("useJavaBeanIntrospector", useJavaBeanIntrospector);
4668   }
4669}