http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java 
b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
index 68c9341..a22242b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
@@ -56,7 +56,7 @@ public final class MsgPackParser extends InputStreamParser {
                BeanContext bc = session.getBeanContext();
                if (nt == null)
                        nt = (ClassMeta<T>)object();
-               PojoTransform<T,Object> transform = 
(PojoTransform<T,Object>)nt.getPojoTransform();
+               PojoSwap<T,Object> transform = 
(PojoSwap<T,Object>)nt.getPojoSwap();
                ClassMeta<?> ft = nt.getTransformedClassMeta();
                session.setCurrentClass(ft);
 
@@ -182,7 +182,7 @@ public final class MsgPackParser extends InputStreamParser {
                }
 
                if (transform != null && o != null)
-                       o = transform.normalize(o, nt);
+                       o = transform.unswap(o, nt);
 
                if (outer != null)
                        setParent(nt, o, outer);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java 
b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
index cd734b8..8795869 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
@@ -78,9 +78,9 @@ public class MsgPackSerializer extends OutputStreamSerializer 
{
                addClassAttr = (session.isAddClassAttrs() && ! 
eType.equals(aType));
 
                // Transform if necessary
-               PojoTransform transform = aType.getPojoTransform();             
                // The transform
+               PojoSwap transform = aType.getPojoSwap();                       
        // The transform
                if (transform != null) {
-                       o = transform.transform(o);
+                       o = transform.swap(o);
 
                        // If the transform's getTransformedClass() method 
returns Object, we need to figure out
                        // the actual type now.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/package.html 
b/juneau-core/src/main/java/org/apache/juneau/package.html
index 8b3d585..ca30bd5 100644
--- a/juneau-core/src/main/java/org/apache/juneau/package.html
+++ b/juneau-core/src/main/java/org/apache/juneau/package.html
@@ -157,10 +157,10 @@
        BeanContext beanContext = BeanContext.<jsf>DEFAULT</jsf>;
        
        <jc>// Create a context from scratch with your own settings.</jc>
-       beanContext = <jk>new</jk> 
BeanContext().addTransforms(DateTransform.ISO8601DT.<jk>class</jk>);
+       beanContext = <jk>new</jk> 
BeanContext().addTransforms(DateSwap.ISO8601DT.<jk>class</jk>);
        
        <jc>// Clone and modify an existing context.</jc>
-       beanContext = 
BeanContext.<jsf>DEFAULT</jsf>.clone().addTransforms(DateTransform.ISO8601DT.<jk>class</jk>);
+       beanContext = 
BeanContext.<jsf>DEFAULT</jsf>.clone().addTransforms(DateSwap.ISO8601DT.<jk>class</jk>);
                </p>
                <p>
                        The {@link org.apache.juneau.BeanContext} class is a 
highly-customizable class.  
@@ -204,7 +204,7 @@
                        Using the <ja>@Bean</ja> and <ja>@BeanProperty</ja> 
annotations, it's also possible to include non-standard properties (for 
example, getters or setters with non-standard names), or override the names of 
properties (for example, {@code "Name"} or {@code "fullName"} instead of {@code 
"name"}).
                </p>
                <p>
-                       It should be noted that the {@link 
org.apache.juneau.transform.BeanTransform} class can also be used to exclude 
properties from beans.  
+                       It should be noted that the {@link 
org.apache.juneau.transform.BeanFilter} class can also be used to exclude 
properties from beans.  
                        However, only the annotations can be used to include 
non-standard properties or override property names.
                </p>
                <p>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java 
b/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
index 1a1bd79..9a858b1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
@@ -94,10 +94,10 @@ import org.apache.juneau.utils.*;
  *             </tr>
  *     </table>
  * <p>
- *     In addition, any class types with {@link PojoTransform PojoTransforms} 
associated with them on the registered
+ *     In addition, any class types with {@link PojoSwap PojoSwaps} associated 
with them on the registered
  *             {@link #getBeanContext() beanContext} can also be passed in.
  * <p>
- *     For example, if the {@link CalendarTransform} transform is used to 
generalize {@code Calendar} objects to {@code String} objects.  When registered
+ *     For example, if the {@link CalendarSwap} transform is used to 
generalize {@code Calendar} objects to {@code String} objects.  When registered
  *     with this parser, you can construct {@code Calendar} objects from 
{@code Strings} using the following syntax...
  * <p class='bcode'>
  *     Calendar c = parser.parse(<js>"'Sun Mar 03 04:05:06 EST 2001'"</js>, 
GregorianCalendar.<jk>class</jk>);
@@ -579,7 +579,7 @@ public abstract class Parser extends CoreApi {
 
                if (type == null)
                        type = (ClassMeta<T>)object();
-               PojoTransform transform = type.getPojoTransform();
+               PojoSwap transform = type.getPojoSwap();
                ClassMeta<?> gType = type.getTransformedClassMeta();
 
                Object o = s;
@@ -600,7 +600,7 @@ public abstract class Parser extends CoreApi {
                }
 
                if (transform != null)
-                       o = transform.normalize(o, type);
+                       o = transform.unswap(o, type);
 
                return (T)o;
        }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java 
b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
index 0e810b8..4b86852 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
@@ -56,7 +56,7 @@ import org.apache.juneau.*;
  *
  *     <jc>// Change settings on parsers simultaneously</jc>
  *     g.setProperty(BeanContext.<jsf>BEAN_beansRequireSerializable</jsf>, 
<jk>true</jk>)
- *             .addTransforms(CalendarTransform.ISO8601DT.<jk>class</jk>)
+ *             .addTransforms(CalendarSwap.ISO8601DT.<jk>class</jk>)
  *             .lock();
  *
  *     <jc>// Find the appropriate parser by Content-Type</jc>
@@ -254,7 +254,7 @@ public final class ParserGroup extends Lockable {
        /**
         * Shortcut for calling {@link Parser#addTransforms(Class[])} on all 
parsers in this group.
         *
-        * @param classes The classes to add bean transforms for to the 
underlying bean context of all parsers in this group.
+        * @param classes The classes to add bean filters for to the underlying 
bean context of all parsers in this group.
         * @throws LockedException If {@link #lock()} was called on this object.
         * @return This object (for method chaining).
         */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java 
b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
index 36ab2b8..e3aeda1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
@@ -34,7 +34,7 @@ import org.apache.juneau.transform.*;
  *     Essentially just converts plain text to POJOs via static 
<code>fromString()</code> or <code>valueOf()</code>, or
  *     through constructors that take a single string argument.
  * <p>
- *     Also parses objects using a transform if the object class has an {@link 
PojoTransform PojoTransform&lt;?,String&gt;} transform defined on it.
+ *     Also parses objects using a transform if the object class has an {@link 
PojoSwap PojoSwap&lt;?,String&gt;} transform defined on it.
  *
  *
  * <h6 class='topic'>Configurable properties</h6>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
 
b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
index fd916f3..6be54ea 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
@@ -32,7 +32,7 @@ import org.apache.juneau.transform.*;
  * <p>
  *     Essentially converts POJOs to plain text using the 
<code>toString()</code> method.
  * <p>
- *     Also serializes objects using a transform if the object class has an 
{@link PojoTransform PojoTransform&lt;?,String&gt;} transform defined on it.
+ *     Also serializes objects using a transform if the object class has an 
{@link PojoSwap PojoSwap&lt;?,String&gt;} transform defined on it.
  *
  *
  * <h6 class='topic'>Configurable properties</h6>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
index 926075e..ef35199 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
@@ -56,7 +56,7 @@ import org.apache.juneau.*;
  *
  *     <jc>// Change settings for all serializers in the group and lock 
it.</jc>
  *     g.setProperty(SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, 
<jk>true</jk>)
- *             .addTransforms(CalendarTransform.ISO8601DT.<jk>class</jk>)
+ *             .addTransforms(CalendarSwap.ISO8601DT.<jk>class</jk>)
  *             .lock();
  *
  *     <jc>// Find the appropriate serializer by Accept type</jc>
@@ -277,7 +277,7 @@ public final class SerializerGroup extends Lockable {
        /**
         * Shortcut for calling {@link Serializer#addTransforms(Class[])} on 
all serializers in this group.
         *
-        * @param classes The classes to add bean transforms for to the 
underlying bean context of all serializers in this group.
+        * @param classes The classes to add bean filters for to the underlying 
bean context of all serializers in this group.
         * @throws LockedException If {@link #lock()} was called on this object.
         * @return This object (for method chaining).
         */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
index 0749066..f7d070a 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
@@ -537,10 +537,10 @@ public class SerializerSession extends Session {
        public final Object generalize(Object o, ClassMeta<?> type) throws 
SerializeException {
                if (o == null)
                        return null;
-               PojoTransform f = (type == null || type.isObject() ? 
getBeanContext().getClassMeta(o.getClass()).getPojoTransform() : 
type.getPojoTransform());
+               PojoSwap f = (type == null || type.isObject() ? 
getBeanContext().getClassMeta(o.getClass()).getPojoSwap() : type.getPojoSwap());
                if (f == null)
                        return o;
-               return f.transform(o);
+               return f.swap(o);
        }
 
        /**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilter.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilter.java
 
b/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilter.java
new file mode 100644
index 0000000..bf502b7
--- /dev/null
+++ 
b/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilter.java
@@ -0,0 +1,70 @@
+/***************************************************************************************************************************
+ * 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.transform;
+
+import java.util.*;
+
+import org.apache.juneau.annotation.*;
+
+/**
+ * Bean filter constructed from a {@link Bean @Bean} annotation found on a 
class.
+ * <p>
+ * <b>*** Internal class - Not intended for external use ***</b>
+ *
+ * @author James Bognar ([email protected])
+ * @param <T> The class type that this transform applies to.
+ */
+public final class AnnotationBeanFilter<T> extends BeanFilter<T> {
+
+       /**
+        * Constructor.
+        *
+        * @param annotatedClass The class found to have a {@link Bean @Bean} 
annotation.
+        * @param annotations The {@link Bean @Bean} annotations found on the 
class and all parent classes in child-to-parent order.
+        */
+       public AnnotationBeanFilter(Class<T> annotatedClass, List<Bean> 
annotations) {
+               super(annotatedClass);
+
+               ListIterator<Bean> li = 
annotations.listIterator(annotations.size());
+               while (li.hasPrevious()) {
+                       Bean b = li.previous();
+
+                       if (b.properties().length > 0 && getProperties() == 
null)
+                               setProperties(b.properties());
+
+                       if (b.sort())
+                               setSortProperties(true);
+
+                       if (b.excludeProperties().length > 0)
+                               setExcludeProperties(b.excludeProperties());
+
+                       setPropertyNamer(b.propertyNamer());
+
+                       if (b.interfaceClass() != Object.class)
+                               setInterfaceClass(b.interfaceClass());
+
+                       if (b.stopClass() != Object.class)
+                               setStopClass(b.stopClass());
+
+                       if (! b.subTypeProperty().isEmpty()) {
+                               setSubTypeProperty(b.subTypeProperty());
+
+                               LinkedHashMap<Class<?>,String> subTypes = new 
LinkedHashMap<Class<?>,String>();
+                               for (BeanSubType bst : b.subTypes())
+                                       subTypes.put(bst.type(), bst.id());
+
+                               setSubTypes(subTypes);
+                       }
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanTransform.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanTransform.java
 
b/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanTransform.java
deleted file mode 100644
index a6bc86f..0000000
--- 
a/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanTransform.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/***************************************************************************************************************************
- * 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.transform;
-
-import java.util.*;
-
-import org.apache.juneau.annotation.*;
-
-/**
- * Bean transform constructed from a {@link Bean @Bean} annotation found on a 
class.
- * <p>
- * <b>*** Internal class - Not intended for external use ***</b>
- *
- * @author James Bognar ([email protected])
- * @param <T> The class type that this transform applies to.
- */
-public final class AnnotationBeanTransform<T> extends BeanTransform<T> {
-
-       /**
-        * Constructor.
-        *
-        * @param annotatedClass The class found to have a {@link Bean @Bean} 
annotation.
-        * @param annotations The {@link Bean @Bean} annotations found on the 
class and all parent classes in child-to-parent order.
-        */
-       public AnnotationBeanTransform(Class<T> annotatedClass, List<Bean> 
annotations) {
-               super(annotatedClass);
-
-               ListIterator<Bean> li = 
annotations.listIterator(annotations.size());
-               while (li.hasPrevious()) {
-                       Bean b = li.previous();
-
-                       if (b.properties().length > 0 && getProperties() == 
null)
-                               setProperties(b.properties());
-
-                       if (b.sort())
-                               setSortProperties(true);
-
-                       if (b.excludeProperties().length > 0)
-                               setExcludeProperties(b.excludeProperties());
-
-                       setPropertyNamer(b.propertyNamer());
-
-                       if (b.interfaceClass() != Object.class)
-                               setInterfaceClass(b.interfaceClass());
-
-                       if (b.stopClass() != Object.class)
-                               setStopClass(b.stopClass());
-
-                       if (! b.subTypeProperty().isEmpty()) {
-                               setSubTypeProperty(b.subTypeProperty());
-
-                               LinkedHashMap<Class<?>,String> subTypes = new 
LinkedHashMap<Class<?>,String>();
-                               for (BeanSubType bst : b.subTypes())
-                                       subTypes.put(bst.type(), bst.id());
-
-                               setSubTypes(subTypes);
-                       }
-               }
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilter.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilter.java 
b/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilter.java
new file mode 100644
index 0000000..1538d0a
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilter.java
@@ -0,0 +1,526 @@
+/***************************************************************************************************************************
+ * 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.transform;
+
+import java.beans.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
+
+/**
+ * Parent class for all bean filters.
+ * <p>
+ *     Bean filters are used to control aspects of how beans are handled 
during serialization and parsing.
+ * <p>
+ *     This class can be considered a programmatic equivalent to using the 
{@link Bean @Bean} annotation on bean classes.
+ *     Thus, it can be used to perform the same function as the 
<code>@Bean</code> annotation when you don't have
+ *             the ability to annotate those classes (e.g. you don't have 
access to the source code).
+ * <p>
+ *     Note that value returned by the {@link Transform#forClass()} method is 
automatically determined through reflection
+ *             when the no-arg constructor is used.
+ *
+ * <p>
+ *     When defining bean filters, you can either call the setters in the 
contructor, or override getters.
+ *
+ * <h6 class='topic'>Example</h6>
+ * <p class='bcode'>
+ *     <jc>// Create our serializer with a filter.</jc>
+ *     WriterSerializer s = <jk>new</jk> 
JsonSerializer().addTransforms(AddressFilter.<jk>class</jk>);
+ *
+ *     Address a = <jk>new</jk> Address();
+ *     String json = s.serialize(a); <jc>// Serializes only street, city, 
state.</jc>
+ *
+ *     <jc>// Filter class defined via setters</jc>
+ *     <jk>public class</jk> AddressFilter <jk>extends</jk> 
BeanFilter&lt;Address&gt; {
+ *             <jk>public</jk> AddressFilter() {
+ *                     
setProperties(<js>"street"</js>,<js>"city"</js>,<js>"state"</js>);
+ *             }
+ *     }
+ *
+ *     <jc>// Filter class defined by overriding getters</jc>
+ *     <jk>public class</jk> AddressFilter <jk>extends</jk> 
BeanFilter&lt;Address&gt; {
+ *             <jk>public</jk> String[] getProperties() {
+ *                     <jk>return new</jk> 
String[]{<js>"street"</js>,<js>"city"</js>,<js>"state"</js>};
+ *             }
+ *     }
+ * </p>
+ * <p>
+ *     The examples in this class use the setters approach.
+ *
+ * <h6 class='topic'>Additional information</h6>
+ *     See {@link org.apache.juneau.transform} for more information.
+ *
+ *
+ * @author James Bognar ([email protected])
+ * @param <T> The class type that this filter applies to.
+ */
+public abstract class BeanFilter<T> extends Transform {
+
+       private String[] properties, excludeProperties;
+       private LinkedHashMap<Class<?>, String> subTypes;
+       private String subTypeAttr;
+       private Class<? extends PropertyNamer> propertyNamer;
+       private Class<?> interfaceClass, stopClass;
+       private boolean sortProperties;
+
+       /**
+        * Constructor that determines the for-class value using reflection.
+        */
+       @SuppressWarnings("unchecked")
+       public BeanFilter() {
+               super();
+               this.type = TransformType.BEAN;
+
+               Class<?> c = this.getClass().getSuperclass();
+               Type t = this.getClass().getGenericSuperclass();
+               while (c != BeanFilter.class) {
+                       t = c.getGenericSuperclass();
+                       c = c.getSuperclass();
+               }
+
+               // Attempt to determine the T and G classes using reflection.
+               if (t instanceof ParameterizedType) {
+                       ParameterizedType pt = (ParameterizedType)t;
+                       Type[] pta = pt.getActualTypeArguments();
+                       if (pta.length > 0) {
+                               Type nType = pta[0];
+                               if (nType instanceof Class)
+                                       this.forClass = (Class<T>)nType;
+
+                               else
+                                       throw new RuntimeException("Unsupported 
parameter type: " + nType);
+                       }
+               }
+       }
+
+       /**
+        * Constructor that specifies the for-class explicitly.
+        * <p>
+        * This constructor only needs to be called when the class type cannot 
be inferred through reflection.
+        *
+        * <dl>
+        *      <dt>Example:</dt>
+        *      <dd>
+        *              <p class='bcode'>
+        *      <jk>public class</jk> SomeArbitraryFilter <jk>extends</jk> 
BeanFilter&lt?&gt; {
+        *              <jk>public</jk> SomeArbitraryFiter(Class&lt?&gt; 
forClass) {
+        *                      <jk>super</jk>(forClass);
+        *                      ...
+        *              }
+        *      }
+        *              </p>
+        *      </dd>
+        * </dl>
+        *
+        * @param forClass The class that this bean filter applies to.
+        */
+       public BeanFilter(Class<T> forClass) {
+               super(forClass);
+               this.type = TransformType.BEAN;
+       }
+
+       /**
+        * Returns the set and order of names of properties associated with a 
bean class.
+        *
+        * @see #setProperties(String...)
+        * @return The name of the properties associated with a bean class, or 
<jk>null</jk> if all bean properties should be used.
+        */
+       public String[] getProperties() {
+               return properties;
+       }
+
+       /**
+        * Specifies the set and order of names of properties associated with a 
bean class.
+        * <p>
+        *      The order specified is the same order that the entries will be 
returned by the {@link BeanMap#entrySet()} and related methods.
+        * <p>
+        *      This method is an alternative to using the {@link 
Bean#properties()} annotation on a class.
+        *
+        * <dl>
+        *      <dt>Example:</dt>
+        *      <dd>
+        *              <p class='bcode'>
+        *      <jc>// Create our serializer with a filter.</jc>
+        *      WriterSerializer s = <jk>new</jk> 
JsonSerializer().addTransforms(AddressFilter.<jk>class</jk>);
+        *
+        *      Address a = <jk>new</jk> Address();
+        *      String json = s.serialize(a); <jc>// Serializes only street, 
city, state.</jc>
+        *
+        *      <jc>// Transform class</jc>
+        *      <jk>public class</jk> AddressFilter <jk>extends</jk> 
BeanFilter&lt;Address&gt; {
+        *              <jk>public</jk> AddressFilter() {
+        *                      
setProperties(<js>"street"</js>,<js>"city"</js>,<js>"state"</js>);
+        *              }
+        *      }
+        *              </p>
+        *      </dd>
+        * </dl>
+        *
+        * @param properties The name of the properties associated with a bean 
class.
+        * @return This object (for method chaining).
+        */
+       public BeanFilter<T> setProperties(String...properties) {
+               this.properties = properties;
+               return this;
+       }
+
+       /**
+        * Same as {@link #setProperties(String[])} but pass in a 
comma-delimited list of values.
+        *
+        * @param properties A comma-delimited list of properties.
+        * @return This object (for method chaining).
+        */
+       public BeanFilter<T> setProperties(String properties) {
+               return setProperties(StringUtils.split(properties, ','));
+       }
+
+       /**
+        * Returns <jk>true</jk> if the properties defined on this bean class 
should be ordered alphabetically.
+        * <p>
+        *      This method is only used when the {@link #getProperties()} 
method returns <jk>null</jk>.
+        *      Otherwise, the ordering of the properties in the returned value 
is used.
+        *
+        * @see #setSortProperties(boolean)
+        * @return <jk>true</jk> if bean properties should be sorted.
+        */
+       public boolean isSortProperties() {
+               return sortProperties;
+       }
+
+       /**
+        * Specifies whether the properties on this bean should be ordered 
alphabetically.
+        * <p>
+        *      This method is ignored if the {@link #getProperties()} method 
does not return <jk>null</jk>.
+        * <p>
+        *      This method is an alternative to using the {@link Bean#sort()} 
annotation on a class.
+        *
+        * @param sortProperties The new value for the sort properties property.
+        * @return This object (for method chaining).
+        */
+       public BeanFilter<T> setSortProperties(boolean sortProperties) {
+               this.sortProperties = sortProperties;
+               return this;
+       }
+
+       /**
+        * Returns the list of properties to ignore on a bean.
+        *
+        * @see #setExcludeProperties(String...)
+        * @return The name of the properties to ignore on a bean, or 
<jk>null</jk> to not ignore any properties.
+        */
+       public String[] getExcludeProperties() {
+               return excludeProperties;
+       }
+
+       /**
+        * Specifies a list of properties to ignore on a bean.
+        * <p>
+        *      This method is an alternative to using the {@link 
Bean#excludeProperties()} annotation on a class.
+        *
+        * <dl>
+        *      <dt>Example:</dt>
+        *      <dd>
+        *              <p class='bcode'>
+        *      <jc>// Create our serializer with a filter.</jc>
+        *      WriterSerializer s = <jk>new</jk> 
JsonSerializer().addTransforms(NoCityOrStateFilter.<jk>class</jk>);
+        *
+        *      Address a = <jk>new</jk> Address();
+        *      String json = s.serialize(a); <jc>// Excludes city and 
state.</jc>
+        *
+        *      <jc>// Transform class</jc>
+        *      <jk>public class</jk> NoCityOrStateFilter <jk>extends</jk> 
BeanFilter&lt;Address&gt; {
+        *              <jk>public</jk> AddressFilter() {
+        *                      
setExcludeProperties(<js>"city"</js>,<js>"state"</js>);
+        *              }
+        *      }
+        *              </p>
+        *      </dd>
+        * </dl>
+        *
+        * @param excludeProperties The name of the properties to ignore on a 
bean class.
+        * @return This object (for method chaining).
+        */
+       public BeanFilter<T> setExcludeProperties(String...excludeProperties) {
+               this.excludeProperties = excludeProperties;
+               return this;
+       }
+
+       /**
+        * Same as {@link #setExcludeProperties(String[])} but pass in a 
comma-delimited list of values.
+        *
+        * @param excludeProperties A comma-delimited list of properties to 
eclipse.
+        * @return This object (for method chaining).
+        */
+       public BeanFilter<T> setExcludeProperties(String excludeProperties) {
+               return 
setExcludeProperties(StringUtils.split(excludeProperties, ','));
+       }
+
+       /**
+        * Returns the {@link PropertyNamer} associated with the bean to tailor 
the names of bean properties.
+        *
+        * @see #setPropertyNamer(Class)
+        * @return The property namer class, or <jk>null</jk> if no property 
namer is associated with this bean property.
+        */
+       public Class<? extends PropertyNamer> getPropertyNamer() {
+               return propertyNamer;
+       }
+
+       /**
+        * Associates a {@link PropertyNamer} with this bean to tailor the 
names of the bean properties.
+        * <p>
+        *      Property namers are used to transform bean property names from 
standard form to some other form.
+        *      For example, the {@link PropertyNamerDashedLC} will convert 
property names to dashed-lowercase, and
+        *              these will be used as attribute names in JSON, and 
element names in XML.
+        * <p>
+        *      This method is an alternative to using the {@link 
Bean#propertyNamer()} annotation on a class.
+        *
+        * @param propertyNamer The property namer class.
+        * @return This object (for method chaining).
+        */
+       public BeanFilter<T> setPropertyNamer(Class<? extends PropertyNamer> 
propertyNamer) {
+               this.propertyNamer = propertyNamer;
+               return this;
+       }
+
+       /**
+        * Returns the name of the sub type property associated with the bean 
class.
+        *
+        * @see #setSubTypeProperty(String)
+        * @return The sub type property name, or <jk>null</jk> if bean has no 
subtypes defined.
+        */
+       public String getSubTypeProperty() {
+               return subTypeAttr;
+       }
+
+       /**
+        * Defines a virtual property on a superclass that identifies bean 
subtype classes.
+        * <p>
+        *      In the following example, the abstract class has two subclasses 
that are differentiated
+        *              by a property called <code>subType</code>
+        *
+        * <p class='bcode'>
+        *      <jc>// Abstract superclass</jc>
+        *      <jk>public abstract class</jk> A {
+        *              <jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>;
+        *      }
+        *
+        *      <jc>// Subclass 1</jc>
+        *      <jk>public class</jk> A1 <jk>extends</jk> A {
+        *              <jk>public</jk> String <jf>f1</jf>;
+        *      }
+        *
+        *      <jc>// Subclass 2</jc>
+        *      <jk>public class</jk> A2 <jk>extends</jk> A {
+        *              <jk>public</jk> String <jf>f2</jf>;
+        *      }
+        *
+        *      <jc>// Transform for defining subtypes</jc>
+        *      <jk>public class</jk> ATransform <jk>extends</jk> 
BeanFilter&lt;A&gt; {
+        *              <jk>public</jk> ATransform() {
+        *                      setSubTypeProperty(<js>"subType"</js>);
+        *                      addSubType(Al.<jk>class</jk>, <js>"A1"</js>);
+        *                      addSubType(A2.<jk>class</jk>, <js>"A2"</js>);
+        *              }
+        *      }
+        * </p>
+        * <p>
+        *      The following shows what happens when serializing a subclassed 
object to JSON:
+        * <p class='bcode'>
+        *      JsonSerializer s = <jk>new</jk> 
JsonSerializer().addTransforms(ATransform.<jk>class</jk>);
+        *      A1 a1 = <jk>new</jk> A1();
+        *      a1.<jf>f1</jf> = <js>"f1"</js>;
+        *      String r = s.serialize(a1);
+        *      
<jsm>assertEquals</jsm>(<js>"{subType:'A1',f1:'f1',f0:'f0'}"</js>, r);
+        * </p>
+        * <p>
+        *      The following shows what happens when parsing back into the 
original object.
+        * <p class='bcode'>
+        *      JsonParser p = <jk>new</jk> 
JsonParser().addTransforms(ATransform.<jk>class</jk>);
+        *      A a = p.parse(r, A.<jk>class</jk>);
+        *      <jsm>assertTrue</jsm>(a <jk>instanceof</jk> A1);
+        * </p>
+        * <p>
+        *      This method is an alternative to using the {@link 
Bean#subTypeProperty()} annotation on a class.
+        *
+        * @param subTypeAttr The name of the attribute representing the 
subtype.
+        * @return This object (for method chaining).
+        */
+       public BeanFilter<T> setSubTypeProperty(String subTypeAttr) {
+               this.subTypeAttr = subTypeAttr;
+               return this;
+       }
+
+       /**
+        * Returns the subtypes associated with the bean class.
+        *
+        * @see #setSubTypeProperty(String)
+        * @return The set of sub types associated with this bean class, or 
<jk>null</jk> if bean has no subtypes defined.
+        */
+       public LinkedHashMap<Class<?>, String> getSubTypes() {
+               return subTypes;
+       }
+
+       /**
+        * Specifies the set of subclasses of this bean class in addition to a 
string identifier for that subclass.
+        *
+        * @see #setSubTypeProperty(String)
+        * @param subTypes the map of subtype classes to subtype identifier 
strings.
+        * @return This object (for method chaining).
+        */
+       public BeanFilter<T> setSubTypes(LinkedHashMap<Class<?>, String> 
subTypes) {
+               this.subTypes = subTypes;
+               return this;
+       }
+
+       /**
+        * Convenience method for adding a single subtype in leu of using 
{@link #setSubTypes(LinkedHashMap)} in one call.
+        *
+        * @see #setSubTypeProperty(String)
+        * @param c The subtype class.
+        * @param id The subtype identifier string for the specified subtype 
class.
+        * @return This object (for method chaining).
+        */
+       public BeanFilter<T> addSubType(Class<?> c, String id) {
+               if (subTypes == null)
+                       subTypes = new LinkedHashMap<Class<?>, String>();
+               subTypes.put(c, id);
+               return this;
+       }
+
+       /**
+        * Returns the interface class associated with this class.
+        *
+        * @see #setInterfaceClass(Class)
+        * @return The interface class associated with this class, or 
<jk>null</jk> if no interface class is associated.
+        */
+       public Class<?> getInterfaceClass() {
+               return interfaceClass;
+       }
+
+       /**
+        * Identifies a class to be used as the interface class for this and 
all subclasses.
+        * <p>
+        *      Functionally equivalent to using the {@link 
Bean#interfaceClass()} annotation.
+        * <p>
+        *      When specified, only the list of properties defined on the 
interface class will be used during serialization.
+        *      Additional properties on subclasses will be ignored.
+        * <p class='bcode'>
+        *      <jc>// Parent class</jc>
+        *      <jk>public abstract class</jk> A {
+        *              <jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>;
+        *      }
+        *
+        *      <jc>// Sub class</jc>
+        *      <jk>public class</jk> A1 <jk>extends</jk> A {
+        *              <jk>public</jk> String <jf>f1</jf> = <js>"f1"</js>;
+        *      }
+        *
+        *      <jc>// Transform class</jc>
+        *      <jk>public class</jk> ATransform <jk>extends</jk> 
BeanFilter&lt;A&gt; {
+        *              <jk>public</jk> ATransform() {
+        *                      setInterfaceClass(A.<jk>class</jk>);
+        *              }
+        *      }
+        *
+        *      JsonSerializer s = new 
JsonSerializer().addTransforms(ATransform.<jk>class</jk>);
+        *      A1 a1 = <jk>new</jk> A1();
+        *      String r = s.serialize(a1);
+        *      <jsm>assertEquals</jsm>(<js>"{f0:'f0'}"</js>, r);  <jc>// Note 
f1 is not serialized</jc>
+        * </p>
+        * <p>
+        *      Note that this filter can be used on the parent class so that 
it filters to all child classes,
+        *              or can be set individually on the child classes.
+        * <p>
+        *      This method is an alternative to using the {@link 
Bean#interfaceClass()}} annotation.
+        *
+        * @param interfaceClass The interface class.
+        * @return This object (for method chaining).
+        */
+       public BeanFilter<T> setInterfaceClass(Class<?> interfaceClass) {
+               this.interfaceClass = interfaceClass;
+               return this;
+       }
+
+       /**
+        * Returns the stop class associated with this class.
+        *
+        * @see #setStopClass(Class)
+        * @return The stop class associated with this class, or <jk>null</jk> 
if no stop class is associated.
+        */
+       public Class<?> getStopClass() {
+               return stopClass;
+       }
+
+       /**
+        * Identifies a stop class for this class and all subclasses.
+        * <p>
+        *      Functionally equivalent to using the {@link Bean#stopClass()} 
annotation.
+        * <p>
+        *      Identical in purpose to the stop class specified by {@link 
Introspector#getBeanInfo(Class, Class)}.
+        *      Any properties in the stop class or in its baseclasses will be 
ignored during analysis.
+        * <p>
+        *      For example, in the following class hierarchy, instances of 
<code>C3</code> will include property <code>p3</code>, but
+        *              not <code>p1</code> or <code>p2</code>.
+        * <p class='bcode'>
+        *      <jk>public class</jk> C1 {
+        *              <jk>public int</jk> getP1();
+        *      }
+        *
+        *      <jk>public class</jk> C2 <jk>extends</jk> C1 {
+        *              <jk>public int</jk> getP2();
+        *      }
+        *
+        *      <ja>@Bean</ja>(stopClass=C2.<jk>class</jk>)
+        *      <jk>public class</jk> C3 <jk>extends</jk> C2 {
+        *              <jk>public int</jk> getP3();
+        *      }
+        * </p>
+        *
+        * @param stopClass The stop class.
+        * @return This object (for method chaining).
+        */
+       public BeanFilter<T> setStopClass(Class<?> stopClass) {
+               this.stopClass = stopClass;
+               return this;
+       }
+
+       /**
+        * Subclasses can override this property to convert property values to 
some other
+        *      object just before serialization.
+        *
+        * @param bean The bean from which the property was read.
+        * @param name The property name.
+        * @param value The value just extracted from calling the bean getter.
+        * @return The value to serialize.  Default is just to return the 
existing value.
+        */
+       public Object readProperty(Object bean, String name, Object value) {
+               return value;
+       }
+
+       /**
+        * Subclasses can override this property to convert property values to 
some other
+        *      object just before calling the bean setter.
+        *
+        * @param bean The bean from which the property was read.
+        * @param name The property name.
+        * @param value The value just parsed.
+        * @return <jk>true</jk> if we set the property, <jk>false</jk> if we 
should allow the
+        *      framework to call the setter.
+        */
+       public boolean writeProperty(Object bean, String name, Object value) {
+               return false;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/BeanTransform.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/transform/BeanTransform.java 
b/juneau-core/src/main/java/org/apache/juneau/transform/BeanTransform.java
deleted file mode 100644
index f0b9f3c..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/transform/BeanTransform.java
+++ /dev/null
@@ -1,526 +0,0 @@
-/***************************************************************************************************************************
- * 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.transform;
-
-import java.beans.*;
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.annotation.*;
-import org.apache.juneau.internal.*;
-
-/**
- * Parent class for all bean transforms.
- * <p>
- *     Bean transforms are used to control aspects of how beans are handled 
during serialization and parsing.
- * <p>
- *     This class can be considered a programmatic equivalent to using the 
{@link Bean @Bean} annotation on bean classes.
- *     Thus, it can be used to perform the same function as the 
<code>@Bean</code> annotation when you don't have
- *             the ability to annotate those classes (e.g. you don't have 
access to the source code).
- * <p>
- *     Note that value returned by the {@link Transform#forClass()} method is 
automatically determined through reflection
- *             when the no-arg constructor is used.
- *
- * <p>
- *     When defining bean transforms, you can either call the setters in the 
contructor, or override getters.
- *
- * <h6 class='topic'>Example</h6>
- * <p class='bcode'>
- *     <jc>// Create our serializer with a transform.</jc>
- *     WriterSerializer s = <jk>new</jk> 
JsonSerializer().addTransforms(AddressTransform.<jk>class</jk>);
- *
- *     Address a = <jk>new</jk> Address();
- *     String json = s.serialize(a); <jc>// Serializes only street, city, 
state.</jc>
- *
- *     <jc>// Transform class defined via setters</jc>
- *     <jk>public class</jk> AddressTransform <jk>extends</jk> 
BeanTransform&lt;Address&gt; {
- *             <jk>public</jk> AddressTransform() {
- *                     
setProperties(<js>"street"</js>,<js>"city"</js>,<js>"state"</js>);
- *             }
- *     }
- *
- *     <jc>// Transform class defined by overriding getters</jc>
- *     <jk>public class</jk> AddressTransform <jk>extends</jk> 
BeanTransform&lt;Address&gt; {
- *             <jk>public</jk> String[] getProperties() {
- *                     <jk>return new</jk> 
String[]{<js>"street"</js>,<js>"city"</js>,<js>"state"</js>};
- *             }
- *     }
- * </p>
- * <p>
- *     The examples in this class use the setters approach.
- *
- * <h6 class='topic'>Additional information</h6>
- *     See {@link org.apache.juneau.transform} for more information.
- *
- *
- * @author James Bognar ([email protected])
- * @param <T> The class type that this transform applies to.
- */
-public abstract class BeanTransform<T> extends Transform {
-
-       private String[] properties, excludeProperties;
-       private LinkedHashMap<Class<?>, String> subTypes;
-       private String subTypeAttr;
-       private Class<? extends PropertyNamer> propertyNamer;
-       private Class<?> interfaceClass, stopClass;
-       private boolean sortProperties;
-
-       /**
-        * Constructor that determines the for-class value using reflection.
-        */
-       @SuppressWarnings("unchecked")
-       public BeanTransform() {
-               super();
-               this.type = TransformType.BEAN;
-
-               Class<?> c = this.getClass().getSuperclass();
-               Type t = this.getClass().getGenericSuperclass();
-               while (c != BeanTransform.class) {
-                       t = c.getGenericSuperclass();
-                       c = c.getSuperclass();
-               }
-
-               // Attempt to determine the T and G classes using reflection.
-               if (t instanceof ParameterizedType) {
-                       ParameterizedType pt = (ParameterizedType)t;
-                       Type[] pta = pt.getActualTypeArguments();
-                       if (pta.length > 0) {
-                               Type nType = pta[0];
-                               if (nType instanceof Class)
-                                       this.forClass = (Class<T>)nType;
-
-                               else
-                                       throw new RuntimeException("Unsupported 
parameter type: " + nType);
-                       }
-               }
-       }
-
-       /**
-        * Constructor that specifies the for-class explicitly.
-        * <p>
-        * This constructor only needs to be called when the class type cannot 
be inferred through reflection.
-        *
-        * <dl>
-        *      <dt>Example:</dt>
-        *      <dd>
-        *              <p class='bcode'>
-        *      <jk>public class</jk> SomeArbitraryTransform <jk>extends</jk> 
BeanTransform&lt?&gt; {
-        *              <jk>public</jk> SomeArbitraryTransform(Class&lt?&gt; 
forClass) {
-        *                      <jk>super</jk>(forClass);
-        *                      ...
-        *              }
-        *      }
-        *              </p>
-        *      </dd>
-        * </dl>
-        *
-        * @param forClass The class that this bean transform applies to.
-        */
-       public BeanTransform(Class<T> forClass) {
-               super(forClass);
-               this.type = TransformType.BEAN;
-       }
-
-       /**
-        * Returns the set and order of names of properties associated with a 
bean class.
-        *
-        * @see #setProperties(String...)
-        * @return The name of the properties associated with a bean class, or 
<jk>null</jk> if all bean properties should be used.
-        */
-       public String[] getProperties() {
-               return properties;
-       }
-
-       /**
-        * Specifies the set and order of names of properties associated with a 
bean class.
-        * <p>
-        *      The order specified is the same order that the entries will be 
returned by the {@link BeanMap#entrySet()} and related methods.
-        * <p>
-        *      This method is an alternative to using the {@link 
Bean#properties()} annotation on a class.
-        *
-        * <dl>
-        *      <dt>Example:</dt>
-        *      <dd>
-        *              <p class='bcode'>
-        *      <jc>// Create our serializer with a transform.</jc>
-        *      WriterSerializer s = <jk>new</jk> 
JsonSerializer().addTransforms(AddressTransform.<jk>class</jk>);
-        *
-        *      Address a = <jk>new</jk> Address();
-        *      String json = s.serialize(a); <jc>// Serializes only street, 
city, state.</jc>
-        *
-        *      <jc>// Transform class</jc>
-        *      <jk>public class</jk> AddressTransform <jk>extends</jk> 
BeanTransform&lt;Address&gt; {
-        *              <jk>public</jk> AddressTransform() {
-        *                      
setProperties(<js>"street"</js>,<js>"city"</js>,<js>"state"</js>);
-        *              }
-        *      }
-        *              </p>
-        *      </dd>
-        * </dl>
-        *
-        * @param properties The name of the properties associated with a bean 
class.
-        * @return This object (for method chaining).
-        */
-       public BeanTransform<T> setProperties(String...properties) {
-               this.properties = properties;
-               return this;
-       }
-
-       /**
-        * Same as {@link #setProperties(String[])} but pass in a 
comma-delimited list of values.
-        *
-        * @param properties A comma-delimited list of properties.
-        * @return This object (for method chaining).
-        */
-       public BeanTransform<T> setProperties(String properties) {
-               return setProperties(StringUtils.split(properties, ','));
-       }
-
-       /**
-        * Returns <jk>true</jk> if the properties defined on this bean class 
should be ordered alphabetically.
-        * <p>
-        *      This method is only used when the {@link #getProperties()} 
method returns <jk>null</jk>.
-        *      Otherwise, the ordering of the properties in the returned value 
is used.
-        *
-        * @see #setSortProperties(boolean)
-        * @return <jk>true</jk> if bean properties should be sorted.
-        */
-       public boolean isSortProperties() {
-               return sortProperties;
-       }
-
-       /**
-        * Specifies whether the properties on this bean should be ordered 
alphabetically.
-        * <p>
-        *      This method is ignored if the {@link #getProperties()} method 
does not return <jk>null</jk>.
-        * <p>
-        *      This method is an alternative to using the {@link Bean#sort()} 
annotation on a class.
-        *
-        * @param sortProperties The new value for the sort properties property.
-        * @return This object (for method chaining).
-        */
-       public BeanTransform<T> setSortProperties(boolean sortProperties) {
-               this.sortProperties = sortProperties;
-               return this;
-       }
-
-       /**
-        * Returns the list of properties to ignore on a bean.
-        *
-        * @see #setExcludeProperties(String...)
-        * @return The name of the properties to ignore on a bean, or 
<jk>null</jk> to not ignore any properties.
-        */
-       public String[] getExcludeProperties() {
-               return excludeProperties;
-       }
-
-       /**
-        * Specifies a list of properties to ignore on a bean.
-        * <p>
-        *      This method is an alternative to using the {@link 
Bean#excludeProperties()} annotation on a class.
-        *
-        * <dl>
-        *      <dt>Example:</dt>
-        *      <dd>
-        *              <p class='bcode'>
-        *      <jc>// Create our serializer with a transform.</jc>
-        *      WriterSerializer s = <jk>new</jk> 
JsonSerializer().addTransforms(NoCityOrStateTransform.<jk>class</jk>);
-        *
-        *      Address a = <jk>new</jk> Address();
-        *      String json = s.serialize(a); <jc>// Excludes city and 
state.</jc>
-        *
-        *      <jc>// Transform class</jc>
-        *      <jk>public class</jk> NoCityOrStateTransform <jk>extends</jk> 
BeanTransform&lt;Address&gt; {
-        *              <jk>public</jk> AddressTransform() {
-        *                      
setExcludeProperties(<js>"city"</js>,<js>"state"</js>);
-        *              }
-        *      }
-        *              </p>
-        *      </dd>
-        * </dl>
-        *
-        * @param excludeProperties The name of the properties to ignore on a 
bean class.
-        * @return This object (for method chaining).
-        */
-       public BeanTransform<T> 
setExcludeProperties(String...excludeProperties) {
-               this.excludeProperties = excludeProperties;
-               return this;
-       }
-
-       /**
-        * Same as {@link #setExcludeProperties(String[])} but pass in a 
comma-delimited list of values.
-        *
-        * @param excludeProperties A comma-delimited list of properties to 
eclipse.
-        * @return This object (for method chaining).
-        */
-       public BeanTransform<T> setExcludeProperties(String excludeProperties) {
-               return 
setExcludeProperties(StringUtils.split(excludeProperties, ','));
-       }
-
-       /**
-        * Returns the {@link PropertyNamer} associated with the bean to tailor 
the names of bean properties.
-        *
-        * @see #setPropertyNamer(Class)
-        * @return The property namer class, or <jk>null</jk> if no property 
namer is associated with this bean property.
-        */
-       public Class<? extends PropertyNamer> getPropertyNamer() {
-               return propertyNamer;
-       }
-
-       /**
-        * Associates a {@link PropertyNamer} with this bean to tailor the 
names of the bean properties.
-        * <p>
-        *      Property namers are used to transform bean property names from 
standard form to some other form.
-        *      For example, the {@link PropertyNamerDashedLC} will convert 
property names to dashed-lowercase, and
-        *              these will be used as attribute names in JSON, and 
element names in XML.
-        * <p>
-        *      This method is an alternative to using the {@link 
Bean#propertyNamer()} annotation on a class.
-        *
-        * @param propertyNamer The property namer class.
-        * @return This object (for method chaining).
-        */
-       public BeanTransform<T> setPropertyNamer(Class<? extends PropertyNamer> 
propertyNamer) {
-               this.propertyNamer = propertyNamer;
-               return this;
-       }
-
-       /**
-        * Returns the name of the sub type property associated with the bean 
class.
-        *
-        * @see #setSubTypeProperty(String)
-        * @return The sub type property name, or <jk>null</jk> if bean has no 
subtypes defined.
-        */
-       public String getSubTypeProperty() {
-               return subTypeAttr;
-       }
-
-       /**
-        * Defines a virtual property on a superclass that identifies bean 
subtype classes.
-        * <p>
-        *      In the following example, the abstract class has two subclasses 
that are differentiated
-        *              by a property called <code>subType</code>
-        *
-        * <p class='bcode'>
-        *      <jc>// Abstract superclass</jc>
-        *      <jk>public abstract class</jk> A {
-        *              <jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>;
-        *      }
-        *
-        *      <jc>// Subclass 1</jc>
-        *      <jk>public class</jk> A1 <jk>extends</jk> A {
-        *              <jk>public</jk> String <jf>f1</jf>;
-        *      }
-        *
-        *      <jc>// Subclass 2</jc>
-        *      <jk>public class</jk> A2 <jk>extends</jk> A {
-        *              <jk>public</jk> String <jf>f2</jf>;
-        *      }
-        *
-        *      <jc>// Transform for defining subtypes</jc>
-        *      <jk>public class</jk> ATransform <jk>extends</jk> 
BeanTransform&lt;A&gt; {
-        *              <jk>public</jk> ATransform() {
-        *                      setSubTypeProperty(<js>"subType"</js>);
-        *                      addSubType(Al.<jk>class</jk>, <js>"A1"</js>);
-        *                      addSubType(A2.<jk>class</jk>, <js>"A2"</js>);
-        *              }
-        *      }
-        * </p>
-        * <p>
-        *      The following shows what happens when serializing a subclassed 
object to JSON:
-        * <p class='bcode'>
-        *      JsonSerializer s = <jk>new</jk> 
JsonSerializer().addTransforms(ATransform.<jk>class</jk>);
-        *      A1 a1 = <jk>new</jk> A1();
-        *      a1.<jf>f1</jf> = <js>"f1"</js>;
-        *      String r = s.serialize(a1);
-        *      
<jsm>assertEquals</jsm>(<js>"{subType:'A1',f1:'f1',f0:'f0'}"</js>, r);
-        * </p>
-        * <p>
-        *      The following shows what happens when parsing back into the 
original object.
-        * <p class='bcode'>
-        *      JsonParser p = <jk>new</jk> 
JsonParser().addTransforms(ATransform.<jk>class</jk>);
-        *      A a = p.parse(r, A.<jk>class</jk>);
-        *      <jsm>assertTrue</jsm>(a <jk>instanceof</jk> A1);
-        * </p>
-        * <p>
-        *      This method is an alternative to using the {@link 
Bean#subTypeProperty()} annotation on a class.
-        *
-        * @param subTypeAttr The name of the attribute representing the 
subtype.
-        * @return This object (for method chaining).
-        */
-       public BeanTransform<T> setSubTypeProperty(String subTypeAttr) {
-               this.subTypeAttr = subTypeAttr;
-               return this;
-       }
-
-       /**
-        * Returns the subtypes associated with the bean class.
-        *
-        * @see #setSubTypeProperty(String)
-        * @return The set of sub types associated with this bean class, or 
<jk>null</jk> if bean has no subtypes defined.
-        */
-       public LinkedHashMap<Class<?>, String> getSubTypes() {
-               return subTypes;
-       }
-
-       /**
-        * Specifies the set of subclasses of this bean class in addition to a 
string identifier for that subclass.
-        *
-        * @see #setSubTypeProperty(String)
-        * @param subTypes the map of subtype classes to subtype identifier 
strings.
-        * @return This object (for method chaining).
-        */
-       public BeanTransform<T> setSubTypes(LinkedHashMap<Class<?>, String> 
subTypes) {
-               this.subTypes = subTypes;
-               return this;
-       }
-
-       /**
-        * Convenience method for adding a single subtype in leu of using 
{@link #setSubTypes(LinkedHashMap)} in one call.
-        *
-        * @see #setSubTypeProperty(String)
-        * @param c The subtype class.
-        * @param id The subtype identifier string for the specified subtype 
class.
-        * @return This object (for method chaining).
-        */
-       public BeanTransform<T> addSubType(Class<?> c, String id) {
-               if (subTypes == null)
-                       subTypes = new LinkedHashMap<Class<?>, String>();
-               subTypes.put(c, id);
-               return this;
-       }
-
-       /**
-        * Returns the interface class associated with this class.
-        *
-        * @see #setInterfaceClass(Class)
-        * @return The interface class associated with this class, or 
<jk>null</jk> if no interface class is associated.
-        */
-       public Class<?> getInterfaceClass() {
-               return interfaceClass;
-       }
-
-       /**
-        * Identifies a class to be used as the interface class for this and 
all subclasses.
-        * <p>
-        *      Functionally equivalent to using the {@link 
Bean#interfaceClass()} annotation.
-        * <p>
-        *      When specified, only the list of properties defined on the 
interface class will be used during serialization.
-        *      Additional properties on subclasses will be ignored.
-        * <p class='bcode'>
-        *      <jc>// Parent class</jc>
-        *      <jk>public abstract class</jk> A {
-        *              <jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>;
-        *      }
-        *
-        *      <jc>// Sub class</jc>
-        *      <jk>public class</jk> A1 <jk>extends</jk> A {
-        *              <jk>public</jk> String <jf>f1</jf> = <js>"f1"</js>;
-        *      }
-        *
-        *      <jc>// Transform class</jc>
-        *      <jk>public class</jk> ATransform <jk>extends</jk> 
BeanTransform&lt;A&gt; {
-        *              <jk>public</jk> ATransform() {
-        *                      setInterfaceClass(A.<jk>class</jk>);
-        *              }
-        *      }
-        *
-        *      JsonSerializer s = new 
JsonSerializer().addTransforms(ATransform.<jk>class</jk>);
-        *      A1 a1 = <jk>new</jk> A1();
-        *      String r = s.serialize(a1);
-        *      <jsm>assertEquals</jsm>(<js>"{f0:'f0'}"</js>, r);  <jc>// Note 
f1 is not serialized</jc>
-        * </p>
-        * <p>
-        *      Note that this transform can be used on the parent class so 
that it transforms to all child classes,
-        *              or can be set individually on the child classes.
-        * <p>
-        *      This method is an alternative to using the {@link 
Bean#interfaceClass()}} annotation.
-        *
-        * @param interfaceClass The interface class.
-        * @return This object (for method chaining).
-        */
-       public BeanTransform<T> setInterfaceClass(Class<?> interfaceClass) {
-               this.interfaceClass = interfaceClass;
-               return this;
-       }
-
-       /**
-        * Returns the stop class associated with this class.
-        *
-        * @see #setStopClass(Class)
-        * @return The stop class associated with this class, or <jk>null</jk> 
if no stop class is associated.
-        */
-       public Class<?> getStopClass() {
-               return stopClass;
-       }
-
-       /**
-        * Identifies a stop class for this class and all subclasses.
-        * <p>
-        *      Functionally equivalent to using the {@link Bean#stopClass()} 
annotation.
-        * <p>
-        *      Identical in purpose to the stop class specified by {@link 
Introspector#getBeanInfo(Class, Class)}.
-        *      Any properties in the stop class or in its baseclasses will be 
ignored during analysis.
-        * <p>
-        *      For example, in the following class hierarchy, instances of 
<code>C3</code> will include property <code>p3</code>, but
-        *              not <code>p1</code> or <code>p2</code>.
-        * <p class='bcode'>
-        *      <jk>public class</jk> C1 {
-        *              <jk>public int</jk> getP1();
-        *      }
-        *
-        *      <jk>public class</jk> C2 <jk>extends</jk> C1 {
-        *              <jk>public int</jk> getP2();
-        *      }
-        *
-        *      <ja>@Bean</ja>(stopClass=C2.<jk>class</jk>)
-        *      <jk>public class</jk> C3 <jk>extends</jk> C2 {
-        *              <jk>public int</jk> getP3();
-        *      }
-        * </p>
-        *
-        * @param stopClass The stop class.
-        * @return This object (for method chaining).
-        */
-       public BeanTransform<T> setStopClass(Class<?> stopClass) {
-               this.stopClass = stopClass;
-               return this;
-       }
-
-       /**
-        * Subclasses can override this property to convert property values to 
some other
-        *      object just before serialization.
-        *
-        * @param bean The bean from which the property was read.
-        * @param name The property name.
-        * @param value The value just extracted from calling the bean getter.
-        * @return The value to serialize.  Default is just to return the 
existing value.
-        */
-       public Object readProperty(Object bean, String name, Object value) {
-               return value;
-       }
-
-       /**
-        * Subclasses can override this property to convert property values to 
some other
-        *      object just before calling the bean setter.
-        *
-        * @param bean The bean from which the property was read.
-        * @param name The property name.
-        * @param value The value just parsed.
-        * @return <jk>true</jk> if we set the property, <jk>false</jk> if we 
should allow the
-        *      framework to call the setter.
-        */
-       public boolean writeProperty(Object bean, String name, Object value) {
-               return false;
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanFilter.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanFilter.java
 
b/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanFilter.java
new file mode 100644
index 0000000..2e9f95c
--- /dev/null
+++ 
b/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanFilter.java
@@ -0,0 +1,39 @@
+/***************************************************************************************************************************
+ * 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.transform;
+
+import org.apache.juneau.*;
+
+
+/**
+ * Simple bean filter that simply identifies a class to be used as an interface
+ *     class for all child classes.
+ * <p>
+ *     These objects are created when you pass in non-<code>Transform</code> 
classes to {@link ContextFactory#addToProperty(String,Object)},
+ *             and are equivalent to adding a 
<code><ja>@Bean</ja>(interfaceClass=Foo.<jk>class</jk>)</code> annotation on 
the <code>Foo</code> class.
+ *
+ * @author James Bognar ([email protected])
+ * @param <T> The class type that this transform applies to.
+ */
+public class InterfaceBeanFilter<T> extends BeanFilter<T> {
+
+       /**
+        * Constructor.
+        *
+        * @param interfaceClass The class to use as an interface on all child 
classes.
+        */
+       public InterfaceBeanFilter(Class<T> interfaceClass) {
+               super(interfaceClass);
+               setInterfaceClass(interfaceClass);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanTransform.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanTransform.java
 
b/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanTransform.java
deleted file mode 100644
index 5f281f3..0000000
--- 
a/juneau-core/src/main/java/org/apache/juneau/transform/InterfaceBeanTransform.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/***************************************************************************************************************************
- * 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.transform;
-
-import org.apache.juneau.*;
-
-
-/**
- * Simple bean transform that simply identifies a class to be used as an 
interface
- *     class for all child classes.
- * <p>
- *     These objects are created when you pass in non-<code>Transform</code> 
classes to {@link ContextFactory#addToProperty(String,Object)},
- *             and are equivalent to adding a 
<code><ja>@Bean</ja>(interfaceClass=Foo.<jk>class</jk>)</code> annotation on 
the <code>Foo</code> class.
- *
- * @author James Bognar ([email protected])
- * @param <T> The class type that this transform applies to.
- */
-public class InterfaceBeanTransform<T> extends BeanTransform<T> {
-
-       /**
-        * Constructor.
-        *
-        * @param interfaceClass The class to use as an interface on all child 
classes.
-        */
-       public InterfaceBeanTransform(Class<T> interfaceClass) {
-               super(interfaceClass);
-               setInterfaceClass(interfaceClass);
-       }
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java 
b/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
new file mode 100644
index 0000000..3bde495
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/PojoSwap.java
@@ -0,0 +1,265 @@
+/***************************************************************************************************************************
+ * 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.transform;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.serializer.*;
+
+/**
+ * Used to convert non-serializable objects to a serializable form.
+ *
+ *
+ * <h6 class='topic'>Description</h6>
+ * <p>
+ *     <code>PojoSwaps</code> are used to extend the functionality of the 
serializers and parsers to be able to handle POJOs
+ *     that aren't automatically handled by the serializers or parsers.  For 
example, JSON does not have a standard
+ *     representation for rendering dates.  By defining a special {@code Date} 
swap and associating it with a serializer and
+ *     parser, you can convert a {@code Date} object to a {@code String} 
during serialization, and convert that {@code String} object back into
+ *     a {@code Date} object during parsing.
+ * <p>
+ *     Swaps MUST declare a public no-arg constructor so that the bean context 
can instantiate them.
+ * <p>
+ *     <code>PojoSwaps</code> are associated with instances of {@link 
BeanContext BeanContexts} by passing the swap class to
+ *     the {@link CoreApi#addTransforms(Class...)} method.<br>
+ *     When associated with a bean context, fields of the specified type will 
automatically be converted when the
+ *     {@link BeanMap#get(Object)} or {@link BeanMap#put(String, Object)} 
methods are called.<br>
+ * <p>
+ *     <code>PojoSwaps</code> have two parameters:
+ *     <ol>
+ *             <li>{@code <T>} - The normal representation of an object.
+ *             <li>{@code <S>} - The swapped representation of an object.
+ *     </ol>
+ *     <br>
+ *     {@link Serializer Serializers} use swaps to convert objects of type T 
into objects of type S, and on calls to {@link BeanMap#get(Object)}.<br>
+ *     {@link Parser Parsers} use swaps to convert objects of type S into 
objects of type T, and on calls to {@link BeanMap#put(String,Object)}.
+ *
+ *
+ * <h6 class='topic'>Swap Class Type {@code <S>}</h6>
+ * <p>
+ *     The swapped object representation of an object must be an object type 
that the serializers can
+ *     natively convert to JSON (or language-specific equivalent).  The list 
of valid transformed types are as follows...
+ *     <ul class='spaced-list'>
+ *             <li>{@link String}
+ *             <li>{@link Number}
+ *             <li>{@link Boolean}
+ *             <li>{@link Collection} containing anything on this list.
+ *             <li>{@link Map} containing anything on this list.
+ *             <li>A java bean with properties of anything on this list.
+ *             <li>An array of anything on this list.
+ *     </ul>
+ *
+ *
+ * <h6 class='topic'>Normal Class Type {@code <T>}</h6>
+ * <p>
+ *     The normal object representation of an object.<br>
+ *
+ *
+ * <h6 class='topic'>One-way vs. Two-way Serialization</h6>
+ * <p>
+ *     Note that while there is a unified interface for handling swaps during 
both serialization and parsing,
+ *     in many cases only one of the {@link #swap(Object)} or {@link 
#unswap(Object, ClassMeta)} methods will be defined
+ *     because the swap is one-way.  For example, a swap may be defined to 
convert an {@code Iterator} to a {@code ObjectList}, but
+ *     it's not possible to unswap an {@code Iterator}.  In that case, the 
{@code generalize(Object}} method would
+ *     be implemented, but the {@code narrow(ObjectMap)} object would not, and 
the swap would be associated on
+ *     the serializer, but not the parser.  Also, you may choose to serialize 
objects like {@code Dates} to readable {@code Strings},
+ *     in which case it's not possible to reparse it back into a {@code Date}, 
since there is no way for the {@code Parser} to
+ *     know it's a {@code Date} from just the JSON or XML text.
+ *
+ *
+ * <h6 class='topic'>Additional information</h6>
+ *     See {@link org.apache.juneau.transform} for more information.
+ *
+ *
+ * @author James Bognar ([email protected])
+ * @param <T> The normal form of the class.
+ * @param <S> The swapped form of the class.
+ */
+public abstract class PojoSwap<T,S> extends Transform {
+
+       /** Represents no transform. */
+       public static class NULL extends PojoSwap<Object,Object> {}
+
+       Class<T> normalClass;
+       Class<S> transformedClass;
+       ClassMeta<S> transformedClassMeta;
+
+       /**
+        * Constructor.
+        */
+       @SuppressWarnings("unchecked")
+       protected PojoSwap() {
+               super();
+
+               Class<?> c = this.getClass().getSuperclass();
+               Type t = this.getClass().getGenericSuperclass();
+               while (c != PojoSwap.class) {
+                       t = c.getGenericSuperclass();
+                       c = c.getSuperclass();
+               }
+
+               // Attempt to determine the T and G classes using reflection.
+               if (t instanceof ParameterizedType) {
+                       ParameterizedType pt = (ParameterizedType)t;
+                       Type[] pta = pt.getActualTypeArguments();
+                       if (pta.length == 2) {
+                               Type nType = pta[0];
+                               if (nType instanceof Class) {
+                                       this.normalClass = (Class<T>)nType;
+
+                               // <byte[],x> ends up containing a 
GenericArrayType, so it has to
+                               // be handled as a special case.
+                               } else if (nType instanceof GenericArrayType) {
+                                       Class<?> cmpntType = 
(Class<?>)((GenericArrayType)nType).getGenericComponentType();
+                                       this.normalClass = 
(Class<T>)Array.newInstance(cmpntType, 0).getClass();
+
+                               // <Class<?>,x> ends up containing a 
ParameterizedType, so just use the raw type.
+                               } else if (nType instanceof ParameterizedType) {
+                                       this.normalClass = 
(Class<T>)((ParameterizedType)nType).getRawType();
+
+                               } else
+                                       throw new RuntimeException("Unsupported 
parameter type: " + nType);
+                               if (pta[1] instanceof Class)
+                                       this.transformedClass = 
(Class<S>)pta[1];
+                               else if (pta[1] instanceof ParameterizedType)
+                                       this.transformedClass = 
(Class<S>)((ParameterizedType)pta[1]).getRawType();
+                               else
+                                       throw new RuntimeException("Unexpected 
transformed class type: " + pta[1].getClass().getName());
+                       }
+               }
+       }
+
+       /**
+        * Constructor for when the normal and transformed classes are already 
known.
+        *
+        * @param normalClass The normal class (cannot be serialized).
+        * @param transformedClass The transformed class (serializable).
+        */
+       protected PojoSwap(Class<T> normalClass, Class<S> transformedClass) {
+               this.normalClass = normalClass;
+               this.transformedClass = transformedClass;
+       }
+
+       /**
+        * If this transform is to be used to serialize non-serializable POJOs, 
it must implement this method.
+        * <p>
+        *      The object must be converted into one of the following 
serializable types:
+        *      <ul class='spaced-list'>
+        *              <li>{@link String}
+        *              <li>{@link Number}
+        *              <li>{@link Boolean}
+        *              <li>{@link Collection} containing anything on this list.
+        *              <li>{@link Map} containing anything on this list.
+        *              <li>A java bean with properties of anything on this 
list.
+        *              <li>An array of anything on this list.
+        *      </ul>
+        *
+        * @param o The object to be transformed.
+        * @return The transformed object.
+        * @throws SerializeException If a problem occurred trying to convert 
the output.
+        */
+       public S swap(T o) throws SerializeException {
+               throw new SerializeException("Generalize method not implemented 
on transform ''{0}''", this.getClass().getName());
+       }
+
+       /**
+        * If this transform is to be used to reconstitute POJOs that aren't 
true Java beans, it must implement this method.
+        *
+        * @param f The transformed object.
+        * @param hint If possible, the parser will try to tell you the object 
type being created.  For example,
+        *      on a serialized date, this may tell you that the object being 
created must be of type {@code GregorianCalendar}.<br>
+        *      This may be <jk>null</jk> if the parser cannot make this 
determination.
+        * @return The narrowed object.
+        * @throws ParseException If this method is not implemented.
+        */
+       public T unswap(S f, ClassMeta<?> hint) throws ParseException {
+               throw new ParseException("Narrow method not implemented on 
transform ''{0}''", this.getClass().getName());
+       }
+
+       /**
+        * Returns the T class, the normalized form of the class.
+        *
+        * @return The normal form of this class.
+        */
+       public Class<T> getNormalClass() {
+               return normalClass;
+       }
+
+       /**
+        * Returns the G class, the generialized form of the class.
+        * <p>
+        *      Subclasses must override this method if the generialized class 
is {@code Object},
+        *      meaning it can produce multiple generialized forms.
+        *
+        * @return The transformed form of this class.
+        */
+       public Class<S> getTransformedClass() {
+               return transformedClass;
+       }
+
+       /**
+        * Returns the {@link ClassMeta} of the transformed class type.
+        * This value is cached for quick lookup.
+        *
+        * @return The {@link ClassMeta} of the transformed class type.
+        */
+       public ClassMeta<S> getTransformedClassMeta() {
+               if (transformedClassMeta == null)
+                       transformedClassMeta = 
beanContext.getClassMeta(transformedClass);
+               return transformedClassMeta;
+       }
+
+       /**
+        * Checks if the specified object is an instance of the normal class 
defined on this transform.
+        *
+        * @param o The object to check.
+        * @return <jk>true</jk> if the specified object is a subclass of the 
normal class defined on this transform.
+        *      <jk>null</jk> always return <jk>false</jk>.
+        */
+       public boolean isNormalObject(Object o) {
+               if (o == null)
+                       return false;
+               return ClassUtils.isParentClass(normalClass, o.getClass());
+       }
+
+       /**
+        * Checks if the specified object is an instance of the transformed 
class defined on this transform.
+        *
+        * @param o The object to check.
+        * @return <jk>true</jk> if the specified object is a subclass of the 
transformed class defined on this transform.
+        *      <jk>null</jk> always return <jk>false</jk>.
+        */
+       public boolean isTransformedObject(Object o) {
+               if (o == null)
+                       return false;
+               return ClassUtils.isParentClass(transformedClass, o.getClass());
+       }
+
+       
//--------------------------------------------------------------------------------
+       // Overridden methods
+       
//--------------------------------------------------------------------------------
+
+       @Override /* Transform */
+       public Class<?> forClass() {
+               return normalClass;
+       }
+
+       @Override /* Object */
+       public String toString() {
+               return getClass().getSimpleName() + '<' + 
getNormalClass().getSimpleName() + "," + getTransformedClass().getSimpleName() 
+ '>';
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/0ce0e663/juneau-core/src/main/java/org/apache/juneau/transform/PojoTransform.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/transform/PojoTransform.java 
b/juneau-core/src/main/java/org/apache/juneau/transform/PojoTransform.java
deleted file mode 100644
index 4d41b3f..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/transform/PojoTransform.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/***************************************************************************************************************************
- * 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.transform;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.serializer.*;
-
-/**
- * Used to convert non-serializable objects to a serializable form.
- *
- *
- * <h6 class='topic'>Description</h6>
- * <p>
- *     <code>PojoTransforms</code> are used to extend the functionality of the 
serializers and parsers to be able to handle POJOs
- *     that aren't automatically handled by the serializers or parsers.  For 
example, JSON does not have a standard
- *     representation for rendering dates.  By defining a special {@code Date} 
transform and associating it with a serializer and
- *     parser, you can convert a {@code Date} object to a {@code String} 
during serialization, and convert that {@code String} object back into
- *     a {@code Date} object during parsing.
- * <p>
- *     Object transforms MUST declare a public no-arg constructor so that the 
bean context can instantiate them.
- * <p>
- *     <code>PojoTransforms</code> are associated with instances of {@link 
BeanContext BeanContexts} by passing the transform class to
- *     the {@link CoreApi#addTransforms(Class...)} method.<br>
- *     When associated with a bean context, fields of the specified type will 
automatically be converted when the
- *     {@link BeanMap#get(Object)} or {@link BeanMap#put(String, Object)} 
methods are called.<br>
- * <p>
- *     <code>PojoTransforms</code> have two parameters:
- *     <ol>
- *             <li>{@code <F>} - The transformed representation of an object.
- *             <li>{@code <T>} - The normal representation of an object.
- *     </ol>
- *     <br>
- *     {@link Serializer Serializers} use object transforms to convert objects 
of type T into objects of type F, and on calls to {@link 
BeanMap#get(Object)}.<br>
- *     {@link Parser Parsers} use object transforms to convert objects of type 
F into objects of type T, and on calls to {@link BeanMap#put(String,Object)}.
- *
- *
- * <h6 class='topic'>Transformed Class Type {@code <T>}</h6>
- * <p>
- *     The transformed object representation of an object must be an object 
type that the serializers can
- *     natively convert to JSON (or language-specific equivalent).  The list 
of valid transformed types are as follows...
- *     <ul class='spaced-list'>
- *             <li>{@link String}
- *             <li>{@link Number}
- *             <li>{@link Boolean}
- *             <li>{@link Collection} containing anything on this list.
- *             <li>{@link Map} containing anything on this list.
- *             <li>A java bean with properties of anything on this list.
- *             <li>An array of anything on this list.
- *     </ul>
- *
- *
- * <h6 class='topic'>Normal Class Type {@code <N>}</h6>
- * <p>
- *     The normal object representation of an object.<br>
- *
- *
- * <h6 class='topic'>One-way vs. Two-way Serialization</h6>
- * <p>
- *     Note that while there is a unified interface for handling transforming 
during both serialization and parsing,
- *     in many cases only one of the {@link #transform(Object)} or {@link 
#normalize(Object, ClassMeta)} methods will be defined
- *     because the transform is one-way.  For example, a transform may be 
defined to convert an {@code Iterator} to a {@code ObjectList}, but
- *     it's not possible to untransform an {@code Iterator}.  In that case, 
the {@code generalize(Object}} method would
- *     be implemented, but the {@code narrow(ObjectMap)} object would not, and 
the transform would be associated on
- *     the serializer, but not the parser.  Also, you may choose to serialize 
objects like {@code Dates} to readable {@code Strings},
- *     in which case it's not possible to reparse it back into a {@code Date}, 
since there is no way for the {@code Parser} to
- *     know it's a {@code Date} from just the JSON or XML text.
- *
- *
- * <h6 class='topic'>Additional information</h6>
- *     See {@link org.apache.juneau.transform} for more information.
- *
- *
- * @author James Bognar ([email protected])
- * @param <N> The normal form of the class.
- * @param <T> The transformed form of the class.
- */
-public abstract class PojoTransform<N,T> extends Transform {
-
-       /** Represents no transform. */
-       public static class NULL extends PojoTransform<Object,Object> {}
-
-       Class<N> normalClass;
-       Class<T> transformedClass;
-       ClassMeta<T> transformedClassMeta;
-
-       /**
-        * Constructor.
-        */
-       @SuppressWarnings("unchecked")
-       protected PojoTransform() {
-               super();
-
-               Class<?> c = this.getClass().getSuperclass();
-               Type t = this.getClass().getGenericSuperclass();
-               while (c != PojoTransform.class) {
-                       t = c.getGenericSuperclass();
-                       c = c.getSuperclass();
-               }
-
-               // Attempt to determine the T and G classes using reflection.
-               if (t instanceof ParameterizedType) {
-                       ParameterizedType pt = (ParameterizedType)t;
-                       Type[] pta = pt.getActualTypeArguments();
-                       if (pta.length == 2) {
-                               Type nType = pta[0];
-                               if (nType instanceof Class) {
-                                       this.normalClass = (Class<N>)nType;
-
-                               // <byte[],x> ends up containing a 
GenericArrayType, so it has to
-                               // be handled as a special case.
-                               } else if (nType instanceof GenericArrayType) {
-                                       Class<?> cmpntType = 
(Class<?>)((GenericArrayType)nType).getGenericComponentType();
-                                       this.normalClass = 
(Class<N>)Array.newInstance(cmpntType, 0).getClass();
-
-                               // <Class<?>,x> ends up containing a 
ParameterizedType, so just use the raw type.
-                               } else if (nType instanceof ParameterizedType) {
-                                       this.normalClass = 
(Class<N>)((ParameterizedType)nType).getRawType();
-
-                               } else
-                                       throw new RuntimeException("Unsupported 
parameter type: " + nType);
-                               if (pta[1] instanceof Class)
-                                       this.transformedClass = 
(Class<T>)pta[1];
-                               else if (pta[1] instanceof ParameterizedType)
-                                       this.transformedClass = 
(Class<T>)((ParameterizedType)pta[1]).getRawType();
-                               else
-                                       throw new RuntimeException("Unexpected 
transformed class type: " + pta[1].getClass().getName());
-                       }
-               }
-       }
-
-       /**
-        * Constructor for when the normal and transformed classes are already 
known.
-        *
-        * @param normalClass The normal class (cannot be serialized).
-        * @param transformedClass The transformed class (serializable).
-        */
-       protected PojoTransform(Class<N> normalClass, Class<T> 
transformedClass) {
-               this.normalClass = normalClass;
-               this.transformedClass = transformedClass;
-       }
-
-       /**
-        * If this transform is to be used to serialize non-serializable POJOs, 
it must implement this method.
-        * <p>
-        *      The object must be converted into one of the following 
serializable types:
-        *      <ul class='spaced-list'>
-        *              <li>{@link String}
-        *              <li>{@link Number}
-        *              <li>{@link Boolean}
-        *              <li>{@link Collection} containing anything on this list.
-        *              <li>{@link Map} containing anything on this list.
-        *              <li>A java bean with properties of anything on this 
list.
-        *              <li>An array of anything on this list.
-        *      </ul>
-        *
-        * @param o The object to be transformed.
-        * @return The transformed object.
-        * @throws SerializeException If a problem occurred trying to convert 
the output.
-        */
-       public T transform(N o) throws SerializeException {
-               throw new SerializeException("Generalize method not implemented 
on transform ''{0}''", this.getClass().getName());
-       }
-
-       /**
-        * If this transform is to be used to reconstitute POJOs that aren't 
true Java beans, it must implement this method.
-        *
-        * @param f The transformed object.
-        * @param hint If possible, the parser will try to tell you the object 
type being created.  For example,
-        *      on a serialized date, this may tell you that the object being 
created must be of type {@code GregorianCalendar}.<br>
-        *      This may be <jk>null</jk> if the parser cannot make this 
determination.
-        * @return The narrowed object.
-        * @throws ParseException If this method is not implemented.
-        */
-       public N normalize(T f, ClassMeta<?> hint) throws ParseException {
-               throw new ParseException("Narrow method not implemented on 
transform ''{0}''", this.getClass().getName());
-       }
-
-       /**
-        * Returns the T class, the normalized form of the class.
-        *
-        * @return The normal form of this class.
-        */
-       public Class<N> getNormalClass() {
-               return normalClass;
-       }
-
-       /**
-        * Returns the G class, the generialized form of the class.
-        * <p>
-        *      Subclasses must override this method if the generialized class 
is {@code Object},
-        *      meaning it can produce multiple generialized forms.
-        *
-        * @return The transformed form of this class.
-        */
-       public Class<T> getTransformedClass() {
-               return transformedClass;
-       }
-
-       /**
-        * Returns the {@link ClassMeta} of the transformed class type.
-        * This value is cached for quick lookup.
-        *
-        * @return The {@link ClassMeta} of the transformed class type.
-        */
-       public ClassMeta<T> getTransformedClassMeta() {
-               if (transformedClassMeta == null)
-                       transformedClassMeta = 
beanContext.getClassMeta(transformedClass);
-               return transformedClassMeta;
-       }
-
-       /**
-        * Checks if the specified object is an instance of the normal class 
defined on this transform.
-        *
-        * @param o The object to check.
-        * @return <jk>true</jk> if the specified object is a subclass of the 
normal class defined on this transform.
-        *      <jk>null</jk> always return <jk>false</jk>.
-        */
-       public boolean isNormalObject(Object o) {
-               if (o == null)
-                       return false;
-               return ClassUtils.isParentClass(normalClass, o.getClass());
-       }
-
-       /**
-        * Checks if the specified object is an instance of the transformed 
class defined on this transform.
-        *
-        * @param o The object to check.
-        * @return <jk>true</jk> if the specified object is a subclass of the 
transformed class defined on this transform.
-        *      <jk>null</jk> always return <jk>false</jk>.
-        */
-       public boolean isTransformedObject(Object o) {
-               if (o == null)
-                       return false;
-               return ClassUtils.isParentClass(transformedClass, o.getClass());
-       }
-
-       
//--------------------------------------------------------------------------------
-       // Overridden methods
-       
//--------------------------------------------------------------------------------
-
-       @Override /* Transform */
-       public Class<?> forClass() {
-               return normalClass;
-       }
-
-       @Override /* Object */
-       public String toString() {
-               return getClass().getSimpleName() + '<' + 
getNormalClass().getSimpleName() + "," + getTransformedClass().getSimpleName() 
+ '>';
-       }
-}

Reply via email to