You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2016/08/27 14:14:48 UTC

[5/7] incubator-juneau git commit: Tweak new name 'Transform' into 'BeanFilter' and 'PojoSwap'

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transform/SurrogateSwap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/SurrogateSwap.java b/juneau-core/src/main/java/org/apache/juneau/transform/SurrogateSwap.java
new file mode 100644
index 0000000..f1164cc
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/SurrogateSwap.java
@@ -0,0 +1,207 @@
+/***************************************************************************************************************************
+ * 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.annotation.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.serializer.*;
+
+
+/**
+ * Specialized {@link PojoSwap} for surrogate classes.
+ * <p>
+ * Surrogate classes are used in place of other classes during serialization.
+ * For example, you may want to use a surrogate class to change the names or order of bean
+ * properties on a bean.
+ * <p>
+ * The following is an example of a surrogate class change changes a property name:
+ * <p class='bcode'>
+ * 	<jk>public class</jk> SurrogateClass {
+ * 		<jk>public</jk> String surrogateField;  <jc>// New bean property</jc>
+ *
+ * 		<jk>public</jk> SurrogateClass(NormalClass normalClass) {
+ * 			<jk>this</jk>.surrogateField = normalClass.normalField;
+ * 		}
+ * 	}
+ * </p>
+ * <p>
+ * Optionally, a public static method can be used to untransform a class during parsing:
+ * <p class='bcode'>
+ * 	<jk>public class</jk> SurrogateClass {
+ * 		...
+ * 		<jk>public static</jk> NormalClass <jsm>toNormalClass</jsm>(SurrogateClass surrogateClass) {
+ * 			<jk>return new</jk> NormalClass(surrogateClass.transformedField);
+ * 		}
+ * 	}
+ * </p>
+ * <p>
+ * Surrogate classes must conform to the following:
+ * <ul class='spaced-list'>
+ * 	<li>It must have a one or more public constructors that take in a single parameter whose type is the normal types.
+ * 		(It is possible to define a class as a surrogate for multiple class types by using multiple constructors with
+ * 		different parameter types).
+ * 	<li>It optionally can have a public static method that takes in a single parameter whose type is the transformed type
+ * 		and returns an instance of the normal type.  This is called the untransform method.  The method can be called anything.
+ * 	<li>If an untransform method is present, the class must also contain a no-arg constructor (so that the transformed class
+ * 		can be instantiated by the parser before being converted into the normal class by the untransform method).
+ * </ul>
+ * <p>
+ * Surrogate classes are associated with serializers and parsers using the {@link CoreApi#addTransforms(Class...)} method.
+ * <p class='bcode'>
+ * 	<ja>@Test</ja>
+ * 	<jk>public void</jk> test() <jk>throws</jk> Exception {
+ * 		JsonSerializer s = <jk>new</jk> JsonSerializer.Simple().addTransforms(Surrogate.<jk>class</jk>);
+ * 		JsonParser p = <jk>new</jk> JsonParser().addTransforms(Surrogate.<jk>class</jk>);
+ * 		String r;
+ * 		Normal n = Normal.<jsm>create</jsm>();
+ *
+ * 		r = s.serialize(n);
+ * 		assertEquals(<js>"{f2:'f1'}"</js>, r);
+ *
+ * 		n = p.parse(r, Normal.<jk>class</jk>);
+ * 		assertEquals(<js>"f1"</js>, n.f1);
+ * 	}
+ *
+ * 	<jc>// The normal class</jc>
+ * 	<jk>public class</jk> Normal {
+ * 		<jk>public</jk> String f1;
+ *
+ * 		<jk>public static</jk> Normal <jsm>create</jsm>() {
+ * 			Normal n = <jk>new</jk> Normal();
+ * 			n.f1 = <js>"f1"</js>;
+ * 			<jk>return</jk> n;
+ * 		}
+ * 	}
+ *
+ * 	<jc>// The surrogate class</jc>
+ * 	<jk>public static class</jk> Surrogate {
+ * 		<jk>public</jk> String f2;
+ *
+ * 		<jc>// Surrogate constructor</jc>
+ * 		<jk>public</jk> Surrogate(Normal n) {
+ * 			f2 = n.f1;
+ * 		}
+ *
+ * 		<jc>// Constructor used during parsing (only needed if untransform method specified)</jc>
+ * 		<jk>public</jk> Surrogate() {}
+ *
+ * 		<jc>// Untransform method (optional)</jc>
+ * 		<jk>public static</jk> Normal <jsm>toNormal</jsm>(Surrogate f) {
+ * 			Normal n = <jk>new</jk> Normal();
+ * 			n.f1 = f.f2;
+ * 			<jk>return</jk> n;
+ * 		}
+ * 	}
+ * </p>
+ * <p>
+ * It should be noted that a surrogate class is functionally equivalent to the following {@link PojoSwap} implementation:
+ * <p class='bcode'>
+ * 	<jk>public static class</jk> SurrogateSwap <jk>extends</jk> PojoSwap&lt;Normal,Surrogate&gt; {
+ * 		<jk>public</jk> Surrogate swap(Normal n) <jk>throws</jk> SerializeException {
+ * 			<jk>return new</jk> Surrogate(n);
+ * 		}
+ * 		<jk>public</jk> Normal unswap(Surrogate s, ClassMeta<?> hint) <jk>throws</jk> ParseException {
+ * 			<jk>return</jk> Surrogate.<jsm>toNormal</jsm>(s);
+ * 		}
+ * 	}
+ * </p>
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ * @param <T> The class type that this transform applies to.
+ * @param <F> The transformed class type.
+ */
+public class SurrogateSwap<T,F> extends PojoSwap<T,F> {
+
+	private Constructor<F> constructor;   // public F(T t);
+	private Method untransformMethod;        // public static T valueOf(F f);
+
+	/**
+	 * Constructor.
+	 *
+	 * @param forClass The normal class.
+	 * @param constructor The constructor on the surrogate class that takes the normal class as a parameter.
+	 * @param untransformMethod The static method that converts surrogate objects into normal objects.
+	 */
+	protected SurrogateSwap(Class<T> forClass, Constructor<F> constructor, Method untransformMethod) {
+		super(forClass, constructor.getDeclaringClass());
+		this.constructor = constructor;
+		this.untransformMethod = untransformMethod;
+	}
+
+	/**
+	 * Given the specified surrogate class, return the list of POJO swaps.
+	 * A transform is returned for each public 1-arg constructor found.
+	 * Returns an empty list if no public 1-arg constructors are found.
+	 *
+	 * @param c The surrogate class.
+	 * @return The list of POJO swaps that apply to this class.
+	 */
+	@SuppressWarnings({"unchecked", "rawtypes"})
+	public static List<SurrogateSwap<?,?>> findTransforms(Class<?> c) {
+		List<SurrogateSwap<?,?>> l = new LinkedList<SurrogateSwap<?,?>>();
+		for (Constructor<?> cc : c.getConstructors()) {
+			if (cc.getAnnotation(BeanIgnore.class) == null) {
+				Class<?>[] pt = cc.getParameterTypes();
+
+				// Only constructors with one parameter.
+				// Ignore instance class constructors.
+				if (pt.length == 1 && pt[0] != c.getDeclaringClass()) {
+					int mod = cc.getModifiers();
+					if (Modifier.isPublic(mod)) {  // Only public constructors.
+
+						// Find the untransform method if there is one.
+						Method untransformMethod = null;
+						for (Method m : c.getMethods()) {
+							if (pt[0].equals(m.getReturnType())) {
+								Class<?>[] mpt = m.getParameterTypes();
+								if (mpt.length == 1 && mpt[0].equals(c)) { // Only methods with one parameter and where the return type matches this class.
+									int mod2 = m.getModifiers();
+									if (Modifier.isPublic(mod2) && Modifier.isStatic(mod2))  // Only public static methods.
+										untransformMethod = m;
+								}
+							}
+						}
+
+						l.add(new SurrogateSwap(pt[0], cc, untransformMethod));
+					}
+				}
+			}
+		}
+		return l;
+	}
+
+	@Override /* PojoSwap */
+	public F swap(T o) throws SerializeException {
+		try {
+			return constructor.newInstance(o);
+		} catch (Exception e) {
+			throw new SerializeException(e);
+		}
+	}
+
+	@Override /* PojoSwap */
+	@SuppressWarnings("unchecked")
+	public T unswap(F f, ClassMeta<?> hint) throws ParseException {
+		if (untransformMethod == null)
+			throw new ParseException("static valueOf({0}) method not implement on surrogate class ''{1}''", f.getClass().getName(), getNormalClass().getName());
+		try {
+			return (T)untransformMethod.invoke(null, f);
+		} catch (Exception e) {
+			throw new ParseException(e);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transform/SurrogateTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/SurrogateTransform.java b/juneau-core/src/main/java/org/apache/juneau/transform/SurrogateTransform.java
deleted file mode 100644
index 2472f4f..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/transform/SurrogateTransform.java
+++ /dev/null
@@ -1,207 +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.annotation.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.serializer.*;
-
-
-/**
- * Specialized {@link PojoTransform} for surrogate classes.
- * <p>
- * Surrogate classes are used in place of other classes during serialization.
- * For example, you may want to use a surrogate class to change the names or order of bean
- * properties on a bean.
- * <p>
- * The following is an example of a surrogate class change changes a property name:
- * <p class='bcode'>
- * 	<jk>public class</jk> SurrogateClass {
- * 		<jk>public</jk> String surrogateField;  <jc>// New bean property</jc>
- *
- * 		<jk>public</jk> SurrogateClass(NormalClass normalClass) {
- * 			<jk>this</jk>.surrogateField = normalClass.normalField;
- * 		}
- * 	}
- * </p>
- * <p>
- * Optionally, a public static method can be used to untransform a class during parsing:
- * <p class='bcode'>
- * 	<jk>public class</jk> SurrogateClass {
- * 		...
- * 		<jk>public static</jk> NormalClass <jsm>toNormalClass</jsm>(SurrogateClass surrogateClass) {
- * 			<jk>return new</jk> NormalClass(surrogateClass.transformedField);
- * 		}
- * 	}
- * </p>
- * <p>
- * Surrogate classes must conform to the following:
- * <ul class='spaced-list'>
- * 	<li>It must have a one or more public constructors that take in a single parameter whose type is the normal types.
- * 		(It is possible to define a class as a surrogate for multiple class types by using multiple constructors with
- * 		different parameter types).
- * 	<li>It optionally can have a public static method that takes in a single parameter whose type is the transformed type
- * 		and returns an instance of the normal type.  This is called the untransform method.  The method can be called anything.
- * 	<li>If an untransform method is present, the class must also contain a no-arg constructor (so that the transformed class
- * 		can be instantiated by the parser before being converted into the normal class by the untransform method).
- * </ul>
- * <p>
- * Surrogate classes are associated with serializers and parsers using the {@link CoreApi#addTransforms(Class...)} method.
- * <p class='bcode'>
- * 	<ja>@Test</ja>
- * 	<jk>public void</jk> test() <jk>throws</jk> Exception {
- * 		JsonSerializer s = <jk>new</jk> JsonSerializer.Simple().addTransforms(Surrogate.<jk>class</jk>);
- * 		JsonParser p = <jk>new</jk> JsonParser().addTransforms(Surrogate.<jk>class</jk>);
- * 		String r;
- * 		Normal n = Normal.<jsm>create</jsm>();
- *
- * 		r = s.serialize(n);
- * 		assertEquals(<js>"{f2:'f1'}"</js>, r);
- *
- * 		n = p.parse(r, Normal.<jk>class</jk>);
- * 		assertEquals(<js>"f1"</js>, n.f1);
- * 	}
- *
- * 	<jc>// The normal class</jc>
- * 	<jk>public class</jk> Normal {
- * 		<jk>public</jk> String f1;
- *
- * 		<jk>public static</jk> Normal <jsm>create</jsm>() {
- * 			Normal n = <jk>new</jk> Normal();
- * 			n.f1 = <js>"f1"</js>;
- * 			<jk>return</jk> n;
- * 		}
- * 	}
- *
- * 	<jc>// The surrogate class</jc>
- * 	<jk>public static class</jk> Surrogate {
- * 		<jk>public</jk> String f2;
- *
- * 		<jc>// Surrogate constructor</jc>
- * 		<jk>public</jk> Surrogate(Normal n) {
- * 			f2 = n.f1;
- * 		}
- *
- * 		<jc>// Constructor used during parsing (only needed if untransform method specified)</jc>
- * 		<jk>public</jk> Surrogate() {}
- *
- * 		<jc>// Untransform method (optional)</jc>
- * 		<jk>public static</jk> Normal <jsm>toNormal</jsm>(Surrogate f) {
- * 			Normal n = <jk>new</jk> Normal();
- * 			n.f1 = f.f2;
- * 			<jk>return</jk> n;
- * 		}
- * 	}
- * </p>
- * <p>
- * It should be noted that a surrogate class is functionally equivalent to the following {@link PojoTransform} implementation:
- * <p class='bcode'>
- * 	<jk>public static class</jk> SurrogateTransform <jk>extends</jk> PojoTransform&lt;Normal,Surrogate&gt; {
- * 		<jk>public</jk> Surrogate transform(Normal n) <jk>throws</jk> SerializeException {
- * 			<jk>return new</jk> Surrogate(n);
- * 		}
- * 		<jk>public</jk> Normal normalize(Surrogate s, ClassMeta<?> hint) <jk>throws</jk> ParseException {
- * 			<jk>return</jk> Surrogate.<jsm>toNormal</jsm>(s);
- * 		}
- * 	}
- * </p>
- *
- * @author James Bognar (james.bognar@salesforce.com)
- * @param <T> The class type that this transform applies to.
- * @param <F> The transformed class type.
- */
-public class SurrogateTransform<T,F> extends PojoTransform<T,F> {
-
-	private Constructor<F> constructor;   // public F(T t);
-	private Method untransformMethod;        // public static T valueOf(F f);
-
-	/**
-	 * Constructor.
-	 *
-	 * @param forClass The normal class.
-	 * @param constructor The constructor on the surrogate class that takes the normal class as a parameter.
-	 * @param untransformMethod The static method that converts surrogate objects into normal objects.
-	 */
-	protected SurrogateTransform(Class<T> forClass, Constructor<F> constructor, Method untransformMethod) {
-		super(forClass, constructor.getDeclaringClass());
-		this.constructor = constructor;
-		this.untransformMethod = untransformMethod;
-	}
-
-	/**
-	 * Given the specified surrogate class, return the list of POJO transforms.
-	 * A transform is returned for each public 1-arg constructor found.
-	 * Returns an empty list if no public 1-arg constructors are found.
-	 *
-	 * @param c The surrogate class.
-	 * @return The list of POJO transforms that apply to this class.
-	 */
-	@SuppressWarnings({"unchecked", "rawtypes"})
-	public static List<SurrogateTransform<?,?>> findTransforms(Class<?> c) {
-		List<SurrogateTransform<?,?>> l = new LinkedList<SurrogateTransform<?,?>>();
-		for (Constructor<?> cc : c.getConstructors()) {
-			if (cc.getAnnotation(BeanIgnore.class) == null) {
-				Class<?>[] pt = cc.getParameterTypes();
-
-				// Only constructors with one parameter.
-				// Ignore instance class constructors.
-				if (pt.length == 1 && pt[0] != c.getDeclaringClass()) {
-					int mod = cc.getModifiers();
-					if (Modifier.isPublic(mod)) {  // Only public constructors.
-
-						// Find the untransform method if there is one.
-						Method untransformMethod = null;
-						for (Method m : c.getMethods()) {
-							if (pt[0].equals(m.getReturnType())) {
-								Class<?>[] mpt = m.getParameterTypes();
-								if (mpt.length == 1 && mpt[0].equals(c)) { // Only methods with one parameter and where the return type matches this class.
-									int mod2 = m.getModifiers();
-									if (Modifier.isPublic(mod2) && Modifier.isStatic(mod2))  // Only public static methods.
-										untransformMethod = m;
-								}
-							}
-						}
-
-						l.add(new SurrogateTransform(pt[0], cc, untransformMethod));
-					}
-				}
-			}
-		}
-		return l;
-	}
-
-	@Override /* PojoTransform */
-	public F transform(T o) throws SerializeException {
-		try {
-			return constructor.newInstance(o);
-		} catch (Exception e) {
-			throw new SerializeException(e);
-		}
-	}
-
-	@Override /* PojoTransform */
-	@SuppressWarnings("unchecked")
-	public T normalize(F f, ClassMeta<?> hint) throws ParseException {
-		if (untransformMethod == null)
-			throw new ParseException("static valueOf({0}) method not implement on surrogate class ''{1}''", f.getClass().getName(), getNormalClass().getName());
-		try {
-			return (T)untransformMethod.invoke(null, f);
-		} catch (Exception e) {
-			throw new ParseException(e);
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transform/Transform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/Transform.java b/juneau-core/src/main/java/org/apache/juneau/transform/Transform.java
index 3fa17f7..2c72c88 100644
--- a/juneau-core/src/main/java/org/apache/juneau/transform/Transform.java
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/Transform.java
@@ -15,7 +15,7 @@ package org.apache.juneau.transform;
 import org.apache.juneau.*;
 
 /**
- * Parent class for all bean and POJO transforms.
+ * Parent class for all bean and POJO swaps.
  *
  *
  * <h6 class='topic'>Description</h6>
@@ -30,8 +30,8 @@ import org.apache.juneau.*;
  * <p>
  * 	There are 2 subclasses of transforms:
  * <ul class='spaced-list'>
- * 	<li>{@link PojoTransform} - Non-bean transforms for converting POJOs into serializable equivalents.
- * 	<li>{@link BeanTransform} - Bean transforms for configuring how beans are handled.
+ * 	<li>{@link PojoSwap} - Non-bean filters for converting POJOs into serializable equivalents.
+ * 	<li>{@link BeanFilter} - Bean filters for configuring how beans are handled.
  * </ul>
  * <p>
  * 	Transforms are associated with bean contexts (and serializers/parsers) through the {@link ContextFactory#addToProperty(String,Object)}
@@ -51,9 +51,9 @@ public class Transform {
 
 	/** The transform subtype */
 	public static enum TransformType {
-		/** PojoTransform */
+		/** PojoSwap */
 		POJO,
-		/** BeanTransform */
+		/** BeanFilter */
 		BEAN
 	}
 
@@ -63,7 +63,7 @@ public class Transform {
 	/** The bean context that this transform instance belongs to. */
 	protected BeanContext beanContext;
 
-	/** Whether this is a BeanTransform or PojoTransform. */
+	/** Whether this is a BeanFilter or PojoSwap. */
 	protected TransformType type = TransformType.POJO;
 
 	Transform() {}
@@ -93,7 +93,7 @@ public class Transform {
 	}
 
 	/**
-	 * Returns whether this is an instance of {@link PojoTransform} or {@link BeanTransform}.
+	 * Returns whether this is an instance of {@link PojoSwap} or {@link BeanFilter}.
 	 *
 	 * @return The transform type.
 	 */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transform/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/package.html b/juneau-core/src/main/java/org/apache/juneau/transform/package.html
index a94e213..059b769 100644
--- a/juneau-core/src/main/java/org/apache/juneau/transform/package.html
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/package.html
@@ -60,9 +60,9 @@
 <ol class='toc'>
 	<li><p><a class='doclink' href='#Transforms'>Transforms</a></p>
 	<ol>
-		<li><p><a class='doclink' href='#BeanTransforms'>BeanTransform Class</a></p>
-		<li><p><a class='doclink' href='#PojoTransforms'>PojoTransform Class</a></p>
-		<li><p><a class='doclink' href='#PojoTransforms_OneWay'>One-Way PojoTransforms</a></p>
+		<li><p><a class='doclink' href='#BeanFilters'>BeanFilter Class</a></p>
+		<li><p><a class='doclink' href='#PojoSwaps'>PojoSwap Class</a></p>
+		<li><p><a class='doclink' href='#PojoSwaps_OneWay'>One-Way PojoSwaps</a></p>
 		<li><p><a class='doclink' href='#StopClasses'>Stop Classes</a></p>
 		<li><p><a class='doclink' href='#SurrogateClasses'>Surrogate Classes</a></p>
 		<li><p><a class='doclink' href='#ToObjectMaps'>Serializing to ObjectMaps</a></p>
@@ -81,8 +81,8 @@
 	<ul class='spaced-list'>
 		<li>{@link org.apache.juneau.transform.Transform} - Top-level interface for all transforms.
 	<ul class='spaced-list'>
-		<li>{@link org.apache.juneau.transform.BeanTransform} - Transforms that alter the way beans are handled.
-		<li>{@link org.apache.juneau.transform.PojoTransform} - Transforms that transform non-serializable POJOs into serializable POJOs during serialization 
+		<li>{@link org.apache.juneau.transform.BeanFilter} - Transforms that alter the way beans are handled.
+		<li>{@link org.apache.juneau.transform.PojoSwap} - Transforms that swap non-serializable POJOs with serializable POJOs during serialization 
 			(and optionally vis-versa during parsing).
 		</ul>
 	</ul>
@@ -100,15 +100,15 @@
 		<li>{@link org.apache.juneau.server.jaxrs.JuneauProvider#transforms()} - On all serializers and parsers defined on a JAX-RS provider.
 	</ul>
 	<p>
-		Transforms (typically <code>PojoTransforms</code>) can also be associated with classes through the {@link org.apache.juneau.annotation.Transform @Transform} annotation. 
+		Swaps can also be associated with classes through the {@link org.apache.juneau.annotation.Pojo @Pojo} annotation. 
 	</p>
 		
 	<!-- ======================================================================================================== -->
-	<a id="BeanTransforms"></a>
-	<h3 class='topic' onclick='toggle(this)'>1.1 - BeanTransform Class</h3>
+	<a id="BeanFilters"></a>
+	<h3 class='topic' onclick='toggle(this)'>1.1 - BeanFilter Class</h3>
 	<div class='topic'>
 		<p>
-			Bean transforms are used to tailor how Juneau handles bean classes.
+			Bean filters are used to tailor how Juneau handles bean classes.
 			They can be used for the following purposes:
 		</p>
 		<ul class='spaced-list'>
@@ -120,7 +120,7 @@
 		<p>
 			It should be noted that the {@link org.apache.juneau.annotation.Bean @Bean} annotation provides equivalent functionality
 				through annotations.  
-			However, the <code>BeanTransform</code> class allows you to provide the same features when you do
+			However, the <code>BeanFilter</code> class allows you to provide the same features when you do
 				not have access to the source code.
 		<p>
 		<h5 class='topic'>Examples</h5>
@@ -128,13 +128,13 @@
 		<h6 class='topic'>Explicitly specify which properties are visible on a bean class</h6>
 		<p class='bcode'>
 	<jc>// Define transform that orders properties by "age" then "name"</jc>
-	<jk>public class</jk> MyTransform <jk>extends</jk> BeanTransform&lt;Person&gt; {
-		<jk>public</jk> MyTransform() {
+	<jk>public class</jk> MyBeanFilter <jk>extends</jk> BeanFilter&lt;Person&gt; {
+		<jk>public</jk> MyBeanFilter() {
 			setProperties(<js>"age"</js>,<js>"name"</js>);
 		}
 	}
 	
-	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyTransform.<jk>class</jk>);
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyBeanFilter.<jk>class</jk>);
 	Person p = getPerson();
 	String json = s.serialize(p);  <jc>// Prints "{age:45,name:'John Smith'}"</jc>
 		</p>
@@ -151,13 +151,13 @@
 		<h6 class='topic'>Exclude which properties are visible on a bean class</h6>
 		<p class='bcode'>
 	<jc>// Define transform that excludes "name"</jc>
-	<jk>public class</jk> MyTransform <jk>extends</jk> BeanTransform&lt;Person&gt; {
-		<jk>public</jk> MyTransform() {
+	<jk>public class</jk> MyBeanFilter <jk>extends</jk> BeanFilter&lt;Person&gt; {
+		<jk>public</jk> MyBeanFilter() {
 			setExcludeProperties(<js>"name"</js>);
 		}
 	}
 	
-	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyTransform.<jk>class</jk>);
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyBeanFilter.<jk>class</jk>);
 	Person p = getPerson();
 	String json = s.serialize(p);  <jc>// Prints "{age:45}"</jc>
 		</p>
@@ -174,8 +174,8 @@
 		<h6 class='topic'>Define specialized property namers</h6>
 		<p class='bcode'>
 	<jc>// Define transform with our own property namer.</jc>
-	<jk>public class</jk> MyTransform <jk>extends</jk> BeanTransform&lt;Person&gt; {
-		<jk>public</jk> MyTransform() {
+	<jk>public class</jk> MyBeanFilter <jk>extends</jk> BeanFilter&lt;Person&gt; {
+		<jk>public</jk> MyBeanFilter() {
 			setPropertyNamer(UpperCasePropertyNamer.<jk>class</jk>);
 		}
 	}
@@ -190,12 +190,12 @@
 	}
 	
 	<jc>// Serialize to JSON</jc>
-	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyTransform.<jk>class</jk>);
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyBeanFilter.<jk>class</jk>);
 	Person person = getPerson();
 	String json = s.serialize(p);  <jc>// Prints "{AGE:45,NAME:'John Smith'}"</jc>
 	
 	<jc>// Parse back into bean</jc>
-	ReaderParser p = <jk>new</jk> JsonParser().addTransforms(MyTransform.<jk>class</jk>);
+	ReaderParser p = <jk>new</jk> JsonParser().addTransforms(MyBeanFilter.<jk>class</jk>);
 	person = p.parse(json, Person.class); <jc>// Read back into original object</jc>
 		</p>
 		<p>
@@ -238,8 +238,8 @@
 		</p>		
 		<p class='bcode'>
 	<jc>// Define transform with our own property namer.</jc>
-	<jk>public class</jk> MyClassTransform <jk>extends</jk> BeanTransform&lt;MyClass&gt; {
-		<jk>public</jk> MyClassTransform() {
+	<jk>public class</jk> MyBeanFilter <jk>extends</jk> BeanFilter&lt;MyClass&gt; {
+		<jk>public</jk> MyBeanFilter() {
 			setSubTypeProperty(<js>"subType"</js>);
 			addSubType(MyClassBar.<jk>class</jk>, <js>"BAR"</js>);
 			addSubType(MyClassBaz.<jk>class</jk>, <js>"BAZ"</js>);
@@ -252,12 +252,12 @@
 		</p>
 		<p class='bcode'>
 	<jc>// Serialize to JSON</jc>
-	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyClassTransform.<jk>class</jk>);
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyBeanFilter.<jk>class</jk>);
 	MyClass c = <jk>new</jk> MyClassBar();
 	String json = s.serialize(p);  <jc>// Prints "{subType:'BAR',foo:'foo',bar:'bar'}"</jc>
 	
 	<jc>// Parse back into bean</jc>
-	ReaderParser p = <jk>new</jk> JsonParser().addTransforms(MyClassTransform.<jk>class</jk>);
+	ReaderParser p = <jk>new</jk> JsonParser().addTransforms(MyBeanFilter.<jk>class</jk>);
 	c = p.parse(json, MyClass.<jk>class</jk>); <jc>// c is an instance of MyClassBar</jc>
 		</p>	
 		<p>
@@ -290,7 +290,7 @@
 				<code>HttpServletRequest</code> and <code>HttpServletResponse</code>.
 			However, we really only want to serialize the properties defined on those specific APIs, not 
 				vendor-specific methods on the instances of those classes.
-			This can be done through the <code>interfaceClass</code> property of a bean transform.
+			This can be done through the <code>interfaceClass</code> property of a bean filter.
 		</p>
 		<p>
 			For example, let's define the following parent class and subclass:
@@ -312,8 +312,8 @@
 		</p>
 		<p class='bcode'>
 	<jc>// Define transform that limits properties to only those defined on MyClass</jc>
-	<jk>public class</jk> MyClassTransform <jk>extends</jk> BeanTransform&lt;MyClass&gt; {
-		<jk>public</jk> MyClassTransform() {
+	<jk>public class</jk> MyBeanFilter <jk>extends</jk> BeanFilter&lt;MyClass&gt; {
+		<jk>public</jk> MyBeanFilter() {
 			setInterfaceClass(MyClass.<jk>class</jk>);
 		}
 	}
@@ -323,7 +323,7 @@
 		</p>
 		<p class='bcode'>
 	<jc>// Serialize to JSON</jc>
-	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyClassTransform.<jk>class</jk>);
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyBeanFilter.<jk>class</jk>);
 	MyClass c = <jk>new</jk> MyClassBar();
 	String json = s.serialize(p);  <jc>// Prints "{foo:'foo'}"</jc>
 		</p>	
@@ -348,7 +348,7 @@
 		<p>
 			Also, the <code>addTransforms(...)</code> methods will automatically interpret any non-<code>Transform</code> classes
 				passed in as meaning interface classes.  
-			So in the previous example, the <code>BeanTransform</code> class could have been avoided altogether by just 
+			So in the previous example, the <code>BeanFilter</code> class could have been avoided altogether by just 
 				passing in <code>MyClass.<jk>class</jk></code> to the serializer, like so:
 		</p>
 		<p class='bcode'>
@@ -409,40 +409,40 @@
 	</div>
 
 	<!-- ======================================================================================================== -->
-	<a id="PojoTransforms"></a>
-	<h3 class='topic' onclick='toggle(this)'>1.2 - PojoTransform Class</h3>
+	<a id="PojoSwaps"></a>
+	<h3 class='topic' onclick='toggle(this)'>1.2 - PojoSwap Class</h3>
 	<div class='topic'>
 		<p>
-			{@link org.apache.juneau.transform.PojoTransform PojoTransforms} are a critical component of the Juneau architecture.  
+			{@link org.apache.juneau.transform.PojoSwap PojoSwaps} are a critical component of the Juneau architecture.  
 			They allow the Juneau serializers and parsers to be extended to handle virtually any kind of Java object. 
 		</p>
 		<p>
 			As explained in the overview, Juneau has built-in support for serializing and parsing specific kinds of objects, like primitive objects, bean, maps, collections, and arrays.  
 			Other kinds of POJOs, such as {@code Date} objects, cannot be serialized properly, since they are not true beans.  
-			This is where <code>PojoTransforms</code> come into play.
+			This is where <code>PojoSwaps</code> come into play.
 		</p>
 		<p>
-			The purpose of an <code>PojoTransform</code> is to convert a non-serializable object to a serializable surrogate form during serialization, and to optionally convert that surrogate form back into the original object during parsing.
+			The purpose of an <code>PojoSwap</code> is to convert a non-serializable object to a serializable surrogate form during serialization, and to optionally convert that surrogate form back into the original object during parsing.
 		</p>
 		<p>
 			For example, the following transform can be used to convert {@link java.util.Date} objects to ISO8601 strings during serialization, and {@link java.util.Date} objects from ISO8601 string during parsing:
 		</p>
 		<p class='bcode'>
 	<jc>// Sample transform for converting Dates to ISO8601 strings.</jc>
-	<jk>public class</jk> MyDateTransform <jk>extends</jk> PojoTransform&lt;Date,String&gt; {
+	<jk>public class</jk> MyDateSwap <jk>extends</jk> PojoSwap&lt;Date,String&gt; {
 		
 		<jc>// ISO8601 formatter.</jc>
 		<jk>private</jk> DateFormat <jf>format</jf> = <jk>new</jk> SimpleDateFormat(<js>"yyyy-MM-dd'T'HH:mm:ssZ"</js>);
 		
 		<jd>/** Converts a Date object to an ISO8601 string. */</jd>
 		<ja>@Override</ja>
-		<jk>public</jk> String transform(Date o) {
+		<jk>public</jk> String swap(Date o) {
 			<jk>return</jk> <jf>format</jf>.format(o);
 		}
 		
 		<jd>/** Converts an ISO8601 string to a Date object. */</jd>
 		<ja>@Override</ja>
-		<jk>public</jk> Date normalize(String o, ClassMeta&lt;?&gt; hint) <jk>throws</jk> ParseException {
+		<jk>public</jk> Date unswap(String o, ClassMeta&lt;?&gt; hint) <jk>throws</jk> ParseException {
 			<jk>try</jk> {
 				<jk>return</jk> <jf>format</jf>.parse(o);
 			} <jk>catch</jk> (java.text.ParseException e) {
@@ -461,11 +461,11 @@
 	}
 
 	<jc>// Create a new JSON serializer, associate our date transform with it, and serialize a sample bean.</jc>
-	Serializer serializer = <jk>new</jk> JsonSerializer().addTransforms(MyDateTransform.<jk>class</jk>);
+	Serializer serializer = <jk>new</jk> JsonSerializer().addTransforms(MyDateSwap.<jk>class</jk>);
 	String json = serializer.serialize(<jk>new</jk> MyBean());	<jc>// == "{date:'2012-03-03T04:05:06-0500'}"</jc>
 	
 	<jc>// Create a JSON parser, associate our date transform with it, and reconstruct our bean (including the date).</jc>
-	ReaderParser parser = <jk>new</jk> JsonParser().addTransforms(MyDateTransform.<jk>class</jk>);
+	ReaderParser parser = <jk>new</jk> JsonParser().addTransforms(MyDateSwap.<jk>class</jk>);
 	MyBean bean = parser.parse(json, MyBean.<jk>class</jk>);
 	<jk>int</jk> day = bean.<jf>date</jf>.getDay(); 						<jc>// == 3</jc>
 		</p>
@@ -474,7 +474,7 @@
 		</p>
 		<p class='bcode'>
 	<jc>// Create a new bean context and add our transform.</jc>
-	BeanContext beanContext = <jk>new</jk> BeanContext().addTransforms(MyDateTransform.<jk>class</jk>);
+	BeanContext beanContext = <jk>new</jk> BeanContext().addTransforms(MyDateSwap.<jk>class</jk>);
 
 	<jc>// Create a new bean.</jc>
 	MyBean myBean = <jk>new</jk> MyBean();
@@ -492,13 +492,13 @@
 	<jk>int</jk> year = myBean.<jf>date</jf>.getYear(); 								<jc>// == 113</jc>
 		</p>
 		<p>
-			Another example of a <code>PojoTransform</code> is one that converts <code><jk>byte</jk>[]</code> arrays to BASE64-encoded strings:
+			Another example of a <code>PojoSwap</code> is one that converts <code><jk>byte</jk>[]</code> arrays to BASE64-encoded strings:
 		</p>
 		<p class='bcode'>
-	<jk>public class</jk> ByteArrayBase64Transform <jk>extends</jk> PojoTransform&lt;<jk>byte</jk>[],String&gt; {
+	<jk>public class</jk> ByteArrayBase64Swap <jk>extends</jk> PojoSwap&lt;<jk>byte</jk>[],String&gt; {
 	
 		<ja>@Override</ja>
-		<jk>public</jk> String transform(<jk>byte</jk>[] b) <jk>throws</jk> SerializeException {
+		<jk>public</jk> String swap(<jk>byte</jk>[] b) <jk>throws</jk> SerializeException {
 			<jk>try</jk> {
 				ByteArrayOutputStream baos = <jk>new</jk> ByteArrayOutputStream();
 				OutputStream b64os = MimeUtility.encode(baos, <js>"base64"</js>);
@@ -511,7 +511,7 @@
 		}
 		
 		<ja>@Override</ja>
-		<jk>public byte</jk>[] normalize(String s, ClassMeta&lt;?&gt; hint) <jk>throws</jk> ParseException {
+		<jk>public byte</jk>[] unswap(String s, ClassMeta&lt;?&gt; hint) <jk>throws</jk> ParseException {
 			<jk>try</jk> {
 				<jk>byte</jk>[] b = s.getBytes();
 				ByteArrayInputStream bais = <jk>new</jk> ByteArrayInputStream(b);
@@ -532,8 +532,8 @@
 		</p>
 		<p class='bcode'>
 	<jc>// Create a JSON serializer and register the BASE64 encoding transform with it.</jc>
-	Serializer serializer = <jk>new</jk> JsonSerializer().addTransforms(ByteArrayBase64Transform.<jk>class</jk>);
-	ReaderParser parser = <jk>new</jk> JsonParser().addTransforms(ByteArrayBase64Transform.<jk>class</jk>);
+	Serializer serializer = <jk>new</jk> JsonSerializer().addTransforms(ByteArrayBase64Swap.<jk>class</jk>);
+	ReaderParser parser = <jk>new</jk> JsonParser().addTransforms(ByteArrayBase64Swap.<jk>class</jk>);
 	
 	<jk>byte</jk>[] a1 = {1,2,3};
 	String s1 = serializer.serialize(a1);		<jc>// Produces "'AQID'"</jc>
@@ -548,13 +548,13 @@
 			The following are a list of out-of-the-box transforms:
 		</p>
 		<ul class='spaced-list'>
-			<li>{@link org.apache.juneau.transforms.ByteArrayBase64Transform} - Converts byte arrays to BASE64 encoded strings.
-			<li>{@link org.apache.juneau.transforms.CalendarTransform} - Transforms for converting <code>Calendar</code> objects to various date format strings.
-			<li>{@link org.apache.juneau.transforms.DateTransform} - Transforms for converting <code>Date</code> objects to various date format strings.
-			<li>{@link org.apache.juneau.transforms.EnumerationTransform} - Transforms for converting <code>Enumeration</code> objects to arrays.
-			<li>{@link org.apache.juneau.transforms.IteratorTransform} - Transforms for converting <code>Iterator</code> objects to arrays.
-			<li>{@link org.apache.juneau.transforms.ReaderTransform} - Transforms for converting <code>Readers</code> to objects before serialization.
-			<li>{@link org.apache.juneau.transforms.XMLGregorianCalendarTransform} - Transforms for converting <code>XMLGregorianCalendar</code> objects to ISO8601 strings.
+			<li>{@link org.apache.juneau.transforms.ByteArrayBase64Swap} - Converts byte arrays to BASE64 encoded strings.
+			<li>{@link org.apache.juneau.transforms.CalendarSwap} - Transforms for converting <code>Calendar</code> objects to various date format strings.
+			<li>{@link org.apache.juneau.transforms.DateSwap} - Transforms for converting <code>Date</code> objects to various date format strings.
+			<li>{@link org.apache.juneau.transforms.EnumerationSwap} - Transforms for converting <code>Enumeration</code> objects to arrays.
+			<li>{@link org.apache.juneau.transforms.IteratorSwap} - Transforms for converting <code>Iterator</code> objects to arrays.
+			<li>{@link org.apache.juneau.transforms.ReaderSwap} - Transforms for converting <code>Readers</code> to objects before serialization.
+			<li>{@link org.apache.juneau.transforms.XMLGregorianCalendarSwap} - Transforms for converting <code>XMLGregorianCalendar</code> objects to ISO8601 strings.
 		</ul>
 		
 		<h6 class='topic'>Valid transformed class types</h6>
@@ -565,23 +565,23 @@
 	
 
 	<!-- ======================================================================================================== -->
-	<a id="PojoTransforms_OneWay"></a>
-	<h3 class='topic' onclick='toggle(this)'>1.3 - One-Way PojoTransforms</h3>
+	<a id="PojoSwaps_OneWay"></a>
+	<h3 class='topic' onclick='toggle(this)'>1.3 - One-Way PojoSwaps</h3>
 	<div class='topic'>
 		<p>
 			In the previous section, we defined two-way transforms, meaning transforms where the original objects could be reconstructing during parsing.  However, there are certain kinds of POJOs that we may want to support for serializing, but that are not possible to reconstruct during parsing.  For these, we can use one-way object transforms.
 		</p>
 		<p>
-			A one-way object transform is simply an object transform that only implements the {@code transform()} method.  The {@code normalize()} method is simply left unimplemented.
+			A one-way object transform is simply an object transform that only implements the {@code swap()} method.  The {@code unswap()} method is simply left unimplemented.
 		</p>
 		<p>
 			An example of a one-way transform would be one that allows {@code Iterators} to be serialized as JSON arrays.  It can make sense to be able to render {@code Iterators} as arrays, but in general it's not possible to reconstruct an {@code Iterator} during parsing. 
 		</p>
 		<p class='bcode'>
-	<jk>public class</jk> IteratorTransform <jk>extends</jk> PojoTransform&lt;Iterator,List&gt; {
+	<jk>public class</jk> IteratorSwap <jk>extends</jk> PojoSwap&lt;Iterator,List&gt; {
 		
 		<ja>@Override</ja>
-		<jk>public</jk> List transform(Iterator o) {
+		<jk>public</jk> List swap(Iterator o) {
 			List l = <jk>new</jk> LinkedList();
 			<jk>while</jk> (o.hasNext())
 				l.add(o.next());
@@ -594,7 +594,7 @@
 		</p>
 		<p class='bcode'>
 	<jc>// Create a JSON serializer that can serialize Iterators.</jc>
-	Serializer serializer = <jk>new</jk> JsonSerializer().addTransforms(IteratorTransform.<jk>class</jk>);
+	Serializer serializer = <jk>new</jk> JsonSerializer().addTransforms(IteratorSwap.<jk>class</jk>);
 	
 	<jc>// Construct an iterator we want to serialize.</jc>
 	Iterator iterator = <jk>new</jk> ObjectList(1,2,3).iterator();
@@ -603,7 +603,7 @@
 	String s = serializer.serialize(iterator);		<jc>// Produces "[1,2,3]"</jc>
 	
 	<jc>// Try to parse it.</jc>
-	ReaderParser parser = <jk>new</jk> JsonParser().addTransforms(IteratorTransform.<jk>class</jk>);
+	ReaderParser parser = <jk>new</jk> JsonParser().addTransforms(IteratorSwap.<jk>class</jk>);
 	iterator = parser.parse(s, Iterator.<jk>class</jk>);		<jc>// Throws ParseException!!!</jc>
 		</p>
 	</div>
@@ -636,8 +636,8 @@
 		</p>
 		<p class='bcode'>
 	<jc>// Define transform that limits properties to only those defined on MyClass</jc>
-	<jk>public class</jk> MyClassTransform <jk>extends</jk> BeanTransform&lt;MyClass&gt; {
-		<jk>public</jk> MyClassTransform() {
+	<jk>public class</jk> MyBeanFilter <jk>extends</jk> BeanFilter&lt;MyClass&gt; {
+		<jk>public</jk>  MyBeanFilter() {
 			setInterfaceClass(MyClass.<jk>class</jk>);
 		}
 	}
@@ -647,7 +647,7 @@
 		</p>
 		<p class='bcode'>
 	<jc>// Serialize to JSON</jc>
-	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyClassTransform.<jk>class</jk>);
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyBeanFilter.<jk>class</jk>);
 	MyClass c = <jk>new</jk> MyClassBar();
 	String json = s.serialize(p);  <jc>// Prints "{foo:'foo'}"</jc>
 		</p>	
@@ -671,7 +671,7 @@
 		</p>
 		<p>
 			Also, the <code>addTransforms()</code> methods will automatically interpret any non-Transform classes passed in as meaning interface classes. 
-			So in the previous example, the <code>BeanTransform</code> class could have been avoided altogether by just passing in <code>MyClass.<jk>class</jk></code> to the serializer, like so:
+			So in the previous example, the <code>BeanFilter</code> class could have been avoided altogether by just passing in <code>MyClass.<jk>class</jk></code> to the serializer, like so:
 		</p>
 		<p class='bcode'>
 	<jc>// Serialize to JSON</jc>
@@ -684,7 +684,7 @@
 	<h3 class='topic' onclick='toggle(this)'>1.5 - Surrogate Classes</h3>
 	<div class='topic'>
 		<p>
-			Surrogate classes are very similar in concept to one-way <code>PojoTransforms</code> except they represent a simpler syntax.
+			Surrogate classes are very similar in concept to one-way <code>PojoSwaps</code> except they represent a simpler syntax.
 		</p>
 		<p>
 			For example, let's say we want to be able to serialize the following class, but it's not serializable for some reason (for example, there are no
@@ -695,17 +695,17 @@
 	}
 		</p>
 		<p>
-			This could be solved with the following <code>PojoTransform</code>.
+			This could be solved with the following <code>PojoSwap</code>.
 		</p>
 		<p class='bcode'>
 	<jk>public class</jk> MySerializableSurrogate {
 		<jk>public</jk> String <jf>foo</jf>;
 	}
 		
-	<jk>public class</jk> MyTransform <jk>extends</jk> PojoTransform&lt;MyNonSerializableClass,MySerializableSurrogate&gt; {
+	<jk>public class</jk> MySwap <jk>extends</jk> PojoSwap&lt;MyNonSerializableClass,MySerializableSurrogate&gt; {
 		
 		<ja>@Override</ja>
-		<jk>public</jk> MySerializableSurrogate transform(MyNonSerializableClass o) {
+		<jk>public</jk> MySerializableSurrogate swap(MyNonSerializableClass o) {
 			MySerializableSurrogate s = <jk>new</jk> MySerializableSurrogate();
 			s.<jf>foo</jf> = o.<jf>foo</jf>;
 			<jk>return</jk> s;

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transforms/BeanStringSwap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/BeanStringSwap.java b/juneau-core/src/main/java/org/apache/juneau/transforms/BeanStringSwap.java
new file mode 100644
index 0000000..03fb6fc
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/BeanStringSwap.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.transforms;
+
+import org.apache.juneau.*;
+import org.apache.juneau.transform.*;
+
+/**
+ * Transforms beans into {@link String Strings} by simply calling the {@link Object#toString()} method.
+ * <p>
+ * 	Allows you to specify classes that should just be converted to {@code Strings} instead of potentially
+ * 	being turned into Maps by the {@link BeanContext} (or worse, throwing {@link BeanRuntimeException BeanRuntimeExceptions}).
+ * <p>
+ * 	This is usually a one-way transform.
+ * 	Beans serialized as strings cannot be reconstituted using a parser unless it is a <a class='doclink' href='../package-summary.html#PojoCategories'>Type 5 POJO</a>.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ * @param <T> The class type of the bean.
+ */
+public class BeanStringSwap<T> extends PojoSwap<T,String> {
+
+	/**
+	 * Converts the specified bean to a {@link String}.
+	 */
+	@Override /* PojoSwap */
+	public String swap(T o) {
+		return o.toString();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transforms/BeanStringTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/BeanStringTransform.java b/juneau-core/src/main/java/org/apache/juneau/transforms/BeanStringTransform.java
deleted file mode 100644
index 51ece7d..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/transforms/BeanStringTransform.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.transforms;
-
-import org.apache.juneau.*;
-import org.apache.juneau.transform.*;
-
-/**
- * Transforms beans into {@link String Strings} by simply calling the {@link Object#toString()} method.
- * <p>
- * 	Allows you to specify classes that should just be converted to {@code Strings} instead of potentially
- * 	being turned into Maps by the {@link BeanContext} (or worse, throwing {@link BeanRuntimeException BeanRuntimeExceptions}).
- * <p>
- * 	This is usually a one-way transform.
- * 	Beans serialized as strings cannot be reconstituted using a parser unless it is a <a class='doclink' href='../package-summary.html#PojoCategories'>Type 5 POJO</a>.
- *
- * @author James Bognar (james.bognar@salesforce.com)
- * @param <T> The class type of the bean.
- */
-public class BeanStringTransform<T> extends PojoTransform<T,String> {
-
-	/**
-	 * Converts the specified bean to a {@link String}.
-	 */
-	@Override /* PojoTransform */
-	public String transform(T o) {
-		return o.toString();
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transforms/ByteArrayBase64Swap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/ByteArrayBase64Swap.java b/juneau-core/src/main/java/org/apache/juneau/transforms/ByteArrayBase64Swap.java
new file mode 100644
index 0000000..5f8e584
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/ByteArrayBase64Swap.java
@@ -0,0 +1,51 @@
+/***************************************************************************************************************************
+ * 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.transforms;
+
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.transform.*;
+
+/**
+ * Transforms <code><jk>byte</jk>[]</code> arrays to BASE-64 encoded {@link String Strings}.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public class ByteArrayBase64Swap extends PojoSwap<byte[],String> {
+
+	/**
+	 * Converts the specified <code><jk>byte</jk>[]</code> to a {@link String}.
+	 */
+	@Override /* PojoSwap */
+	public String swap(byte[] b) throws SerializeException {
+		try {
+			return StringUtils.base64Encode(b);
+		} catch (Exception e) {
+			throw new SerializeException(e);
+		}
+	}
+
+	/**
+	 * Converts the specified {@link String} to a <code><jk>byte</jk>[]</code>.
+	 */
+	@Override /* PojoSwap */
+	public byte[] unswap(String s, ClassMeta<?> hint) throws ParseException {
+		try {
+			return StringUtils.base64Decode(s);
+		} catch (Exception e) {
+			throw new ParseException(e);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transforms/ByteArrayBase64Transform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/ByteArrayBase64Transform.java b/juneau-core/src/main/java/org/apache/juneau/transforms/ByteArrayBase64Transform.java
deleted file mode 100644
index f4f809d..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/transforms/ByteArrayBase64Transform.java
+++ /dev/null
@@ -1,51 +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.transforms;
-
-import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.serializer.*;
-import org.apache.juneau.transform.*;
-
-/**
- * Transforms <code><jk>byte</jk>[]</code> arrays to BASE-64 encoded {@link String Strings}.
- *
- * @author James Bognar (james.bognar@salesforce.com)
- */
-public class ByteArrayBase64Transform extends PojoTransform<byte[],String> {
-
-	/**
-	 * Converts the specified <code><jk>byte</jk>[]</code> to a {@link String}.
-	 */
-	@Override /* PojoTransform */
-	public String transform(byte[] b) throws SerializeException {
-		try {
-			return StringUtils.base64Encode(b);
-		} catch (Exception e) {
-			throw new SerializeException(e);
-		}
-	}
-
-	/**
-	 * Converts the specified {@link String} to a <code><jk>byte</jk>[]</code>.
-	 */
-	@Override /* PojoTransform */
-	public byte[] normalize(String s, ClassMeta<?> hint) throws ParseException {
-		try {
-			return StringUtils.base64Decode(s);
-		} catch (Exception e) {
-			throw new ParseException(e);
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarLongSwap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarLongSwap.java b/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarLongSwap.java
new file mode 100644
index 0000000..551c31c
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarLongSwap.java
@@ -0,0 +1,54 @@
+/***************************************************************************************************************************
+ * 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.transforms;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.transform.*;
+
+/**
+ * Transforms {@link Calendar Calendars} to {@link Long Longs} using {@code Calender.getTime().getTime()}.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public class CalendarLongSwap extends PojoSwap<Calendar,Long> {
+
+	/**
+	 * Converts the specified {@link Calendar} to a {@link Long}.
+	 */
+	@Override /* PojoSwap */
+	public Long swap(Calendar o) {
+		return o.getTime().getTime();
+	}
+
+	/**
+	 * Converts the specified {@link Long} to a {@link Calendar}.
+	 */
+	@Override /* PojoSwap */
+	@SuppressWarnings("unchecked")
+	public Calendar unswap(Long o, ClassMeta<?> hint) throws ParseException {
+		ClassMeta<? extends Calendar> tt;
+		try {
+			if (hint == null || ! hint.canCreateNewInstance())
+				hint = getBeanContext().getClassMeta(GregorianCalendar.class);
+			tt = (ClassMeta<? extends Calendar>)hint;
+			Calendar c = tt.newInstance();
+			c.setTimeInMillis(o);
+			return c;
+		} catch (Exception e) {
+			throw new ParseException(e);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarLongTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarLongTransform.java b/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarLongTransform.java
deleted file mode 100644
index 48423c0..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarLongTransform.java
+++ /dev/null
@@ -1,54 +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.transforms;
-
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.transform.*;
-
-/**
- * Transforms {@link Calendar Calendars} to {@link Long Longs} using {@code Calender.getTime().getTime()}.
- *
- * @author James Bognar (james.bognar@salesforce.com)
- */
-public class CalendarLongTransform extends PojoTransform<Calendar,Long> {
-
-	/**
-	 * Converts the specified {@link Calendar} to a {@link Long}.
-	 */
-	@Override /* PojoTransform */
-	public Long transform(Calendar o) {
-		return o.getTime().getTime();
-	}
-
-	/**
-	 * Converts the specified {@link Long} to a {@link Calendar}.
-	 */
-	@Override /* PojoTransform */
-	@SuppressWarnings("unchecked")
-	public Calendar normalize(Long o, ClassMeta<?> hint) throws ParseException {
-		ClassMeta<? extends Calendar> tt;
-		try {
-			if (hint == null || ! hint.canCreateNewInstance())
-				hint = getBeanContext().getClassMeta(GregorianCalendar.class);
-			tt = (ClassMeta<? extends Calendar>)hint;
-			Calendar c = tt.newInstance();
-			c.setTimeInMillis(o);
-			return c;
-		} catch (Exception e) {
-			throw new ParseException(e);
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarMapSwap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarMapSwap.java b/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarMapSwap.java
new file mode 100644
index 0000000..0dcd0d7
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarMapSwap.java
@@ -0,0 +1,62 @@
+/***************************************************************************************************************************
+ * 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.transforms;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.transform.*;
+
+/**
+ * Transforms {@link Calendar Calendars} to {@link Map Maps} of the format <code>{_class:String,value:long}</code>.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+@SuppressWarnings("rawtypes")
+public class CalendarMapSwap extends PojoSwap<Calendar,Map> {
+
+	/**
+	 * Converts the specified {@link Calendar} to a {@link Map}.
+	 */
+	@Override /* PojoSwap */
+	public Map swap(Calendar o) {
+		ObjectMap m = new ObjectMap();
+		m.put("time", o.getTime().getTime());
+		m.put("timeZone", o.getTimeZone().getID());
+		return m;
+	}
+
+	/**
+	 * Converts the specified {@link Map} to a {@link Calendar}.
+	 */
+	@Override /* PojoSwap */
+	@SuppressWarnings("unchecked")
+	public Calendar unswap(Map o, ClassMeta<?> hint) throws ParseException {
+		ClassMeta<? extends Calendar> tt;
+		try {
+			if (hint == null || ! hint.canCreateNewInstance())
+				hint = getBeanContext().getClassMeta(GregorianCalendar.class);
+			tt = (ClassMeta<? extends Calendar>)hint;
+			long time = Long.parseLong(o.get("time").toString());
+			String timeZone = o.get("timeZone").toString();
+			Date d = new Date(time);
+			Calendar c = tt.newInstance();
+			c.setTime(d);
+			c.setTimeZone(TimeZone.getTimeZone(timeZone));
+			return c;
+		} catch (Exception e) {
+			throw new ParseException(e);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarMapTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarMapTransform.java b/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarMapTransform.java
deleted file mode 100644
index 1582a61..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarMapTransform.java
+++ /dev/null
@@ -1,62 +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.transforms;
-
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.transform.*;
-
-/**
- * Transforms {@link Calendar Calendars} to {@link Map Maps} of the format <code>{_class:String,value:long}</code>.
- *
- * @author James Bognar (james.bognar@salesforce.com)
- */
-@SuppressWarnings("rawtypes")
-public class CalendarMapTransform extends PojoTransform<Calendar,Map> {
-
-	/**
-	 * Converts the specified {@link Calendar} to a {@link Map}.
-	 */
-	@Override /* PojoTransform */
-	public Map transform(Calendar o) {
-		ObjectMap m = new ObjectMap();
-		m.put("time", o.getTime().getTime());
-		m.put("timeZone", o.getTimeZone().getID());
-		return m;
-	}
-
-	/**
-	 * Converts the specified {@link Map} to a {@link Calendar}.
-	 */
-	@Override /* PojoTransform */
-	@SuppressWarnings("unchecked")
-	public Calendar normalize(Map o, ClassMeta<?> hint) throws ParseException {
-		ClassMeta<? extends Calendar> tt;
-		try {
-			if (hint == null || ! hint.canCreateNewInstance())
-				hint = getBeanContext().getClassMeta(GregorianCalendar.class);
-			tt = (ClassMeta<? extends Calendar>)hint;
-			long time = Long.parseLong(o.get("time").toString());
-			String timeZone = o.get("timeZone").toString();
-			Date d = new Date(time);
-			Calendar c = tt.newInstance();
-			c.setTime(d);
-			c.setTimeZone(TimeZone.getTimeZone(timeZone));
-			return c;
-		} catch (Exception e) {
-			throw new ParseException(e);
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarSwap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarSwap.java b/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarSwap.java
new file mode 100644
index 0000000..62af394
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarSwap.java
@@ -0,0 +1,293 @@
+/***************************************************************************************************************************
+ * 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.transforms;
+
+import java.text.*;
+import java.util.*;
+
+import javax.xml.bind.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.parser.ParseException;
+import org.apache.juneau.transform.*;
+
+/**
+ * Transforms {@link Calendar Calendars} to {@link String Strings}.
+ *
+ *
+ * <h6 class='topic'>Behavior-specific subclasses</h6>
+ * <p>
+ * 	The following direct subclasses are provided for convenience:
+ * <ul class='spaced-list'>
+ * 	<li>{@link ToString} - Transforms to {@link String Strings} using the {@code Date.toString()} method.
+ * 	<li>{@link ISO8601DT} - Transforms to ISO8601 date-time strings.
+ * 	<li>{@link ISO8601DTZ} - Same as {@link ISO8601DT}, except always serializes in GMT.
+ * 	<li>{@link RFC2822DT} - Transforms to RFC2822 date-time strings.
+ * 	<li>{@link RFC2822DTZ} - Same as {@link RFC2822DT}, except always serializes in GMT.
+ * 	<li>{@link RFC2822D} - Transforms to RFC2822 date strings.
+ * 	<li>{@link Simple} - Transforms to simple <js>"yyyy/MM/dd HH:mm:ss"</js> strings.
+ * 	<li>{@link Medium} - Transforms to {@link DateFormat#MEDIUM} strings.
+ * </ul>
+ *
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public class CalendarSwap extends PojoSwap<Calendar,String> {
+
+	private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
+
+	/**
+	 * Transforms {@link Calendar Calendars} to {@link String Strings} using the {@code Date.toString()} method.
+	 *
+	 * <dl>
+	 * 	<dt>Example output:</dt>
+	 * 	<dd>
+	 * 		<ul>
+	 * 			<li><js>"Wed Jul 04 15:30:45 EST 2001"</js>
+	 * 		</ul>
+	 * 	</dd>
+	 * </dl>
+	 */
+	public static class ToString extends CalendarSwap {
+		/** Constructor */
+		public ToString() {
+			super("EEE MMM dd HH:mm:ss zzz yyyy");
+		}
+	}
+
+	/**
+	 * Transforms {@link Calendar Calendars} to ISO8601 date-time strings.
+	 *
+	 * <dl>
+	 * 	<dt>Example output:</dt>
+	 * 	<dd>
+	 * 		<ul>
+	 * 			<li><js>"2001-07-04T15:30:45-05:00"</js>
+	 * 			<li><js>"2001-07-04T15:30:45Z"</js>
+	 * 		</ul>
+	 * 	</dd>
+	 * 	<dt>Example input:</dt>
+	 * 	<dd>
+	 * 		<ul>
+	 * 			<li><js>"2001-07-04T15:30:45-05:00"</js>
+	 * 			<li><js>"2001-07-04T15:30:45Z"</js>
+	 * 			<li><js>"2001-07-04T15:30:45.1Z"</js>
+	 * 			<li><js>"2001-07-04T15:30Z"</js>
+	 * 			<li><js>"2001-07-04"</js>
+	 * 			<li><js>"2001-07"</js>
+	 * 			<li><js>"2001"</js>
+	 *			 </ul>
+	 * 	</dd>
+	 * </dl>
+	 */
+	public static class ISO8601DT extends CalendarSwap {
+
+		/** Constructor */
+		public ISO8601DT() {}
+
+		@Override /* PojoSwap */
+		public Calendar unswap(String o, ClassMeta<?> hint) throws ParseException {
+			try {
+				if (StringUtils.isEmpty(o))
+					return null;
+				return convert(DatatypeConverter.parseDateTime(o), hint);
+			} catch (Exception e) {
+				throw new ParseException(e);
+			}
+		}
+
+		@Override /* PojoSwap */
+		public String swap(Calendar o) {
+			return DatatypeConverter.printDateTime(o);
+		}
+	}
+
+	/**
+	 * Same as {@link ISO8601DT}, except always serializes in GMT.
+	 * <p>
+	 * Example output: <js>"2001-07-04T15:30:45Z"</js>
+	 */
+	public static class ISO8601DTZ extends CalendarSwap {
+
+		/** Constructor */
+		public ISO8601DTZ() {}
+
+		@Override /* PojoSwap */
+		public Calendar unswap(String o, ClassMeta<?> hint) throws ParseException {
+			try {
+				if (StringUtils.isEmpty(o))
+					return null;
+				return convert(DatatypeConverter.parseDateTime(o), hint);
+			} catch (Exception e) {
+				throw new ParseException(e);
+			}
+		}
+
+		@Override /* PojoSwap */
+		public String swap(Calendar o) {
+			if (o.getTimeZone().getRawOffset() != 0) {
+				Calendar c = Calendar.getInstance(GMT);
+				c.setTime(o.getTime());
+				o = c;
+			}
+			return DatatypeConverter.printDateTime(o);
+		}
+	}
+
+	/**
+	 * Transforms {@link Calendar Calendars} to RFC2822 date-time strings.
+	 */
+	public static class RFC2822DT extends CalendarSwap {
+		/** Constructor */
+		public RFC2822DT() {
+			super("EEE, dd MMM yyyy HH:mm:ss Z");
+		}
+	}
+
+	/**
+	 * Same as {@link RFC2822DT}, except always serializes in GMT.
+	 * <p>
+	 * Example output: <js>"Wed, 31 Jan 2001 12:34:56 +0000"</js>
+	 */
+	public static class RFC2822DTZ extends CalendarSwap {
+		/** Constructor */
+		public RFC2822DTZ() {
+			super("EEE, dd MMM yyyy HH:mm:ss 'GMT'", GMT);
+		}
+	}
+
+	/**
+	 * Transforms {@link Calendar Calendars} to RFC2822 date strings.
+	 */
+	public static class RFC2822D extends CalendarSwap {
+		/** Constructor */
+		public RFC2822D() {
+			super("dd MMM yyyy");
+		}
+	}
+
+	/**
+	 * Transforms {@link Calendar Calendars} to simple <js>"yyyy/MM/dd HH:mm:ss"</js> strings.
+	 */
+	public static class Simple extends CalendarSwap {
+		/** Constructor */
+		public Simple() {
+			super("yyyy/MM/dd HH:mm:ss");
+		}
+	}
+
+	/**
+	 * Transforms {@link Calendar Calendars} to {@link DateFormat#MEDIUM} strings.
+	 */
+	public static class Medium extends CalendarSwap {
+		/** Constructor */
+		public Medium() {
+			super(DateFormat.getDateInstance(DateFormat.MEDIUM));
+		}
+	}
+
+	/** The formatter to convert dates to Strings. */
+	private DateFormat format;
+
+	private TimeZone timeZone;
+
+	/**
+	 * Default constructor.
+	 * <p>
+	 * 	This constructor is used when <code>swap()</code> and <code>unswap()</code> are overridden by subclasses.
+	 */
+	public CalendarSwap() {}
+
+	/**
+	 * Construct a transform using the specified date format string that will be
+	 * 	used to construct a {@link SimpleDateFormat} that will be used to convert
+	 * 	dates to strings.
+	 *
+	 * @param simpleDateFormat The {@link SimpleDateFormat} pattern.
+	 */
+	public CalendarSwap(String simpleDateFormat) {
+		this(new SimpleDateFormat(simpleDateFormat));
+	}
+
+	/**
+	 * Construct a transform using the specified date format string that will be
+	 * 	used to construct a {@link SimpleDateFormat} that will be used to convert
+	 * 	dates to strings.
+	 *
+	 * @param simpleDateFormat The {@link SimpleDateFormat} pattern.
+	 * @param timeZone The time zone to associate with the date pattern.
+	 */
+	public CalendarSwap(String simpleDateFormat, TimeZone timeZone) {
+		this(new SimpleDateFormat(simpleDateFormat));
+		format.setTimeZone(timeZone);
+		this.timeZone = timeZone;
+	}
+
+	/**
+	 * Construct a transform using the specified {@link DateFormat} that will be used to convert
+	 * 	dates to strings.
+	 *
+	 * @param format The format to use to convert dates to strings.
+	 */
+	public CalendarSwap(DateFormat format) {
+		super();
+		this.format = format;
+	}
+
+	/**
+	 * Converts the specified {@link Calendar} to a {@link String}.
+	 */
+	@Override /* PojoSwap */
+	public String swap(Calendar o) {
+		DateFormat df = format;
+		TimeZone tz1 = o.getTimeZone();
+		TimeZone tz2 = format.getTimeZone();
+		if (timeZone == null && ! tz1.equals(tz2)) {
+			df = (DateFormat)format.clone();
+			df.setTimeZone(tz1);
+		}
+		return df.format(o.getTime());
+	}
+
+	/**
+	 * Converts the specified {@link String} to a {@link Calendar}.
+	 */
+	@Override /* PojoSwap */
+	public Calendar unswap(String o, ClassMeta<?> hint) throws ParseException {
+		try {
+			if (StringUtils.isEmpty(o))
+				return null;
+			return convert(format.parse(o), hint);
+		} catch (Exception e) {
+			throw new ParseException(e);
+		}
+	}
+
+	private static Calendar convert(Calendar in, ClassMeta<?> hint) throws Exception {
+		if (hint.isInstance(in) || ! hint.canCreateNewInstance())
+			return in;
+		Calendar c = (Calendar)hint.newInstance();
+		c.setTime(in.getTime());
+		c.setTimeZone(in.getTimeZone());
+		return c;
+	}
+
+	private static Calendar convert(Date in, ClassMeta<?> hint) throws Exception {
+		if (hint == null || ! hint.canCreateNewInstance())
+			hint = BeanContext.DEFAULT.getClassMeta(GregorianCalendar.class);
+		Calendar c = (Calendar)hint.newInstance();
+		c.setTime(in);
+		return c;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarTransform.java b/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarTransform.java
deleted file mode 100644
index 6847dca..0000000
--- a/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarTransform.java
+++ /dev/null
@@ -1,293 +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.transforms;
-
-import java.text.*;
-import java.util.*;
-
-import javax.xml.bind.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
-import org.apache.juneau.parser.ParseException;
-import org.apache.juneau.transform.*;
-
-/**
- * Transforms {@link Calendar Calendars} to {@link String Strings}.
- *
- *
- * <h6 class='topic'>Behavior-specific subclasses</h6>
- * <p>
- * 	The following direct subclasses are provided for convenience:
- * <ul class='spaced-list'>
- * 	<li>{@link ToString} - Transforms to {@link String Strings} using the {@code Date.toString()} method.
- * 	<li>{@link ISO8601DT} - Transforms to ISO8601 date-time strings.
- * 	<li>{@link ISO8601DTZ} - Same as {@link ISO8601DT}, except always serializes in GMT.
- * 	<li>{@link RFC2822DT} - Transforms to RFC2822 date-time strings.
- * 	<li>{@link RFC2822DTZ} - Same as {@link RFC2822DT}, except always serializes in GMT.
- * 	<li>{@link RFC2822D} - Transforms to RFC2822 date strings.
- * 	<li>{@link Simple} - Transforms to simple <js>"yyyy/MM/dd HH:mm:ss"</js> strings.
- * 	<li>{@link Medium} - Transforms to {@link DateFormat#MEDIUM} strings.
- * </ul>
- *
- *
- * @author James Bognar (james.bognar@salesforce.com)
- */
-public class CalendarTransform extends PojoTransform<Calendar,String> {
-
-	private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
-
-	/**
-	 * Transforms {@link Calendar Calendars} to {@link String Strings} using the {@code Date.toString()} method.
-	 *
-	 * <dl>
-	 * 	<dt>Example output:</dt>
-	 * 	<dd>
-	 * 		<ul>
-	 * 			<li><js>"Wed Jul 04 15:30:45 EST 2001"</js>
-	 * 		</ul>
-	 * 	</dd>
-	 * </dl>
-	 */
-	public static class ToString extends CalendarTransform {
-		/** Constructor */
-		public ToString() {
-			super("EEE MMM dd HH:mm:ss zzz yyyy");
-		}
-	}
-
-	/**
-	 * Transforms {@link Calendar Calendars} to ISO8601 date-time strings.
-	 *
-	 * <dl>
-	 * 	<dt>Example output:</dt>
-	 * 	<dd>
-	 * 		<ul>
-	 * 			<li><js>"2001-07-04T15:30:45-05:00"</js>
-	 * 			<li><js>"2001-07-04T15:30:45Z"</js>
-	 * 		</ul>
-	 * 	</dd>
-	 * 	<dt>Example input:</dt>
-	 * 	<dd>
-	 * 		<ul>
-	 * 			<li><js>"2001-07-04T15:30:45-05:00"</js>
-	 * 			<li><js>"2001-07-04T15:30:45Z"</js>
-	 * 			<li><js>"2001-07-04T15:30:45.1Z"</js>
-	 * 			<li><js>"2001-07-04T15:30Z"</js>
-	 * 			<li><js>"2001-07-04"</js>
-	 * 			<li><js>"2001-07"</js>
-	 * 			<li><js>"2001"</js>
-	 *			 </ul>
-	 * 	</dd>
-	 * </dl>
-	 */
-	public static class ISO8601DT extends CalendarTransform {
-
-		/** Constructor */
-		public ISO8601DT() {}
-
-		@Override /* PojoTransform */
-		public Calendar normalize(String o, ClassMeta<?> hint) throws ParseException {
-			try {
-				if (StringUtils.isEmpty(o))
-					return null;
-				return convert(DatatypeConverter.parseDateTime(o), hint);
-			} catch (Exception e) {
-				throw new ParseException(e);
-			}
-		}
-
-		@Override /* PojoTransform */
-		public String transform(Calendar o) {
-			return DatatypeConverter.printDateTime(o);
-		}
-	}
-
-	/**
-	 * Same as {@link ISO8601DT}, except always serializes in GMT.
-	 * <p>
-	 * Example output: <js>"2001-07-04T15:30:45Z"</js>
-	 */
-	public static class ISO8601DTZ extends CalendarTransform {
-
-		/** Constructor */
-		public ISO8601DTZ() {}
-
-		@Override /* PojoTransform */
-		public Calendar normalize(String o, ClassMeta<?> hint) throws ParseException {
-			try {
-				if (StringUtils.isEmpty(o))
-					return null;
-				return convert(DatatypeConverter.parseDateTime(o), hint);
-			} catch (Exception e) {
-				throw new ParseException(e);
-			}
-		}
-
-		@Override /* PojoTransform */
-		public String transform(Calendar o) {
-			if (o.getTimeZone().getRawOffset() != 0) {
-				Calendar c = Calendar.getInstance(GMT);
-				c.setTime(o.getTime());
-				o = c;
-			}
-			return DatatypeConverter.printDateTime(o);
-		}
-	}
-
-	/**
-	 * Transforms {@link Calendar Calendars} to RFC2822 date-time strings.
-	 */
-	public static class RFC2822DT extends CalendarTransform {
-		/** Constructor */
-		public RFC2822DT() {
-			super("EEE, dd MMM yyyy HH:mm:ss Z");
-		}
-	}
-
-	/**
-	 * Same as {@link RFC2822DT}, except always serializes in GMT.
-	 * <p>
-	 * Example output: <js>"Wed, 31 Jan 2001 12:34:56 +0000"</js>
-	 */
-	public static class RFC2822DTZ extends CalendarTransform {
-		/** Constructor */
-		public RFC2822DTZ() {
-			super("EEE, dd MMM yyyy HH:mm:ss 'GMT'", GMT);
-		}
-	}
-
-	/**
-	 * Transforms {@link Calendar Calendars} to RFC2822 date strings.
-	 */
-	public static class RFC2822D extends CalendarTransform {
-		/** Constructor */
-		public RFC2822D() {
-			super("dd MMM yyyy");
-		}
-	}
-
-	/**
-	 * Transforms {@link Calendar Calendars} to simple <js>"yyyy/MM/dd HH:mm:ss"</js> strings.
-	 */
-	public static class Simple extends CalendarTransform {
-		/** Constructor */
-		public Simple() {
-			super("yyyy/MM/dd HH:mm:ss");
-		}
-	}
-
-	/**
-	 * Transforms {@link Calendar Calendars} to {@link DateFormat#MEDIUM} strings.
-	 */
-	public static class Medium extends CalendarTransform {
-		/** Constructor */
-		public Medium() {
-			super(DateFormat.getDateInstance(DateFormat.MEDIUM));
-		}
-	}
-
-	/** The formatter to convert dates to Strings. */
-	private DateFormat format;
-
-	private TimeZone timeZone;
-
-	/**
-	 * Default constructor.
-	 * <p>
-	 * 	This constructor is used when <code>transform()</code> and <code>normalize()</code> are overridden by subclasses.
-	 */
-	public CalendarTransform() {}
-
-	/**
-	 * Construct a transform using the specified date format string that will be
-	 * 	used to construct a {@link SimpleDateFormat} that will be used to convert
-	 * 	dates to strings.
-	 *
-	 * @param simpleDateFormat The {@link SimpleDateFormat} pattern.
-	 */
-	public CalendarTransform(String simpleDateFormat) {
-		this(new SimpleDateFormat(simpleDateFormat));
-	}
-
-	/**
-	 * Construct a transform using the specified date format string that will be
-	 * 	used to construct a {@link SimpleDateFormat} that will be used to convert
-	 * 	dates to strings.
-	 *
-	 * @param simpleDateFormat The {@link SimpleDateFormat} pattern.
-	 * @param timeZone The time zone to associate with the date pattern.
-	 */
-	public CalendarTransform(String simpleDateFormat, TimeZone timeZone) {
-		this(new SimpleDateFormat(simpleDateFormat));
-		format.setTimeZone(timeZone);
-		this.timeZone = timeZone;
-	}
-
-	/**
-	 * Construct a transform using the specified {@link DateFormat} that will be used to convert
-	 * 	dates to strings.
-	 *
-	 * @param format The format to use to convert dates to strings.
-	 */
-	public CalendarTransform(DateFormat format) {
-		super();
-		this.format = format;
-	}
-
-	/**
-	 * Converts the specified {@link Calendar} to a {@link String}.
-	 */
-	@Override /* PojoTransform */
-	public String transform(Calendar o) {
-		DateFormat df = format;
-		TimeZone tz1 = o.getTimeZone();
-		TimeZone tz2 = format.getTimeZone();
-		if (timeZone == null && ! tz1.equals(tz2)) {
-			df = (DateFormat)format.clone();
-			df.setTimeZone(tz1);
-		}
-		return df.format(o.getTime());
-	}
-
-	/**
-	 * Converts the specified {@link String} to a {@link Calendar}.
-	 */
-	@Override /* PojoTransform */
-	public Calendar normalize(String o, ClassMeta<?> hint) throws ParseException {
-		try {
-			if (StringUtils.isEmpty(o))
-				return null;
-			return convert(format.parse(o), hint);
-		} catch (Exception e) {
-			throw new ParseException(e);
-		}
-	}
-
-	private static Calendar convert(Calendar in, ClassMeta<?> hint) throws Exception {
-		if (hint.isInstance(in) || ! hint.canCreateNewInstance())
-			return in;
-		Calendar c = (Calendar)hint.newInstance();
-		c.setTime(in.getTime());
-		c.setTimeZone(in.getTimeZone());
-		return c;
-	}
-
-	private static Calendar convert(Date in, ClassMeta<?> hint) throws Exception {
-		if (hint == null || ! hint.canCreateNewInstance())
-			hint = BeanContext.DEFAULT.getClassMeta(GregorianCalendar.class);
-		Calendar c = (Calendar)hint.newInstance();
-		c.setTime(in);
-		return c;
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/ee27361d/juneau-core/src/main/java/org/apache/juneau/transforms/DateLongSwap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/DateLongSwap.java b/juneau-core/src/main/java/org/apache/juneau/transforms/DateLongSwap.java
new file mode 100644
index 0000000..06c0310
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/DateLongSwap.java
@@ -0,0 +1,52 @@
+/***************************************************************************************************************************
+ * 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.transforms;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.transform.*;
+
+/**
+ * Transforms {@link Date Dates} to {@link Long Longs}.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public class DateLongSwap extends PojoSwap<Date,Long> {
+
+	/**
+	 * Converts the specified {@link Date} to a {@link Long}.
+	 */
+	@Override /* PojoSwap */
+	public Long swap(Date o) {
+		return o.getTime();
+	}
+
+	/**
+	 * Converts the specified {@link Long} to a {@link Date}.
+	 */
+	@Override /* PojoSwap */
+	public Date unswap(Long o, ClassMeta<?> hint) throws ParseException {
+		Class<?> c = (hint == null ? java.util.Date.class : hint.getInnerClass());
+		if (c == java.util.Date.class)
+			return new java.util.Date(o);
+		if (c == java.sql.Date.class)
+			return new java.sql.Date(o);
+		if (c == java.sql.Time.class)
+			return new java.sql.Time(o);
+		if (c == java.sql.Timestamp.class)
+			return new java.sql.Timestamp(o);
+		throw new ParseException("DateLongSwap is unable to narrow object of type ''{0}''", c);
+	}
+}