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