Repository: incubator-juneau
Updated Branches:
  refs/heads/master b37d99bac -> 75b0d8ee6


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
new file mode 100644
index 0000000..70ffaf3
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
@@ -0,0 +1,1776 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau;
+
+import static org.apache.juneau.Visibility.*;
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.beans.*;
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.transform.*;
+
+/**
+ * Core class of the Juneau architecture.
+ *
+ * <p>
+ * This class servers multiple purposes:
+ * <ul class='spaced-list'>
+ *     <li>
+ *             Provides the ability to wrap beans inside {@link Map} 
interfaces.
+ *     <li>
+ *             Serves as a repository for metadata on POJOs, such as 
associated {@link BeanFilter beanFilters},
+ *             {@link PropertyNamer property namers}, etc...  which are used 
to tailor how POJOs are serialized and parsed.
+ *     <li>
+ *             Serves as a common utility class for all {@link Serializer 
Serializers} and {@link Parser Parsers}
+ *             for serializing and parsing Java beans.
+ * </ul>
+ *
+ * <p>
+ * All serializer and parser contexts extend from this context.
+ *
+ * <h5 class='topic'>Bean Contexts</h5>
+ *
+ * Bean contexts are created through the {@link 
PropertyStore#getContext(Class)} method.
+ * These context objects are read-only, reusable, and thread-safe.
+ * The {@link PropertyStore} class will typically cache copies of 
<code>Context</code> objects based on
+ * the current settings on the factory.
+ *
+ * <p>
+ * Each bean context maintains a cache of {@link ClassMeta} objects that 
describe information about classes encountered.
+ * These <code>ClassMeta</code> objects are time-consuming to construct.
+ * Therefore, instances of {@link BeanContext} that share the same 
<js>"BeanContext.*"</js> property values share
+ * the same cache.  This allows for efficient reuse of <code>ClassMeta</code> 
objects so that the information about
+ * classes only needs to be calculated once.
+ * Because of this, many of the properties defined on the {@link BeanContext} 
class cannot be overridden on the session.
+ *
+ * <h5 class='topic'>Bean Sessions</h5>
+ *
+ * Whereas <code>BeanContext</code> objects are permanent, unchangeable, 
cached, and thread-safe,
+ * {@link BeanSession} objects are ephemeral and not thread-safe.
+ * They are meant to be used as quickly-constructed scratchpads for creating 
bean maps.
+ * {@link BeanMap} objects can only be created through the session.
+ *
+ * <h5 class='topic'>BeanContext configuration properties</h5>
+ *
+ * <code>BeanContexts</code> have several configuration properties that can be 
used to tweak behavior on how beans are
+ * handled.  These are denoted as the static <jsf>BEAN_*</jsf> fields on this 
class.
+ *
+ * <p>
+ * Some settings (e.g. {@link 
BeanContext#BEAN_beansRequireDefaultConstructor}) are used to differentiate 
between bean
+ * and non-bean classes.
+ * Attempting to create a bean map around one of these objects will throw a 
{@link BeanRuntimeException}.
+ * The purpose for this behavior is so that the serializers can identify these 
non-bean classes and convert them to
+ * plain strings using the {@link Object#toString()} method.
+ *
+ * <p>
+ * Some settings (e.g. {@link BeanContext#BEAN_beanFieldVisibility}) are used 
to determine what kinds of properties are
+ * detected on beans.
+ *
+ * <p>
+ * Some settings (e.g. {@link BeanContext#BEAN_beanMapPutReturnsOldValue}) 
change the runtime behavior of bean maps.
+ *
+ * <p>
+ * Settings are specified using the {@link PropertyStore#setProperty(String, 
Object)} method and related convenience
+ * methods.
+ *
+ * <h5 class='section'>Example:</h5>
+ *
+ * <p class='bcode'>
+ *     <jc>// Construct a context from scratch.</jc>
+ *     BeanContext beanContext = PropertyStore.<jsm>create</jsm>()
+ *             
.property(BeanContext.<jsf>BEAN_beansRequireDefaultConstructor</jsf>, 
<jk>true</jk>)
+ *             .notBeanClasses(Foo.<jk>class</jk>)
+ *             .getBeanContext();
+ *
+ *     <jc>// Clone an existing property store.</jc>
+ *     BeanContext beanContext = PropertyStore.<jsm>create</jsm>(otherConfig)
+ *             
.property(BeanContext.<jsf>BEAN_beansRequireDefaultConstructor</jsf>, 
<jk>true</jk>)
+ *             .notBeanClasses(Foo.<jk>class</jk>)
+ *             .getBeanContext();
+ * </p>
+ *
+ * <h5 class='topic'>Bean Maps</h5>
+ *
+ * {@link BeanMap BeanMaps} are wrappers around Java beans that allow 
properties to be retrieved and
+ * set using the common {@link Map#put(Object,Object)} and {@link 
Map#get(Object)} methods.
+ *
+ * <p>
+ * Bean maps are created in two ways...
+ * <ol>
+ *     <li>{@link BeanSession#toBeanMap(Object) BeanSession.toBeanMap()} - 
Wraps an existing bean inside a {@code Map}
+ *             wrapper.
+ *     <li>{@link BeanSession#newBeanMap(Class) BeanSession.newBeanMap()} - 
Create a new bean instance wrapped in a
+ *             {@code Map} wrapper.
+ * </ol>
+ *
+ * <h5 class='section'>Example:</h5>
+ *
+ * <p class='bcode'>
+ *     <jc>// A sample bean class</jc>
+ *     <jk>public class</jk> Person {
+ *             <jk>public</jk> String getName();
+ *             <jk>public void</jk> setName(String name);
+ *             <jk>public int</jk> getAge();
+ *             <jk>public void</jk> setAge(<jk>int</jk> age);
+ *     }
+ *
+ *     <jc>// Create a new bean session</jc>
+ *     BeanSession session = BeanContext.<jsf>DEFAULT</jsf>.createSession();
+ *
+ *     <jc>// Wrap an existing bean in a new bean map</jc>
+ *     BeanMap&lt;Person&gt; m1 = session.toBeanMap(<jk>new</jk> Person());
+ *     m1.put(<js>"name"</js>, <js>"John Smith"</js>);
+ *     m1.put(<js>"age"</js>, 45);
+ *
+ *     <jc>// Create a new bean instance wrapped in a new bean map</jc>
+ *     BeanMap&lt;Person&gt; m2 = session.newBeanMap(Person.<jk>class</jk>);
+ *     m2.put(<js>"name"</js>, <js>"John Smith"</js>);
+ *     m2.put(<js>"age"</js>, 45);
+ *     Person p = m2.getBean();  <jc>// Get the bean instance that was 
created.</jc>
+ * </p>
+ *
+ * <h5 class='topic'>Bean Annotations</h5>
+ *
+ * This package contains annotations that can be applied to class definitions 
to override what properties are detected
+ * on a bean.
+ *
+ * <h5 class='section'>Example:</h5>
+ *
+ * <p class='bcode'>
+ *     <jc>// Bean class definition where only property 'name' is 
detected.</jc>
+ *     <ja>&#64;Bean</ja>(properties=<js>"name"</js>)
+ *     <jk>public class</jk> Person {
+ *             <jk>public</jk> String getName();
+ *             <jk>public void</jk> setName(String name);
+ *             <jk>public int</jk> getAge();
+ *             <jk>public void</jk> setAge(<jk>int</jk> age);
+ *     }
+ * </p>
+ *
+ * <p>
+ * See {@link Bean @Bean} and {@link BeanProperty @BeanProperty} for more 
information.
+ *
+ * <h5 class='topic'>Beans with read-only properties</h5>
+ *
+ * Bean maps can also be defined on top of beans with read-only properties by 
adding a
+ * {@link BeanConstructor @BeanConstructor} annotation to one of the 
constructors on the
+ * bean class.  This will allow read-only properties to be set through 
constructor arguments.
+ *
+ * <p>
+ * When the <code>@BeanConstructor</code> annotation is present, bean 
instantiation is delayed until the call to
+ * {@link BeanMap#getBean()}.
+ * Until then, bean property values are stored in a local cache until 
<code>getBean()</code> is called.
+ * Because of this additional caching step, parsing into read-only beans tends 
to be slower and use more memory than
+ * parsing into beans with writable properties.
+ *
+ * <p>
+ * Attempting to call {@link BeanMap#put(String,Object)} on a read-only 
property after calling {@link BeanMap#getBean()}
+ * will result in a {@link BeanRuntimeException} being thrown.
+ * Multiple calls to {@link BeanMap#getBean()} will return the same bean 
instance.
+ *
+ * <p>
+ * Beans can be defined with a combination of read-only and read-write 
properties.
+ *
+ * <p>
+ * See {@link BeanConstructor @BeanConstructor} for more information.
+ *
+ * <h5 class='topic'>BeanFilters and PojoSwaps</h5>
+ *
+ *     {@link BeanFilter BeanFilters} and {@link PojoSwap PojoSwaps} are used 
to tailor how beans and POJOs are handled.
+ *     <ol class='spaced-list'>
+ *             <li>
+ *                     {@link BeanFilter} - Allows you to tailor handling of 
bean classes.
+ *                     This class can be considered a programmatic equivalent 
to the {@link Bean} annotation when
+ *                     annotating classes are not possible (e.g. you don't 
have access to the source).
+ *                     This includes specifying which properties are visible 
and the ability to programmatically override the
+ *                     execution of properties.
+ *             <li>
+ *                     {@link PojoSwap} - Allows you to swap out 
non-serializable objects with serializable replacements.
+ *     </ol>
+ *
+ * <p>
+ * See <a class='doclink' 
href='transform/package-summary.html#TOC'>org.apache.juneau.transform</a> for 
more
+ * information.
+ *
+ * <h5 class='topic'>ClassMetas</h5>
+ *
+ * The {@link ClassMeta} class is a wrapper around {@link Class} object that 
provides cached information about that
+ * class (e.g. whether it's a {@link Map} or {@link Collection} or bean).
+ *
+ * <p>
+ * As a general rule, it's best to reuse bean contexts (and therefore 
serializers and parsers too) whenever possible
+ * since it takes some time to populate the internal {@code ClassMeta} object 
cache.
+ * By reusing bean contexts, the class type metadata only needs to be 
calculated once which significantly improves
+ * performance.
+ *
+ * <p>
+ * See {@link ClassMeta} for more information.
+ */
+@SuppressWarnings({"unchecked","rawtypes"})
+public class BeanContext extends Context {
+
+       /**
+        * <b>Configuration property:</b>  Beans require no-arg constructors.
+        *
+        * <ul>
+        *      <li><b>Name:</b> 
<js>"BeanContext.beansRequireDefaultConstructor"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>false</jk>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * If <jk>true</jk>, a Java class must implement a default no-arg 
constructor to be considered a bean.
+        *
+        * <p>
+        * The {@link Bean @Bean} annotation can be used on a class to override 
this setting when <jk>true</jk>.
+        */
+       public static final String BEAN_beansRequireDefaultConstructor = 
"BeanContext.beansRequireDefaultConstructor";
+
+       /**
+        * <b>Configuration property:</b>  Beans require {@link Serializable} 
interface.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.beansRequireSerializable"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>false</jk>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * If <jk>true</jk>, a Java class must implement the {@link 
Serializable} interface to be considered a bean.
+        *
+        * <p>
+        * The {@link Bean @Bean} annotation can be used on a class to override 
this setting when <jk>true</jk>.
+        */
+       public static final String BEAN_beansRequireSerializable = 
"BeanContext.beansRequireSerializable";
+
+       /**
+        * <b>Configuration property:</b>  Beans require setters for getters.
+        *
+        * <ul>
+        *      <li><b>Name:</b> 
<js>"BeanContext.beansRequireSettersForGetters"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>false</jk>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * If <jk>true</jk>, only getters that have equivalent setters will be 
considered as properties on a bean.
+        * Otherwise, they will be ignored.
+        */
+       public static final String BEAN_beansRequireSettersForGetters = 
"BeanContext.beansRequireSettersForGetters";
+
+       /**
+        * <b>Configuration property:</b>  Beans require at least one property.
+        *
+        * <ul>
+        *      <li><b>Name:</b> 
<js>"BeanContext.beansRequireSomeProperties"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>true</jk>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * If <jk>true</jk>, then a Java class must contain at least 1 property 
to be considered a bean.
+        *
+        * <p>
+        * The {@link Bean @Bean} annotation can be used on a class to override 
this setting when <jk>true</jk>.
+        */
+       public static final String BEAN_beansRequireSomeProperties = 
"BeanContext.beansRequireSomeProperties";
+
+       /**
+        * <b>Configuration property:</b>  {@link BeanMap#put(String,Object) 
BeanMap.put()} method will return old property
+        * value.
+        *
+        * <ul>
+        *      <li><b>Name:</b> 
<js>"BeanContext.beanMapPutReturnsOldValue"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>false</jk>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * If <jk>true</jk>, then the {@link BeanMap#put(String,Object) 
BeanMap.put()} method will return old property
+        * values.
+        *
+        * <p>
+        * Disabled by default because it introduces a slight performance 
penalty.
+        */
+       public static final String BEAN_beanMapPutReturnsOldValue = 
"BeanContext.beanMapPutReturnsOldValue";
+
+       /**
+        * <b>Configuration property:</b>  Look for bean constructors with the 
specified minimum visibility.
+        *
+        * <ul>
+        *      <li><b>Name:</b> 
<js>"BeanContext.beanConstructorVisibility"</js>
+        *      <li><b>Data type:</b> {@link Visibility}
+        *      <li><b>Default:</b> {@link Visibility#PUBLIC}
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        */
+       public static final String BEAN_beanConstructorVisibility = 
"BeanContext.beanConstructorVisibility";
+
+       /**
+        * <b>Configuration property:</b>  Look for bean classes with the 
specified minimum visibility.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.beanClassVisibility"</js>
+        *      <li><b>Data type:</b> {@link Visibility}
+        *      <li><b>Default:</b> {@link Visibility#PUBLIC}
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * Classes are not considered beans unless they meet the minimum 
visibility requirements.
+        * For example, if the visibility is <code>PUBLIC</code> and the bean 
class is <jk>protected</jk>, then the class
+        * will not be interpreted as a bean class.
+        */
+       public static final String BEAN_beanClassVisibility = 
"BeanContext.beanClassVisibility";
+
+       /**
+        * <b>Configuration property:</b>  Look for bean fields with the 
specified minimum visibility.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.beanFieldVisibility"</js>
+        *      <li><b>Data type:</b> {@link Visibility}
+        *      <li><b>Default:</b> {@link Visibility#PUBLIC}
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * Fields are not considered bean properties unless they meet the 
minimum visibility requirements.
+        * For example, if the visibility is <code>PUBLIC</code> and the bean 
field is <jk>protected</jk>, then the field
+        * will not be interpreted as a bean property.
+        *
+        * <p>
+        * Use {@link Visibility#NONE} to prevent bean fields from being 
interpreted as bean properties altogether.
+        */
+       public static final String BEAN_beanFieldVisibility = 
"BeanContext.beanFieldVisibility";
+
+       /**
+        * <b>Configuration property:</b>  Look for bean methods with the 
specified minimum visibility.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.methodVisibility"</js>
+        *      <li><b>Data type:</b> {@link Visibility}
+        *      <li><b>Default:</b> {@link Visibility#PUBLIC}
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * Methods are not considered bean getters/setters unless they meet the 
minimum visibility requirements.
+        * For example, if the visibility is <code>PUBLIC</code> and the bean 
method is <jk>protected</jk>, then the method
+        * will not be interpreted as a bean getter or setter.
+        */
+       public static final String BEAN_methodVisibility = 
"BeanContext.methodVisibility";
+
+       /**
+        * <b>Configuration property:</b>  Use Java {@link Introspector} for 
determining bean properties.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.useJavaBeanIntrospector"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>false</jk>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * Using the built-in Java bean introspector will not pick up fields or 
non-standard getters/setters.
+        * Most {@link Bean @Bean} annotations will be ignored.
+        */
+       public static final String BEAN_useJavaBeanIntrospector = 
"BeanContext.useJavaBeanIntrospector";
+
+       /**
+        * <b>Configuration property:</b>  Use interface proxies.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.useInterfaceProxies"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>true</jk>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * If <jk>true</jk>, then interfaces will be instantiated as proxy 
classes through the use of an
+        * {@link InvocationHandler} if there is no other way of instantiating 
them.
+        */
+       public static final String BEAN_useInterfaceProxies = 
"BeanContext.useInterfaceProxies";
+
+       /**
+        * <b>Configuration property:</b>  Ignore unknown properties.
+        *
+        * <ul>
+        *      <li><b>Name:</b> 
<js>"BeanContext.ignoreUnknownBeanProperties"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>false</jk>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * If <jk>true</jk>, trying to set a value on a non-existent bean 
property will silently be ignored.
+        * Otherwise, a {@code RuntimeException} is thrown.
+        */
+       public static final String BEAN_ignoreUnknownBeanProperties = 
"BeanContext.ignoreUnknownBeanProperties";
+
+       /**
+        * <b>Configuration property:</b>  Ignore unknown properties with null 
values.
+        *
+        * <ul>
+        *      <li><b>Name:</b> 
<js>"BeanContext.ignoreUnknownNullBeanProperties"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>true</jk>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * If <jk>true</jk>, trying to set a <jk>null</jk> value on a 
non-existent bean property will silently be ignored.
+        * Otherwise, a {@code RuntimeException} is thrown.
+        */
+       public static final String BEAN_ignoreUnknownNullBeanProperties = 
"BeanContext.ignoreUnknownNullBeanProperties";
+
+       /**
+        * <b>Configuration property:</b>  Ignore properties without setters.
+        *
+        * <ul>
+        *      <li><b>Name:</b> 
<js>"BeanContext.ignorePropertiesWithoutSetters"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>true</jk>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * If <jk>true</jk>, trying to set a value on a bean property without a 
setter will silently be ignored.
+        * Otherwise, a {@code RuntimeException} is thrown.
+        */
+       public static final String BEAN_ignorePropertiesWithoutSetters = 
"BeanContext.ignorePropertiesWithoutSetters";
+
+       /**
+        * <b>Configuration property:</b>  Ignore invocation errors on getters.
+        *
+        * <ul>
+        *      <li><b>Name:</b> 
<js>"BeanContext.ignoreInvocationExceptionsOnGetters"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>false</jk>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * If <jk>true</jk>, errors thrown when calling bean getter methods 
will silently be ignored.
+        * Otherwise, a {@code BeanRuntimeException} is thrown.
+        */
+       public static final String BEAN_ignoreInvocationExceptionsOnGetters = 
"BeanContext.ignoreInvocationExceptionsOnGetters";
+
+       /**
+        * <b>Configuration property:</b>  Ignore invocation errors on setters.
+        *
+        * <ul>
+        *      <li><b>Name:</b> 
<js>"BeanContext.ignoreInvocationExceptionsOnSetters"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>false</jk>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * If <jk>true</jk>, errors thrown when calling bean setter methods 
will silently be ignored.
+        * Otherwise, a {@code BeanRuntimeException} is thrown.
+        */
+       public static final String BEAN_ignoreInvocationExceptionsOnSetters = 
"BeanContext.ignoreInvocationExceptionsOnSetters";
+
+       /**
+        * <b>Configuration property:</b>  Sort bean properties in alphabetical 
order.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.sortProperties"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>false</jk>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * When <jk>true</jk>, all bean properties will be serialized and 
access in alphabetical order.
+        * Otherwise, the natural order of the bean properties is used which is 
dependent on the JVM vendor.
+        * On IBM JVMs, the bean properties are ordered based on their ordering 
in the Java file.
+        * On Oracle JVMs, the bean properties are not ordered (which follows 
the official JVM specs).
+        *
+        * <p>
+        * This property is disabled by default so that IBM JVM users don't 
have to use {@link Bean @Bean} annotations
+        * to force bean properties to be in a particular order and can just 
alter the order of the fields/methods
+        * in the Java file.
+        */
+       public static final String BEAN_sortProperties = 
"BeanContext.sortProperties";
+
+       /**
+        * <b>Configuration property:</b>  Packages whose classes should not be 
considered beans.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.notBeanPackages.set"</js>
+        *      <li><b>Data type:</b> <code>Set&lt;String&gt;</code>
+        *      <li><b>Default:</b>
+        *      <ul>
+        *              <li><code>java.lang</code>
+        *              <li><code>java.lang.annotation</code>
+        *              <li><code>java.lang.ref</code>
+        *              <li><code>java.lang.reflect</code>
+        *              <li><code>java.io</code>
+        *              <li><code>java.net</code>
+        *              <li><code>java.nio.*</code>
+        *              <li><code>java.util.*</code>
+        *      </ul>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * When specified, the current list of ignore packages are appended to.
+        *
+        * <p>
+        * Any classes within these packages will be serialized to strings 
using {@link Object#toString()}.
+        *
+        * <p>
+        * Note that you can specify prefix patterns to include all subpackages.
+        */
+       public static final String BEAN_notBeanPackages = 
"BeanContext.notBeanPackages.set";
+
+       /**
+        * <b>Configuration property:</b>  Add to packages whose classes should 
not be considered beans.
+        */
+       public static final String BEAN_notBeanPackages_add = 
"BeanContext.notBeanPackages.set.add";
+
+       /**
+        * <b>Configuration property:</b>  Remove from packages whose classes 
should not be considered beans.
+        */
+       public static final String BEAN_notBeanPackages_remove = 
"BeanContext.notBeanPackages.set.remove";
+
+       /**
+        * <b>Configuration property:</b>  Classes to be excluded from 
consideration as being beans.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.notBeanClasses.set"</js>
+        *      <li><b>Data type:</b> <code>Set&lt;Class&gt;</code>
+        *      <li><b>Default:</b> empty set
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * Not-bean classes are typically converted to <code>Strings</code> 
during serialization even if they appear to be
+        * bean-like.
+        */
+       public static final String BEAN_notBeanClasses = 
"BeanContext.notBeanClasses.set";
+
+       /**
+        * <b>Configuration property:</b>  Add to classes that should not be 
considered beans.
+        */
+       public static final String BEAN_notBeanClasses_add = 
"BeanContext.notBeanClasses.set.add";
+
+       /**
+        * <b>Configuration property:</b>  Remove from classes that should not 
be considered beans.
+        */
+       public static final String BEAN_notBeanClasses_remove = 
"BeanContext.notBeanClasses.set.remove";
+
+       /**
+        * <b>Configuration property:</b>  Bean filters to apply to beans.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.beanFilters.list"</js>
+        *      <li><b>Data type:</b> <code>List&lt;Class&gt;</code>
+        *      <li><b>Default:</b> empty list
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * This is a programmatic equivalent to the {@link Bean @Bean} 
annotation.
+        * It's useful when you want to use the Bean annotation functionality, 
but you don't have the ability to alter the
+        * bean classes.
+        *
+        * <p>
+        * There are two category of classes that can be passed in through this 
method:
+        * <ul class='spaced-list'>
+        *      <li>
+        *              Subclasses of {@link BeanFilterBuilder}.
+        *              These must have a public no-arg constructor.
+        *      <li>
+        *              Bean interface classes.
+        *              A shortcut for defining a {@link 
InterfaceBeanFilterBuilder}.
+        *              Any subclasses of an interface class will only have 
properties defined on the interface.
+        *              All other bean properties will be ignored.
+        * </ul>
+        */
+       public static final String BEAN_beanFilters = 
"BeanContext.beanFilters.list";
+
+       /**
+        * <b>Configuration property:</b>  Add to bean filters.
+        */
+       public static final String BEAN_beanFilters_add = 
"BeanContext.beanFilters.list.add";
+
+       /**
+        * <b>Configuration property:</b>  Remove from bean filters.
+        */
+       public static final String BEAN_beanFilters_remove = 
"BeanContext.beanFilters.list.remove";
+
+       /**
+        * <b>Configuration property:</b>  POJO swaps to apply to Java objects.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.pojoSwaps.list"</js>
+        *      <li><b>Data type:</b> <code>List&lt;Class&gt;</code>
+        *      <li><b>Default:</b> empty list
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * There are two category of classes that can be passed in through this 
method:
+        * <ul>
+        *      <li>Subclasses of {@link PojoSwap}.
+        *      <li>Surrogate classes.  A shortcut for defining a {@link 
SurrogateSwap}.
+        * </ul>
+        */
+       public static final String BEAN_pojoSwaps = 
"BeanContext.pojoSwaps.list";
+
+       /**
+        * <b>Configuration property:</b>  Add to POJO swap classes.
+        */
+       public static final String BEAN_pojoSwaps_add = 
"BeanContext.pojoSwaps.list.add";
+
+       /**
+        * <b>Configuration property:</b>  Remove from POJO swap classes.
+        */
+       public static final String BEAN_pojoSwaps_remove = 
"BeanContext.pojoSwaps.list.remove";
+
+       /**
+        * <b>Configuration property:</b>  Implementation classes for 
interfaces and abstract classes.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.implClasses.map"</js>
+        *      <li><b>Data type:</b> <code>Map&lt;Class,Class&gt;</code>
+        *      <li><b>Default:</b> empty map
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * For interfaces and abstract classes this method can be used to 
specify an implementation class for the
+        * interface/abstract class so that instances of the implementation 
class are used when instantiated (e.g. during a
+        * parse).
+        */
+       public static final String BEAN_implClasses = 
"BeanContext.implClasses.map";
+
+       /**
+        * <b>Configuration property:</b>  Add an implementation class.
+        */
+       public static final String BEAN_implClasses_put = 
"BeanContext.implClasses.map.put";
+
+       /**
+        * <b>Configuration property:</b>  Explicitly specify visible bean 
properties.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.includeProperties"</js>
+        *      <li><b>Data type:</b> <code>Map&lt;String,String&gt;</code>
+        *      <li><b>Default:</b> <code>{}</code>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * Specifies to only include the specified list of properties for the 
specified bean classes.
+        *
+        * <p>
+        * The keys are either fully-qualified or simple class names, and the 
values are comma-delimited lists of property
+        *      names.
+        * The key <js>"*"</js> means all bean classes.
+        *
+        * <p>
+        * For example, <code>{Bean1:<js>'foo,bar'</js>}</code> means only 
serialize the <code>foo</code> and
+        * <code>bar</code> properties on the specified bean.
+        *
+        * <p>
+        * Setting applies to specified class and all subclasses.
+        */
+       public static final String BEAN_includeProperties = 
"BeanContext.includeProperties.map";
+
+       /**
+        * <b>Configuration property:</b>  Explicitly specify visible bean 
properties.
+        */
+       public static final String BEAN_includeProperties_put = 
"BeanContext.includeProperties.map.put";
+
+       /**
+        * <b>Configuration property:</b>  Exclude specified properties from 
beans.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.excludeProperties"</js>
+        *      <li><b>Data type:</b> <code>Map&lt;String,String&gt;</code>
+        *      <li><b>Default:</b> <code>{}</code>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * Specifies to exclude the specified list of properties for the 
specified bean class.
+        *
+        * <p>
+        * The keys are either fully-qualified or simple class names, and the 
values are comma-delimited lists of property
+        * names.
+        * The key <js>"*"</js> means all bean classes.
+        *
+        * <p>
+        * For example, <code>{Bean1:<js>'foo,bar'</js>}</code> means don't 
serialize the <code>foo</code> and
+        * <code>bar</code> properties on the specified bean.
+        *
+        * <p>
+        * Setting applies to specified class and all subclasses.
+        */
+       public static final String BEAN_excludeProperties = 
"BeanContext.excludeProperties.map";
+
+       /**
+        * <b>Configuration property:</b>  Exclude specified properties from 
beans.
+        */
+       public static final String BEAN_excludeProperties_put = 
"BeanContext.excludeProperties.map.put";
+
+       /**
+        * <b>Configuration property:</b>  Bean lookup dictionary.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.beanDictionary.list"</js>
+        *      <li><b>Data type:</b> <code>List&lt;Class&gt;</code>
+        *      <li><b>Default:</b> empty list
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * This list can consist of the following class types:
+        * <ul>
+        *      <li>Any bean class that specifies a value for {@link 
Bean#typeName() @Bean.typeName()}.
+        *      <li>Any subclass of {@link BeanDictionaryList} containing a 
collection of bean classes with type name
+        *              annotations.
+        *      <li>Any subclass of {@link BeanDictionaryMap} containing a 
mapping of type names to classes without type name
+        *              annotations.
+        * </ul>
+        */
+       public static final String BEAN_beanDictionary = 
"BeanContext.beanDictionary.list";
+
+       /**
+        * <b>Configuration property:</b>  Add to bean dictionary.
+        */
+       public static final String BEAN_beanDictionary_add = 
"BeanContext.beanDictionary.list.add";
+
+       /**
+        * <b>Configuration property:</b>  Remove from bean dictionary.
+        */
+       public static final String BEAN_beanDictionary_remove = 
"BeanContext.beanDictionary.list.remove";
+
+       /**
+        * <b>Configuration property:</b>  Name to use for the bean type 
properties used to represent a bean type.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.beanTypePropertyName"</js>
+        *      <li><b>Data type:</b> <code>String</code>
+        *      <li><b>Default:</b> <js>"_type"</js>
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        */
+       public static final String BEAN_beanTypePropertyName = 
"BeanContext.beanTypePropertyName";
+
+       /**
+        * <b>Configuration property:</b>  Default parser to use when 
converting <code>Strings</code> to POJOs.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.defaultParser"</js>
+        *      <li><b>Data type:</b> <code>Class</code>
+        *      <li><b>Default:</b> {@link JsonSerializer}
+        *      <li><b>Session-overridable:</b> <jk>false</jk>
+        * </ul>
+        *
+        * <p>
+        * Used in the in the {@link BeanSession#convertToType(Object, Class)} 
method.
+        */
+       public static final String BEAN_defaultParser = 
"BeanContext.defaultParser";
+
+       /**
+        * <b>Configuration property:</b>  Locale.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.locale"</js>
+        *      <li><b>Data type:</b> <code>Locale</code>
+        *      <li><b>Default:</b> <code>Locale.getDefault()</code>
+        *      <li><b>Session-overridable:</b> <jk>true</jk>
+        * </ul>
+        *
+        * <p>
+        * Used in the in the {@link BeanSession#convertToType(Object, Class)} 
method.
+        */
+       public static final String BEAN_locale = "BeanContext.locale";
+
+       /**
+        * <b>Configuration property:</b>  TimeZone.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.timeZone"</js>
+        *      <li><b>Data type:</b> <code>TimeZone</code>
+        *      <li><b>Default:</b> <jk>null</jk>
+        *      <li><b>Session-overridable:</b> <jk>true</jk>
+        * </ul>
+        *
+        * <p>
+        * Used in the in the {@link BeanSession#convertToType(Object, Class)} 
method.
+        */
+       public static final String BEAN_timeZone = "BeanContext.timeZone";
+
+       /**
+        * <b>Configuration property:</b>  Media type.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.mediaType"</js>
+        *      <li><b>Data type:</b> <code>MediaType</code>
+        *      <li><b>Default:</b> <jk>null</jk>
+        *      <li><b>Session-overridable:</b> <jk>true</jk>
+        * </ul>
+        *
+        * <p>
+        * Specifies a default media type value for serializer and parser 
sessions.
+        */
+       public static final String BEAN_mediaType = "BeanContext.mediaType";
+
+       /**
+        * <b>Configuration property:</b>  Debug mode.
+        *
+        * <ul>
+        *      <li><b>Name:</b> <js>"BeanContext.debug"</js>
+        *      <li><b>Data type:</b> <code>Boolean</code>
+        *      <li><b>Default:</b> <jk>false</jk>
+        *      <li><b>Session-overridable:</b> <jk>true</jk>
+        * </ul>
+        *
+        * <p>
+        * Enables the following additional information during serialization:
+        * <ul class='spaced-list'>
+        *      <li>
+        *              When bean getters throws exceptions, the exception 
includes the object stack information
+        *              in order to determine how that method was invoked.
+        *      <li>
+        *              Enables {@link 
SerializerContext#SERIALIZER_detectRecursions}.
+        * </ul>
+        *
+        * <p>
+        * Enables the following additional information during parsing:
+        * <ul class='spaced-list'>
+        *      <li>
+        *              When bean setters throws exceptions, the exception 
includes the object stack information
+        *              in order to determine how that method was invoked.
+        * </ul>
+        */
+       public static final String BEAN_debug = "BeanContext.debug";
+
+       /*
+        * The default package pattern exclusion list.
+        * Any beans in packages in this list will not be considered beans.
+        */
+       private static final String[] DEFAULT_NOTBEAN_PACKAGES = {
+               "java.lang",
+               "java.lang.annotation",
+               "java.lang.ref",
+               "java.lang.reflect",
+               "java.io",
+               "java.net",
+               "java.nio.*",
+               "java.util.*"
+       };
+
+       /*
+        * The default bean class exclusion list.
+        * Anything in this list will not be considered beans.
+        */
+       private static final Class<?>[] DEFAULT_NOTBEAN_CLASSES = {
+               Map.class,
+               Collection.class,
+               Reader.class,
+               Writer.class,
+               InputStream.class,
+               OutputStream.class,
+               Throwable.class
+       };
+
+
+       static final void loadDefaults(PropertyStore config) {
+               config.setProperty(BEAN_notBeanPackages, 
DEFAULT_NOTBEAN_PACKAGES);
+               config.setProperty(BEAN_notBeanClasses, 
DEFAULT_NOTBEAN_CLASSES);
+       }
+
+
+       // This map is important!
+       // We may have many ConfigFactory objects that have identical 
BeanContext properties.
+       // This map ensures that if the BeanContext properties in the 
ConfigFactory are the same,
+       // then we reuse the same Class->ClassMeta cache map.
+       // This significantly reduces the number of times we need to construct 
ClassMeta objects which can be expensive.
+       private static final ConcurrentHashMap<Integer,Map<Class,ClassMeta>> 
cmCacheCache
+               = new ConcurrentHashMap<Integer,Map<Class,ClassMeta>>();
+
+       /** Default config.  All default settings. */
+       public static final BeanContext DEFAULT = 
PropertyStore.create().getContext(BeanContext.class);
+
+       /** Default config.  All default settings except sort bean properties. 
*/
+       public static final BeanContext DEFAULT_SORTED = 
PropertyStore.create().setProperty(BEAN_sortProperties, 
true).getContext(BeanContext.class);
+
+       final boolean
+               beansRequireDefaultConstructor,
+               beansRequireSerializable,
+               beansRequireSettersForGetters,
+               beansRequireSomeProperties,
+               beanMapPutReturnsOldValue,
+               useInterfaceProxies,
+               ignoreUnknownBeanProperties,
+               ignoreUnknownNullBeanProperties,
+               ignorePropertiesWithoutSetters,
+               ignoreInvocationExceptionsOnGetters,
+               ignoreInvocationExceptionsOnSetters,
+               useJavaBeanIntrospector,
+               sortProperties,
+               debug;
+
+       final Visibility
+               beanConstructorVisibility,
+               beanClassVisibility,
+               beanMethodVisibility,
+               beanFieldVisibility;
+
+       final Class<?>[] notBeanClasses, beanDictionaryClasses;
+       final String[] notBeanPackageNames, notBeanPackagePrefixes;
+       final BeanFilter[] beanFilters;
+       final PojoSwap<?,?>[] pojoSwaps;
+       final BeanRegistry beanRegistry;
+       final Map<Class<?>,Class<?>> implClasses;
+       final Class<?>[] implKeyClasses, implValueClasses;
+       final ClassLoader classLoader;
+       final Locale locale;
+       final TimeZone timeZone;
+       final MediaType mediaType;
+       final Map<String,String[]> includeProperties, excludeProperties;
+
+       final Map<Class,ClassMeta> cmCache;
+       final ClassMeta<Object> cmObject;  // Reusable ClassMeta that 
represents general Objects.
+       final ClassMeta<String> cmString;  // Reusable ClassMeta that 
represents general Strings.
+       final ClassMeta<Class> cmClass;  // Reusable ClassMeta that represents 
general Classes.
+
+       // Optional default parser set by setDefaultParser().
+       final ReaderParser defaultParser;
+
+       final String beanTypePropertyName;
+
+       final int hashCode;
+
+       /**
+        * Constructor.
+        *
+        * <p>
+        * Typically only called from {@link PropertyStore#getContext(Class)} 
or {@link PropertyStore#getBeanContext()}.
+        *
+        * @param ps The property store that created this context.
+        */
+       public BeanContext(PropertyStore ps) {
+               super(ps);
+
+               PropertyStore.PropertyMap pm = ps.getPropertyMap("BeanContext");
+               hashCode = pm.hashCode();
+               classLoader = ps.classLoader;
+               defaultParser = ps.defaultParser;
+
+               beansRequireDefaultConstructor = 
pm.get(BEAN_beansRequireDefaultConstructor, boolean.class, false);
+               beansRequireSerializable = 
pm.get(BEAN_beansRequireSerializable, boolean.class, false);
+               beansRequireSettersForGetters = 
pm.get(BEAN_beansRequireSettersForGetters, boolean.class, false);
+               beansRequireSomeProperties = 
pm.get(BEAN_beansRequireSomeProperties, boolean.class, true);
+               beanMapPutReturnsOldValue = 
pm.get(BEAN_beanMapPutReturnsOldValue, boolean.class, false);
+               useInterfaceProxies = pm.get(BEAN_useInterfaceProxies, 
boolean.class, true);
+               ignoreUnknownBeanProperties = 
pm.get(BEAN_ignoreUnknownBeanProperties, boolean.class, false);
+               ignoreUnknownNullBeanProperties = 
pm.get(BEAN_ignoreUnknownNullBeanProperties, boolean.class, true);
+               ignorePropertiesWithoutSetters = 
pm.get(BEAN_ignorePropertiesWithoutSetters, boolean.class, true);
+               ignoreInvocationExceptionsOnGetters = 
pm.get(BEAN_ignoreInvocationExceptionsOnGetters, boolean.class, false);
+               ignoreInvocationExceptionsOnSetters = 
pm.get(BEAN_ignoreInvocationExceptionsOnSetters, boolean.class, false);
+               useJavaBeanIntrospector = pm.get(BEAN_useJavaBeanIntrospector, 
boolean.class, false);
+               sortProperties = pm.get(BEAN_sortProperties, boolean.class, 
false);
+               beanTypePropertyName = pm.get(BEAN_beanTypePropertyName, 
String.class, "_type");
+               debug = ps.getProperty(BEAN_debug, boolean.class, false);
+
+               beanConstructorVisibility = 
pm.get(BEAN_beanConstructorVisibility, Visibility.class, PUBLIC);
+               beanClassVisibility = pm.get(BEAN_beanClassVisibility, 
Visibility.class, PUBLIC);
+               beanMethodVisibility = pm.get(BEAN_methodVisibility, 
Visibility.class, PUBLIC);
+               beanFieldVisibility = pm.get(BEAN_beanFieldVisibility, 
Visibility.class, PUBLIC);
+
+               notBeanClasses = pm.get(BEAN_notBeanClasses, Class[].class, new 
Class[0]);
+
+               List<String> l1 = new LinkedList<String>();
+               List<String> l2 = new LinkedList<String>();
+               for (String s : pm.get(BEAN_notBeanPackages, String[].class, 
new String[0])) {
+                       if (s.endsWith(".*"))
+                               l2.add(s.substring(0, s.length()-2));
+                       else
+                               l1.add(s);
+               }
+               notBeanPackageNames = l1.toArray(new String[l1.size()]);
+               notBeanPackagePrefixes = l2.toArray(new String[l2.size()]);
+
+               LinkedList<BeanFilter> lbf = new LinkedList<BeanFilter>();
+               for (Class<?> c : pm.get(BEAN_beanFilters, Class[].class, new 
Class[0])) {
+                       if (isParentClass(BeanFilter.class, c))
+                               lbf.add(newInstance(BeanFilter.class, c));
+                       else if (isParentClass(BeanFilterBuilder.class, c))
+                               lbf.add(newInstance(BeanFilterBuilder.class, 
c).build());
+                       else
+                               lbf.add(new 
InterfaceBeanFilterBuilder(c).build());
+               }
+               beanFilters = lbf.toArray(new BeanFilter[0]);
+
+               LinkedList<PojoSwap<?,?>> lpf = new LinkedList<PojoSwap<?,?>>();
+               for (Class<?> c : pm.get(BEAN_pojoSwaps, Class[].class, new 
Class[0])) {
+                       if (isParentClass(PojoSwap.class, c))
+                               lpf.add(newInstance(PojoSwap.class, c));
+                       else
+                               lpf.addAll(SurrogateSwap.findPojoSwaps(c));
+               }
+               pojoSwaps = lpf.toArray(new PojoSwap[0]);
+
+               implClasses = new TreeMap<Class<?>,Class<?>>(new 
ClassComparator());
+               Map<Class,Class> m = pm.getMap(BEAN_implClasses, Class.class, 
Class.class, null);
+               if (m != null)
+                       for (Map.Entry<Class,Class> e : m.entrySet())
+                               implClasses.put(e.getKey(), e.getValue());
+               implKeyClasses = implClasses.keySet().toArray(new Class[0]);
+               implValueClasses = implClasses.values().toArray(new Class[0]);
+
+               Map<String,String[]> m2 = pm.getMap(BEAN_includeProperties, 
String.class, String[].class, null);
+               includeProperties = m2 == null ? Collections.EMPTY_MAP : 
Collections.unmodifiableMap(m2);
+               m2 = pm.getMap(BEAN_excludeProperties, String.class, 
String[].class, null);
+               excludeProperties = m2 == null ? Collections.EMPTY_MAP : 
Collections.unmodifiableMap(m2);
+
+               locale = pm.get(BEAN_locale, Locale.class, null);
+               timeZone = pm.get(BEAN_timeZone, TimeZone.class, null);
+               mediaType = pm.get(BEAN_mediaType, MediaType.class, null);
+
+               if (! cmCacheCache.containsKey(hashCode)) {
+                       ConcurrentHashMap<Class,ClassMeta> cm = new 
ConcurrentHashMap<Class,ClassMeta>();
+                       cm.putIfAbsent(String.class, new 
ClassMeta(String.class, this, null, null, findPojoSwap(String.class), 
findChildPojoSwaps(String.class)));
+                       cm.putIfAbsent(Object.class, new 
ClassMeta(Object.class, this, null, null, findPojoSwap(Object.class), 
findChildPojoSwaps(Object.class)));
+                       cmCacheCache.putIfAbsent(hashCode, cm);
+               }
+               this.cmCache = cmCacheCache.get(hashCode);
+               this.cmString = cmCache.get(String.class);
+               this.cmObject = cmCache.get(Object.class);
+               this.cmClass = cmCache.get(Class.class);
+
+               this.beanDictionaryClasses = pm.get(BEAN_beanDictionary, 
Class[].class, new Class[0]);
+               this.beanRegistry = new BeanRegistry(this, null);
+       }
+
+       /**
+        * Create a new bean session based on the properties defined on this 
context.
+        *
+        * @param args
+        *      The session arguments.
+        * @return A new session object.
+        */
+       public BeanSession createSession(BeanSessionArgs args) {
+               return new BeanSession(this, args);
+       }
+
+       /**
+        * Create a new bean session based on the properties defined on this 
context.
+        *
+        * <p>
+        * Use this method for creating sessions if you don't need to override 
any
+        * properties or locale/timezone currently set on this context.
+        *
+        * @return A new session object.
+        */
+       public BeanSession createSession() {
+               return new BeanSession(this, new BeanSessionArgs(null, 
this.locale, this.timeZone, this.mediaType));
+       }
+
+       /**
+        * Returns <jk>true</jk> if the specified bean context shares the same 
cache as this bean context.
+        *
+        * <p>
+        * Useful for testing purposes.
+        *
+        * @param bc The bean context to compare to.
+        * @return <jk>true</jk> if the bean contexts have equivalent settings 
and thus share caches.
+        */
+       public final boolean hasSameCache(BeanContext bc) {
+               return bc.cmCache == this.cmCache;
+       }
+
+       /**
+        * Determines whether the specified class is ignored as a bean class 
based on the various exclusion parameters
+        * specified on this context class.
+        *
+        * @param c The class type being tested.
+        * @return <jk>true</jk> if the specified class matches any of the 
exclusion parameters.
+        */
+       protected final boolean isNotABean(Class<?> c) {
+               if (c.isArray() || c.isPrimitive() || c.isEnum() || 
c.isAnnotation())
+                       return true;
+               Package p = c.getPackage();
+               if (p != null) {
+                       for (String p2 : notBeanPackageNames)
+                               if (p.getName().equals(p2))
+                                       return true;
+                       for (String p2 : notBeanPackagePrefixes)
+                               if (p.getName().startsWith(p2))
+                                       return true;
+               }
+               for (Class exclude : notBeanClasses)
+                       if (isParentClass(exclude, c))
+                               return true;
+               return false;
+       }
+
+       /**
+        * Returns <jk>true</jk> if the specified object is a bean.
+        *
+        * @param o The object to test.
+        * @return <jk>true</jk> if the specified object is a bean.  
<jk>false</jk> if the bean is <jk>null</jk>.
+        */
+       public boolean isBean(Object o) {
+               if (o == null)
+                       return false;
+               return getClassMetaForObject(o).isBean();
+       }
+
+       /**
+        * Prints meta cache statistics to <code>System.out</code>.
+        */
+       protected static void dumpCacheStats() {
+               try {
+                       int ctCount = 0;
+                       for (Map<Class,ClassMeta> cm : cmCacheCache.values())
+                               ctCount += cm.size();
+                       System.out.println(format("ClassMeta cache: {0} 
instances in {1} caches", ctCount, cmCacheCache.size())); // NOT DEBUG
+               } catch (Exception e) {
+                       e.printStackTrace();
+               }
+       }
+
+       /**
+        * Returns the {@link BeanMeta} class for the specified class.
+        *
+        * @param <T> The class type to get the meta-data on.
+        * @param c The class to get the meta-data on.
+        * @return
+        *      The {@link BeanMeta} for the specified class, or <jk>null</jk> 
if the class is not a bean per the settings on
+        *      this context.
+        */
+       public final <T> BeanMeta<T> getBeanMeta(Class<T> c) {
+               if (c == null)
+                       return null;
+               return getClassMeta(c).getBeanMeta();
+       }
+
+       /**
+        * Construct a {@code ClassMeta} wrapper around a {@link Class} object.
+        *
+        * @param <T> The class type being wrapped.
+        * @param type The class to resolve.
+        * @return
+        *      If the class is not an array, returns a cached {@link 
ClassMeta} object.
+        *      Otherwise, returns a new {@link ClassMeta} object every time.
+        */
+       public final <T> ClassMeta<T> getClassMeta(Class<T> type) {
+               return getClassMeta(type, true);
+       }
+
+       /**
+        * Construct a {@code ClassMeta} wrapper around a {@link Class} object.
+        *
+        * @param <T> The class type being wrapped.
+        * @param type The class to resolve.
+        * @param waitForInit
+        *      If <jk>true</jk>, wait for the ClassMeta constructor to finish 
before returning.
+        * @return
+        *      If the class is not an array, returns a cached {@link 
ClassMeta} object.
+        *      Otherwise, returns a new {@link ClassMeta} object every time.
+        */
+       final <T> ClassMeta<T> getClassMeta(Class<T> type, boolean waitForInit) 
{
+
+               // If this is an array, then we want it wrapped in an uncached 
ClassMeta object.
+               // Note that if it has a pojo swap, we still want to cache it 
so that
+               // we can cache something like byte[] with ByteArrayBase64Swap.
+               if (type.isArray() && findPojoSwap(type) == null)
+                       return new ClassMeta(type, this, findImplClass(type), 
findBeanFilter(type), findPojoSwap(type), findChildPojoSwaps(type));
+
+               // This can happen if we have transforms defined against String 
or Object.
+               if (cmCache == null)
+                       return null;
+
+               ClassMeta<T> cm = cmCache.get(type);
+               if (cm == null) {
+
+                       synchronized (this) {
+                               // Make sure someone didn't already set it 
while this thread was blocked.
+                               cm = cmCache.get(type);
+                               if (cm == null)
+                                       cm = new ClassMeta<T>(type, this, 
findImplClass(type), findBeanFilter(type), findPojoSwap(type), 
findChildPojoSwaps(type));
+                       }
+               }
+               if (waitForInit)
+                       cm.waitForInit();
+               return cm;
+       }
+
+       /**
+        * Used to resolve <code>ClassMetas</code> of type 
<code>Collection</code> and <code>Map</code> that have
+        * <code>ClassMeta</code> values that themselves could be collections 
or maps.
+        *
+        * <p>
+        * <code>Collection</code> meta objects are assumed to be followed by 
zero or one meta objects indicating the element type.
+        *
+        * <p>
+        * <code>Map</code> meta objects are assumed to be followed by zero or 
two meta objects indicating the key and value types.
+        *
+        * <p>
+        * The array can be arbitrarily long to indicate arbitrarily complex 
data structures.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <ul>
+        *      <li><code>getClassMeta(String.<jk>class</jk>);</code> - A 
normal type.
+        *      <li><code>getClassMeta(List.<jk>class</jk>);</code> - A list 
containing objects.
+        *      <li><code>getClassMeta(List.<jk>class</jk>, 
String.<jk>class</jk>);</code> - A list containing strings.
+        *      <li><code>getClassMeta(LinkedList.<jk>class</jk>, 
String.<jk>class</jk>);</code> - A linked-list containing
+        *              strings.
+        *      <li><code>getClassMeta(LinkedList.<jk>class</jk>, 
LinkedList.<jk>class</jk>, String.<jk>class</jk>);</code> -
+        *              A linked-list containing linked-lists of strings.
+        *      <li><code>getClassMeta(Map.<jk>class</jk>);</code> - A map 
containing object keys/values.
+        *      <li><code>getClassMeta(Map.<jk>class</jk>, 
String.<jk>class</jk>, String.<jk>class</jk>);</code> - A map
+        *              containing string keys/values.
+        *      <li><code>getClassMeta(Map.<jk>class</jk>, 
String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);</code> -
+        *              A map containing string keys and values of lists 
containing beans.
+        * </ul>
+        *
+        * @param type
+        *      The class to resolve.
+        *      <br>Can be any of the following: {@link ClassMeta}, {@link 
Class}, {@link ParameterizedType},
+        *      {@link GenericArrayType}
+        * @param args
+        *      The type arguments of the class if it's a collection or map.
+        *      <br>Can be any of the following: {@link ClassMeta}, {@link 
Class}, {@link ParameterizedType},
+        *      {@link GenericArrayType}
+        *      <br>Ignored if the main type is not a map or collection.
+        * @return The resolved class meta.
+        */
+       public final <T> ClassMeta<T> getClassMeta(Type type, Type...args) {
+               if (type == null)
+                       return null;
+               ClassMeta<T> cm = type instanceof Class ? 
getClassMeta((Class)type) : resolveClassMeta(type, null);
+               if (args.length == 0)
+                       return cm;
+               ClassMeta<?>[] cma = new ClassMeta[args.length+1];
+               cma[0] = cm;
+               for (int i = 0; i < Array.getLength(args); i++) {
+                       Type arg = (Type)Array.get(args, i);
+                       cma[i+1] = arg instanceof Class ? 
getClassMeta((Class)arg) : resolveClassMeta(arg, null);
+               }
+               return (ClassMeta<T>) getTypedClassMeta(cma, 0);
+       }
+
+       /*
+        * Resolves the 'genericized' class meta at the specified position in 
the ClassMeta array.
+        */
+       private ClassMeta<?> getTypedClassMeta(ClassMeta<?>[] c, int pos) {
+               ClassMeta<?> cm = c[pos++];
+               if (cm.isCollection()) {
+                       ClassMeta<?> ce = c.length == pos ? object() : 
getTypedClassMeta(c, pos);
+                       return (ce.isObject() ? cm : new ClassMeta(cm, null, 
null, ce));
+               } else if (cm.isMap()) {
+                       ClassMeta<?> ck = c.length == pos ? object() : c[pos++];
+                       ClassMeta<?> cv = c.length == pos ? object() : 
getTypedClassMeta(c, pos);
+                       return (ck.isObject() && cv.isObject() ? cm : new 
ClassMeta(cm, ck, cv, null));
+               }
+               return cm;
+       }
+
+       final ClassMeta resolveClassMeta(Type o, Map<Class<?>,Class<?>[]> 
typeVarImpls) {
+               if (o == null)
+                       return null;
+
+               if (o instanceof ClassMeta) {
+                       ClassMeta<?> cm = (ClassMeta)o;
+
+                       // This classmeta could have been created by a 
different context.
+                       // Need to re-resolve it to pick up PojoSwaps and stuff 
on this context.
+                       if (cm.getBeanContext() == this)
+                               return cm;
+                       if (cm.isMap())
+                               return getClassMeta(cm.innerClass, 
cm.getKeyType(), cm.getValueType());
+                       if (cm.isCollection())
+                               return getClassMeta(cm.innerClass, 
cm.getElementType());
+                       return getClassMeta(cm.innerClass);
+               }
+
+               Class c = resolve(o, typeVarImpls);
+
+               // This can happen when trying to resolve the "E getFirst()" 
method on LinkedList, whose type is a TypeVariable
+               // These should just resolve to Object.
+               if (c == null)
+                       return object();
+
+               ClassMeta rawType = getClassMeta(c);
+
+               // If this is a Map or Collection, and the parameter types 
aren't part
+               // of the class definition itself (e.g. class AddressBook 
extends List<Person>),
+               // then we need to figure out the parameters.
+               if (rawType.isMap() || rawType.isCollection()) {
+                       ClassMeta[] params = findParameters(o, c);
+                       if (params == null)
+                               return rawType;
+                       if (rawType.isMap()) {
+                               if (params.length != 2)
+                                       return rawType;
+                               if (params[0].isObject() && 
params[1].isObject())
+                                       return rawType;
+                               return new ClassMeta(rawType, params[0], 
params[1], null);
+                       }
+                       if (rawType.isCollection()) {
+                               if (params.length != 1)
+                                       return rawType;
+                               if (params[0].isObject())
+                                       return rawType;
+                               return new ClassMeta(rawType, null, null, 
params[0]);
+                       }
+               }
+
+               return rawType;
+       }
+
+       /**
+        * Convert a Type to a Class if possible.
+        * Return null if not possible.
+        */
+       final Class resolve(Type t, Map<Class<?>,Class<?>[]> typeVarImpls) {
+
+               if (t instanceof Class)
+                       return (Class)t;
+
+               if (t instanceof ParameterizedType)
+                       // A parameter (e.g. <String>.
+                       return (Class)((ParameterizedType)t).getRawType();
+
+               if (t instanceof GenericArrayType) {
+                       // An array parameter (e.g. <byte[]>).
+                       Type gatct = 
((GenericArrayType)t).getGenericComponentType();
+
+                       if (gatct instanceof Class)
+                               return Array.newInstance((Class)gatct, 
0).getClass();
+
+                       if (gatct instanceof ParameterizedType)
+                               return 
Array.newInstance((Class)((ParameterizedType)gatct).getRawType(), 0).getClass();
+
+                       if (gatct instanceof GenericArrayType)
+                               return Array.newInstance(resolve(gatct, 
typeVarImpls), 0).getClass();
+
+                       return null;
+
+               } else if (t instanceof TypeVariable) {
+                       if (typeVarImpls != null) {
+                               TypeVariable tv = (TypeVariable)t;
+                               String varName = tv.getName();
+                               int varIndex = -1;
+                               Class gc = (Class)tv.getGenericDeclaration();
+                               TypeVariable[] tvv = gc.getTypeParameters();
+                               for (int i = 0; i < tvv.length; i++) {
+                                       if (tvv[i].getName().equals(varName)) {
+                                               varIndex = i;
+                                       }
+                               }
+                               if (varIndex != -1) {
+
+                                       // If we couldn't find a type variable 
implementation, that means
+                                       // the type was defined at runtime 
(e.g. Bean b = new Bean<Foo>();)
+                                       // in which case the type is lost 
through erasure.
+                                       // Assume java.lang.Object as the type.
+                                       if (! typeVarImpls.containsKey(gc))
+                                               return null;
+
+                                       return typeVarImpls.get(gc)[varIndex];
+                               }
+                       }
+               }
+               return null;
+       }
+
+       final ClassMeta[] findParameters(Type o, Class c) {
+               if (o == null)
+                       o = c;
+
+               // Loop until we find a ParameterizedType
+               if (! (o instanceof ParameterizedType)) {
+                       loop: do {
+                               o = c.getGenericSuperclass();
+                               if (o instanceof ParameterizedType)
+                                       break loop;
+                               for (Type t : c.getGenericInterfaces()) {
+                                       o = t;
+                                       if (o instanceof ParameterizedType)
+                                               break loop;
+                               }
+                               c = c.getSuperclass();
+                       } while (c != null);
+               }
+
+               if (o instanceof ParameterizedType) {
+                       ParameterizedType pt = (ParameterizedType)o;
+                       if (! pt.getRawType().equals(Enum.class)) {
+                               List<ClassMeta<?>> l = new 
LinkedList<ClassMeta<?>>();
+                               for (Type pt2 : pt.getActualTypeArguments()) {
+                                       if (pt2 instanceof WildcardType || pt2 
instanceof TypeVariable)
+                                               return null;
+                                       l.add(resolveClassMeta(pt2, null));
+                               }
+                               if (l.isEmpty())
+                                       return null;
+                               return l.toArray(new ClassMeta[l.size()]);
+                       }
+               }
+
+               return null;
+       }
+
+       /**
+        * Shortcut for calling {@code getClassMeta(o.getClass())}.
+        *
+        * @param <T> The class of the object being passed in.
+        * @param o The class to find the class type for.
+        * @return The ClassMeta object, or <jk>null</jk> if {@code o} is 
<jk>null</jk>.
+        */
+       public final <T> ClassMeta<T> getClassMetaForObject(T o) {
+               if (o == null)
+                       return null;
+               return (ClassMeta<T>)getClassMeta(o.getClass());
+       }
+
+
+       /**
+        * Used for determining the class type on a method or field where a 
{@code @BeanProperty} annotation may be present.
+        *
+        * @param <T> The class type we're wrapping.
+        * @param p The property annotation on the type if there is one.
+        * @param t The type.
+        * @param typeVarImpls
+        *      Contains known resolved type parameters on the specified class 
so that we can result
+        *      {@code ParameterizedTypes} and {@code TypeVariables}.
+        *      Can be <jk>null</jk> if the information is not known.
+        * @return The new {@code ClassMeta} object wrapped around the {@code 
Type} object.
+        */
+       protected final <T> ClassMeta<T> resolveClassMeta(BeanProperty p, Type 
t, Map<Class<?>,Class<?>[]> typeVarImpls) {
+               ClassMeta<T> cm = resolveClassMeta(t, typeVarImpls);
+               ClassMeta<T> cm2 = cm;
+               if (p != null) {
+
+                       if (p.type() != Object.class)
+                               cm2 = resolveClassMeta(p.type(), typeVarImpls);
+
+                       if (cm2.isMap()) {
+                               Class<?>[] pParams = (p.params().length == 0 ? 
new Class[]{Object.class, Object.class} : p.params());
+                               if (pParams.length != 2)
+                                       throw new 
FormattedRuntimeException("Invalid number of parameters specified for Map (must 
be 2): {0}", pParams.length);
+                               ClassMeta<?> keyType = resolveType(pParams[0], 
cm2.getKeyType(), cm.getKeyType());
+                               ClassMeta<?> valueType = 
resolveType(pParams[1], cm2.getValueType(), cm.getValueType());
+                               if (keyType.isObject() && valueType.isObject())
+                                       return cm2;
+                               return new ClassMeta<T>(cm2, keyType, 
valueType, null);
+                       }
+
+                       if (cm2.isCollection()) {
+                               Class<?>[] pParams = (p.params().length == 0 ? 
new Class[]{Object.class} : p.params());
+                               if (pParams.length != 1)
+                                       throw new 
FormattedRuntimeException("Invalid number of parameters specified for 
Collection (must be 1): {0}", pParams.length);
+                               ClassMeta<?> elementType = 
resolveType(pParams[0], cm2.getElementType(), cm.getElementType());
+                               if (elementType.isObject())
+                                       return cm2;
+                               return new ClassMeta<T>(cm2, null, null, 
elementType);
+                       }
+
+                       return cm2;
+               }
+
+               return cm;
+       }
+
+       private ClassMeta<?> resolveType(Type...t) {
+               for (Type tt : t) {
+                       if (tt != null) {
+                               ClassMeta<?> cm = getClassMeta(tt);
+                               if (tt != cmObject)
+                                       return cm;
+                       }
+               }
+               return cmObject;
+       }
+
+       /**
+        * Returns the {@link PojoSwap} associated with the specified class, or 
<jk>null</jk> if there is no POJO swap
+        * associated with the class.
+        *
+        * @param <T> The class associated with the swap.
+        * @param c The class associated with the swap.
+        * @return The swap associated with the class, or null if there is no 
association.
+        */
+       private final <T> PojoSwap findPojoSwap(Class<T> c) {
+               // Note:  On first
+               if (c != null)
+                       for (PojoSwap f : pojoSwaps)
+                               if (isParentClass(f.getNormalClass(), c))
+                                       return f;
+               return null;
+       }
+
+       /**
+        * Checks whether a class has a {@link PojoSwap} associated with it in 
this bean context.
+        *
+        * @param c The class to check.
+        * @return <jk>true</jk> if the specified class or one of its 
subclasses has a {@link PojoSwap} associated with it.
+        */
+       private final PojoSwap[] findChildPojoSwaps(Class<?> c) {
+               if (c == null || pojoSwaps.length == 0)
+                       return null;
+               List<PojoSwap> l = null;
+               for (PojoSwap f : pojoSwaps) {
+                       if (isParentClass(c, f.getNormalClass())) {
+                               if (l == null)
+                                       l = new ArrayList<PojoSwap>();
+                               l.add(f);
+                       }
+               }
+               return l == null ? null : l.toArray(new PojoSwap[l.size()]);
+       }
+
+       /**
+        * Returns the {@link BeanFilter} associated with the specified class, 
or <jk>null</jk> if there is no bean filter
+        * associated with the class.
+        *
+        * @param <T> The class associated with the bean filter.
+        * @param c The class associated with the bean filter.
+        * @return The bean filter associated with the class, or null if there 
is no association.
+        */
+       private final <T> BeanFilter findBeanFilter(Class<T> c) {
+               if (c != null)
+                       for (BeanFilter f : beanFilters)
+                               if (isParentClass(f.getBeanClass(), c))
+                                       return f;
+               return null;
+       }
+
+       /**
+        * Returns the type property name as defined by {@link 
BeanContext#BEAN_beanTypePropertyName}.
+        *
+        * @return The type property name.  Never <jk>null</jk>.
+        */
+       protected final String getBeanTypePropertyName() {
+               return beanTypePropertyName;
+       }
+
+       /**
+        * Returns the bean registry defined in this bean context defined by 
{@link BeanContext#BEAN_beanDictionary}.
+        *
+        * @return The bean registry defined in this bean context.  Never 
<jk>null</jk>.
+        */
+       protected final BeanRegistry getBeanRegistry() {
+               return beanRegistry;
+       }
+
+       /**
+        * Gets the no-arg constructor for the specified class.
+        *
+        * @param <T> The class to check.
+        * @param c The class to check.
+        * @param v The minimum visibility for the constructor.
+        * @return The no arg constructor, or <jk>null</jk> if the class has no 
no-arg constructor.
+        */
+       protected final <T> Constructor<? extends T> 
getImplClassConstructor(Class<T> c, Visibility v) {
+               if (implClasses.isEmpty())
+                       return null;
+               Class cc = c;
+               while (cc != null) {
+                       Class implClass = implClasses.get(cc);
+                       if (implClass != null)
+                               return findNoArgConstructor(implClass, v);
+                       for (Class ic : cc.getInterfaces()) {
+                               implClass = implClasses.get(ic);
+                               if (implClass != null)
+                                       return findNoArgConstructor(implClass, 
v);
+                       }
+                       cc = cc.getSuperclass();
+               }
+               return null;
+       }
+
+       private final <T> Class<? extends T> findImplClass(Class<T> c) {
+               if (implClasses.isEmpty())
+                       return null;
+               Class cc = c;
+               while (cc != null) {
+                       Class implClass = implClasses.get(cc);
+                       if (implClass != null)
+                               return implClass;
+                       for (Class ic : cc.getInterfaces()) {
+                               implClass = implClasses.get(ic);
+                               if (implClass != null)
+                                       return implClass;
+                       }
+                       cc = cc.getSuperclass();
+               }
+               return null;
+       }
+
+       /**
+        * Returns the {@link #BEAN_includeProperties} setting for the 
specified class.
+        *
+        * @param c The class.
+        * @return The properties to include for the specified class, or 
<jk>null</jk> if it's not defined for the class.
+        */
+       public String[] getIncludeProperties(Class<?> c) {
+               if (includeProperties.isEmpty())
+                       return null;
+               String[] s = null;
+               for (Iterator<Class<?>> i = ClassUtils.getParentClasses(c, 
false, true); i.hasNext();) {
+                       Class<?> c2 = i.next();
+                       s = includeProperties.get(c2.getName());
+                       if (s != null)
+                               return s;
+                       s = includeProperties.get(c2.getSimpleName());
+                       if (s != null)
+                               return s;
+               }
+               return includeProperties.get("*");
+       }
+
+       /**
+        * Returns the {@link #BEAN_excludeProperties} setting for the 
specified class.
+        *
+        * @param c The class.
+        * @return The properties to exclude for the specified class, or 
<jk>null</jk> if it's not defined for the class.
+        */
+       public String[] getExcludeProperties(Class<?> c) {
+               if (excludeProperties.isEmpty())
+                       return null;
+               String[] s = null;
+               for (Iterator<Class<?>> i = ClassUtils.getParentClasses(c, 
false, true); i.hasNext();) {
+                       Class<?> c2 = i.next();
+                       s = excludeProperties.get(c2.getName());
+                       if (s != null)
+                               return s;
+                       s = excludeProperties.get(c2.getSimpleName());
+                       if (s != null)
+                               return s;
+               }
+               return excludeProperties.get("*");
+       }
+
+       /**
+        * Returns a reusable {@link ClassMeta} representation for the class 
<code>Object</code>.
+        *
+        * <p>
+        * This <code>ClassMeta</code> is often used to represent "any object 
type" when an object type is not known.
+        *
+        * <p>
+        * This method is identical to calling 
<code>getClassMeta(Object.<jk>class</jk>)</code> but uses a cached copy to
+        * avoid a hashmap lookup.
+        *
+        * @return The {@link ClassMeta} object associated with the 
<code>Object</code> class.
+        */
+       protected final ClassMeta<Object> object() {
+               return cmObject;
+       }
+
+       /**
+        * Returns a reusable {@link ClassMeta} representation for the class 
<code>String</code>.
+        *
+        * <p>
+        * This <code>ClassMeta</code> is often used to represent key types in 
maps.
+        *
+        * <p>
+        * This method is identical to calling 
<code>getClassMeta(String.<jk>class</jk>)</code> but uses a cached copy to
+        * avoid a hashmap lookup.
+        *
+        * @return The {@link ClassMeta} object associated with the 
<code>String</code> class.
+        */
+       protected final ClassMeta<String> string() {
+               return cmString;
+       }
+
+       /**
+        * Returns a reusable {@link ClassMeta} representation for the class 
<code>Class</code>.
+        *
+        * <p>
+        * This <code>ClassMeta</code> is often used to represent key types in 
maps.
+        *
+        * <p>
+        * This method is identical to calling 
<code>getClassMeta(Class.<jk>class</jk>)</code> but uses a cached copy to
+        * avoid a hashmap lookup.
+        *
+        * @return The {@link ClassMeta} object associated with the 
<code>String</code> class.
+        */
+       protected final ClassMeta<Class> _class() {
+               return cmClass;
+       }
+
+       @Override /* Object */
+       public int hashCode() {
+               return hashCode;
+       }
+
+       @Override /* Object */
+       public boolean equals(Object o) {
+               if (this == o)
+                       return true;
+               if (o instanceof BeanContext)
+                       return ((BeanContext)o).hashCode == hashCode;
+               return false;
+       }
+
+       @Override /* Context */
+       public ObjectMap asMap() {
+               return super.asMap()
+                       .append("BeanContext", new ObjectMap()
+                               .append("id", System.identityHashCode(this))
+                               .append("beansRequireDefaultConstructor", 
beansRequireDefaultConstructor)
+                               .append("beansRequireSerializable", 
beansRequireSerializable)
+                               .append("beansRequireSettersForGetters", 
beansRequireSettersForGetters)
+                               .append("beansRequireSomeProperties", 
beansRequireSomeProperties)
+                               .append("beanMapPutReturnsOldValue", 
beanMapPutReturnsOldValue)
+                               .append("beanConstructorVisibility", 
beanConstructorVisibility)
+                               .append("beanClassVisibility", 
beanClassVisibility)
+                               .append("beanMethodVisibility", 
beanMethodVisibility)
+                               .append("beanFieldVisibility", 
beanFieldVisibility)
+                               .append("useInterfaceProxies", 
useInterfaceProxies)
+                               .append("ignoreUnknownBeanProperties", 
ignoreUnknownBeanProperties)
+                               .append("ignoreUnknownNullBeanProperties", 
ignoreUnknownNullBeanProperties)
+                               .append("ignorePropertiesWithoutSetters", 
ignorePropertiesWithoutSetters)
+                               .append("ignoreInvocationExceptionsOnGetters", 
ignoreInvocationExceptionsOnGetters)
+                               .append("ignoreInvocationExceptionsOnSetters", 
ignoreInvocationExceptionsOnSetters)
+                               .append("useJavaBeanIntrospector", 
useJavaBeanIntrospector)
+                               .append("beanFilters", beanFilters)
+                               .append("pojoSwaps", pojoSwaps)
+                               .append("notBeanClasses", notBeanClasses)
+                               .append("implClasses", implClasses)
+                               .append("sortProperties", sortProperties)
+                               .append("locale", locale)
+                               .append("timeZone", timeZone)
+                               .append("mediaType", mediaType)
+                               .append("includeProperties", includeProperties)
+                               .append("excludeProperties", excludeProperties)
+                       );
+       }
+}
\ No newline at end of file

Reply via email to