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