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