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