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