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