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