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