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/09 19:53:51 UTC

[18/51] [partial] incubator-juneau git commit: Rename project directories.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/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
new file mode 100644
index 0000000..c9a953e
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/package.html
@@ -0,0 +1,771 @@
+<!DOCTYPE HTML>
+<!--
+/***************************************************************************************************************************
+ * 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.
+ *
+ ***************************************************************************************************************************/
+ -->
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+	<style type="text/css">
+		/* For viewing in Page Designer */
+		@IMPORT url("../../../../../../javadoc.css");
+
+		/* For viewing in REST interface */
+		@IMPORT url("../htdocs/javadoc.css");
+		body { 
+			margin: 20px; 
+		}	
+	</style>
+	<script>
+		/* Replace all @code and @link tags. */	
+		window.onload = function() {
+			document.body.innerHTML = document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>');
+			document.body.innerHTML = document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, '<code>$3</code>');
+		}
+	</script>
+</head>
+<body>
+<p>Transform API</p>
+
+<script>
+	function toggle(x) {
+		var div = x.nextSibling;
+		while (div != null && div.nodeType != 1)
+			div = div.nextSibling;
+		if (div != null) {
+			var d = div.style.display;
+			if (d == 'block' || d == '') {
+				div.style.display = 'none';
+				x.className += " closed";
+			} else {
+				div.style.display = 'block';
+				x.className = x.className.replace(/(?:^|\s)closed(?!\S)/g , '' );
+			}
+		}
+	}
+</script>
+
+<a id='TOC'></a><h5 class='toc'>Table of Contents</h5>
+<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='#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>
+	</ol>
+</ol>
+
+<!-- ======================================================================================================== -->
+<a id="Transforms"></a>
+<h2 class='topic' onclick='toggle(this)'>1 - Transforms</h2>
+<div class='topic'>
+	<p>
+		By default, the Juneau framework can serialize and parse a wide variety of POJOs out-of-the-box.  
+		However, a <code>Transform</code> API is provided to tailor how certain Java objects are handled by the framework.
+		The class hierarchy is shown here:
+	</p>
+	<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 
+			(and optionally vis-versa during parsing).
+		</ul>
+	</ul>
+	<p>
+		Transforms are added to serializers and parsers in a variety of ways:
+	</p> 
+	<ul class='spaced-list'>
+		<li>{@link org.apache.juneau.serializer.Serializer#addTransforms(Class[])} - On serializers.
+		<li>{@link org.apache.juneau.serializer.SerializerGroup#addTransforms(Class[])} - On groups of serializers.
+		<li>{@link org.apache.juneau.parser.Parser#addTransforms(Class[])} - On parsers.
+		<li>{@link org.apache.juneau.parser.ParserGroup#addTransforms(Class[])} - On groups of parsers.
+		<li>{@link org.apache.juneau.client.RestClient#addTransforms(Class[])} - On the serializer and parser registered on a REST client.
+		<li>{@link org.apache.juneau.server.annotation.RestResource#transforms() @RestResource.transforms()} - On all serializers and parsers defined on a REST servlet.
+		<li>{@link org.apache.juneau.server.annotation.RestMethod#transforms() @RestMethod.transforms()} - On all serializers and parsers defined on a method in a REST servlet.
+		<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. 
+	</p>
+		
+	<!-- ======================================================================================================== -->
+	<a id="BeanTransforms"></a>
+	<h3 class='topic' onclick='toggle(this)'>1.1 - BeanTransform Class</h3>
+	<div class='topic'>
+		<p>
+			Bean transforms are used to tailor how Juneau handles bean classes.
+			They can be used for the following purposes:
+		</p>
+		<ul class='spaced-list'>
+			<li>Include or exclude which properties are exposed in beans, or the order those properties are serialized.
+			<li>Define property-namers for customizing bean property names.
+			<li>Define bean subtypes.
+			<li>Define bean interface classes.
+		</ul>
+		<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
+				not have access to the source code.
+		<p>
+		<h5 class='topic'>Examples</h5>
+
+		<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&ltPerson&gt; {
+		<jk>public</jk> MyTransform() {
+			setProperties(<js>"age"</js>,<js>"name"</js>);
+		}
+	}
+	
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyTransform.<jk>class</jk>);
+	Person p = getPerson();
+	String json = s.serialize(p);  <jc>// Prints "{age:45,name:'John Smith'}"</jc>
+		</p>
+		<p>
+			Note that this is equivalent to specifying the following annotation on the bean class:
+		</p>
+		<p class='bcode'>
+	<ja>@Bean</ja>(properties={<js>"age"</js>,<js>"name"</js>})
+	<jk>public class</jk> Person {
+		...
+	}
+		</p>
+
+		<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&ltPerson&gt; {
+		<jk>public</jk> MyTransform() {
+			setExcludeProperties(<js>"name"</js>);
+		}
+	}
+	
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyTransform.<jk>class</jk>);
+	Person p = getPerson();
+	String json = s.serialize(p);  <jc>// Prints "{age:45}"</jc>
+		</p>
+		<p>
+			Note that this is equivalent to specifying the following annotation on the bean class:
+		</p>
+		<p class='bcode'>
+	<ja>@Bean</ja>(excludeProperties={<js>"name"</js>})
+	<jk>public class</jk> Person {
+		...
+	}
+		</p>
+
+		<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&ltPerson&gt; {
+		<jk>public</jk> MyTransform() {
+			setPropertyNamer(UpperCasePropertyNamer.<jk>class</jk>);
+		}
+	}
+
+	<jc>// Define property namer that upper-cases the property names</jc>	
+	<jk>public class</jk> UpperCasePropertyNamer <jk>implements</jk> PropertyNamer {
+	
+		<ja>@Override</ja>
+		<jk>public</jk> String getPropertyName(String name) {
+			<jk>return</jk> name.toUpperCase();
+		}
+	}
+	
+	<jc>// Serialize to JSON</jc>
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyTransform.<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>);
+	person = p.parse(json, Person.class); <jc>// Read back into original object</jc>
+		</p>
+		<p>
+			Note that this is equivalent to specifying the following annotation on the bean class:
+		</p>
+		<p class='bcode'>
+	<ja>@Bean</ja>(propertyNamer=UpperCasePropertyNamer.<jk>class</jk>)
+	<jk>public class</jk> Person {
+		...
+	}
+		</p>
+		
+		<h6 class='topic'>Define bean subtypes</h6>
+		<p>
+			Juneau allows you to losslessly serialize and parse abstract class fields back into the original 
+				concrete objects by defining a subtype attribute and a list of subtypes/ids.
+		</p>
+		<p>
+			For example, let's define the following parent class with two subclasses:
+		</p>
+		<p class='bcode'>
+	<jc>// Abstract parent class</jc>
+	<jk>public abstract class</jk> MyClass {
+		<jk>public</jk> String <jf>foo</jf>=<js>"foo"</js>;
+	}
+
+	<jc>// Subclass 1</jc>
+	<jk>public class</jk> MyClassBar <jk>extends</jk> MyClass {
+		<jk>public</jk> String <jf>bar</jf>=<js>"bar"</js>;
+	}
+	
+	<jc>// Subclass 2</jc>
+	<jk>public class</jk> MyClassBaz <jk>extends</jk> MyClass {
+		<jk>public</jk> String <jf>baz</jf>=<js>"baz"</js>;
+	}
+		</p>
+		<p>
+			Normally, when parsing a serialized <code>MyClass</code> object, the parser does not know what subtype to create.
+			This can be fixed by defining the following transform:
+		</p>		
+		<p class='bcode'>
+	<jc>// Define transform with our own property namer.</jc>
+	<jk>public class</jk> MyClassTransform <jk>extends</jk> BeanTransform&ltMyClass&gt; {
+		<jk>public</jk> MyClassTransform() {
+			setSubTypeProperty(<js>"subType"</js>);
+			addSubType(MyClassBar.<jk>class</jk>, <js>"BAR"</js>);
+			addSubType(MyClassBaz.<jk>class</jk>, <js>"BAZ"</js>);
+		}
+	}
+		</p>
+		<p>
+			When serialized, the serialized bean will include a <code>"subType"</code> attribute that identifies the subclass, and
+				allows it to be parsed back into the original subclass.
+		</p>
+		<p class='bcode'>
+	<jc>// Serialize to JSON</jc>
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyClassTransform.<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>);
+	c = p.parse(json, MyClass.<jk>class</jk>); <jc>// c is an instance of MyClassBar</jc>
+		</p>	
+		<p>
+			It should be noted that the sub type attribute is always rendered first in the JSON object so 
+				that the bean object can be instantiated before the real properties are set on it during parsing.  
+			Beans with subtypes are thus 'lazy-instantiated' when the sub type attribute is set.
+			If the sub type attribute is not listed first, the parser will still be able to parse the input,
+			but with reduced efficiency since it must cache the incoming data until the bean can be instantiated.
+		</p>
+		<p>
+			Note that this transform is equivalent to specifying the following annotation on the bean class:
+		</p>
+		<p class='bcode'>
+	<ja>@Bean</ja>(
+		subTypeProperty=<js>"subType"</js>,
+		subTypes={
+			<ja>@BeanSubType</ja>(type=MyClassBar.<jk>class</jk>, id=<js>"BAR"</js>),
+			<ja>@BeanSubType</ja>(type=MyClassBaz.<jk>class</jk>, id=<js>"BAZ"</js>)
+		}
+	)
+	<jk>public abstract class</jk> MyClass {
+		...
+	}
+		</p>
+			
+		<h6 class='topic'>Limiting bean properties to parent bean classes</h6>
+		<p>
+			Occassionally, you may want to limit bean properties to some parent interface.
+			For example, in the <code>RequestEchoResource</code> class in the sample war file, we serialize instances of
+				<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.
+		</p>
+		<p>
+			For example, let's define the following parent class and subclass:
+		</p>
+		<p class='bcode'>
+	<jc>// Abstract parent class</jc>
+	<jk>public abstract class</jk> MyClass {
+		<jk>public</jk> String <jf>foo</jf>=<js>"foo"</js>;
+	}
+
+	<jc>// Subclass 1</jc>
+	<jk>public class</jk> MyClassBar <jk>extends</jk> MyClass {
+		<jk>public</jk> String <jf>bar</jf>=<js>"bar"</js>;
+	}
+		</p>
+		<p>
+			Suppose we only want to render the properties defined on <code>MyClass</code>, not those defined on child classes.
+			To do so, we can define the following transform:
+		</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&ltMyClass&gt; {
+		<jk>public</jk> MyClassTransform() {
+			setInterfaceClass(MyClass.<jk>class</jk>);
+		}
+	}
+		</p>
+		<p>
+			When serialized, the serialized bean will only include properties defined on the parent class.
+		</p>
+		<p class='bcode'>
+	<jc>// Serialize to JSON</jc>
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyClassTransform.<jk>class</jk>);
+	MyClass c = <jk>new</jk> MyClassBar();
+	String json = s.serialize(p);  <jc>// Prints "{foo:'foo'}"</jc>
+		</p>	
+		<p>
+			The equivalent can be done through an annotation on the parent class, which applies to all child classes:
+		</p>
+		<p class='bcode'>
+	<ja>@Bean</ja>(interfaceClass=MyClass.<jk>class</jk>)
+	<jk>public abstract class</jk> MyClass {
+		<jk>public</jk> String <jf>foo</jf>=<js>"foo"</js>;
+	}
+		</p>
+		<p>
+			The annotation can also be applied on the individual child classes, like so...
+		</p>
+		<p class='bcode'>
+	<ja>@Bean</ja>(interfaceClass=MyClass.<jk>class</jk>)
+	<jk>public class</jk> MyClassBar <jk>extends</jk> MyClass {
+		<jk>public</jk> String <jf>bar</jf>=<js>"bar"</js>;
+	}
+		</p>
+		<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 
+				passing in <code>MyClass.<jk>class</jk></code> to the serializer, like so:
+		</p>
+		<p class='bcode'>
+	<jc>// Serialize to JSON</jc>
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyClass.<jk>class</jk>);
+		</p>
+		<p>
+			In fact, this is the shortcut used in the <code>RequestEchoResource</code> sample class:
+		</p>
+		<p class='bcode'>
+	<ja>@RestResource</ja>(
+		transforms={
+			<jc>// Interpret these as their parent classes, not subclasses</jc>
+			HttpServletRequest.<jk>class</jk>, HttpSession.<jk>class</jk>, ServletContext.<jk>class</jk>
+		}
+	)
+	<jk>public class</jk> RequestEchoResource <jk>extends</jk> RestServletDefault {
+		</p>
+		
+		<h6 class='topic'>Allowing non-public bean classes/methods/fields to be used by the framework</h6>
+		<p>
+			By default, only public classes are interpreted as beans.  Non-public classes are treated as 'other' POJOs that
+			are typically just serialized to strings using the <code>toString()</code> method.
+			Likewise, by default, only public fields/methods are interpreted as bean properties.
+		</p>
+		<p>
+			The following bean context properties can be used to allow non-public classes/methods/fields to be
+			used by the framework:
+		</p>
+		<ul>
+			<li>{@link org.apache.juneau.BeanContext#BEAN_beanClassVisibility}
+			<li>{@link org.apache.juneau.BeanContext#BEAN_beanConstructorVisibility}
+			<li>{@link org.apache.juneau.BeanContext#BEAN_methodVisibility}
+			<li>{@link org.apache.juneau.BeanContext#BEAN_beanFieldVisibility}
+		</ul>
+		<p>
+			Also, specifying a {@link org.apache.juneau.annotation.BeanProperty @BeanProperty} annotation on non-public getters/setters/fields
+				will also allow them to be detected by the framework.
+		</p>
+		<p class='bcode'>
+	<jk>public class</jk> MyBean {
+		<jc>// A bean property</jc>
+		<jk>public int</jk> f1;    
+		
+		<jc>// Not a bean property</jc>
+		<ja>@BeanIgnore</ja>
+		<jk>public int</jk> f2;     
+		
+		<jc>// A bean property</jc>
+		<ja>@BeanProperty</ja>    
+		<jk>protected int</jk> f3;  
+		
+		<jc>// A bean property</jc>
+		<ja>@BeanProperty</ja>    
+		<jk>private int</jk> getF3() {...}
+	}
+		</p>
+	</div>
+
+	<!-- ======================================================================================================== -->
+	<a id="PojoTransforms"></a>
+	<h3 class='topic' onclick='toggle(this)'>1.2 - PojoTransform Class</h3>
+	<div class='topic'>
+		<p>
+			{@link org.apache.juneau.transform.PojoTransform PojoTransforms} 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.
+		</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.
+		</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; {
+		
+		<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>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>try</jk> {
+				<jk>return</jk> <jf>format</jf>.parse(o);
+			} <jk>catch</jk> (java.text.ParseException e) {
+				<jk>throw new</jk> ParseException(e);
+			}
+		}
+	}
+		</p>
+		<p>
+			The transform above can then be associated with serializers and parsers as the following example shows:
+		</p>
+		<p class='bcode'>
+	<jc>// Sample bean with a Date field.</jc>
+	<jk>public class</jk> MyBean {
+		<jk>public</jk> Date <jf>date</jf> = <jk>new</jk> Date(112, 2, 3, 4, 5, 6);
+	}
+
+	<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>);
+	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>);
+	MyBean bean = parser.parse(json, MyBean.<jk>class</jk>);
+	<jk>int</jk> day = bean.<jf>date</jf>.getDay(); 						<jc>// == 3</jc>
+		</p>
+		<p>
+			In addition, the {@link org.apache.juneau.BeanMap#get(Object)} and {@link org.apache.juneau.BeanMap#put(String,Object)} methods will automatically convert to transformed values as the following example shows:
+		</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>);
+
+	<jc>// Create a new bean.</jc>
+	MyBean myBean = <jk>new</jk> MyBean();
+
+	<jc>// Wrap it in a bean map.</jc>
+	BeanMap&lt;Bean&gt; beanMap = beanContext.forBean(myBean);
+
+	<jc>// Use the get() method to get the date field as an ISO8601 string.</jc>
+	String date = (String)beanMap.get(<js>"date"</js>);				<jc>// == "2012-03-03T04:05:06-0500"</jc> 
+	
+	<jc>// Use the put() method to set the date field to an ISO8601 string.</jc>
+	beanMap.put(<js>"date"</js>, <js>"2013-01-01T12:30:00-0500"</js>);	<jc>// Set it to a new value.</jc> 
+	
+	<jc>// Verify that the date changed on the original bean.</jc>
+	<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:
+		</p>
+		<p class='bcode'>
+	<jk>public class</jk> ByteArrayBase64Transform <jk>extends</jk> PojoTransform&lt;<jk>byte</jk>[],String&gt; {
+	
+		<ja>@Override</ja>
+		<jk>public</jk> String transform(<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>);
+				b64os.write(b);
+				b64os.close();
+				<jk>return new</jk> String(baos.toByteArray());
+			} <jk>catch</jk> (Exception e) {
+				<jk>throw new</jk> SerializeException(e);
+			}
+		}
+		
+		<ja>@Override</ja>
+		<jk>public byte</jk>[] normalize(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);
+				InputStream b64is = MimeUtility.decode(bais, <js>"base64"</js>);
+				<jk>byte</jk>[] tmp = <jk>new byte</jk>[b.length];
+				<jk>int</jk> n = b64is.read(tmp);
+				<jk>byte</jk>[] res = <jk>new byte</jk>[n];
+				System.<jsm>arraycopy</jsm>(tmp, 0, res, 0, n);
+				<jk>return</jk> res;
+			} <jk>catch</jk> (Exception e) {
+				<jk>throw new</jk> ParseException(e);
+			}
+		}
+	}
+		</p>
+		<p>
+			The following example shows the BASE64 transform in use:
+		</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>);
+	
+	<jk>byte</jk>[] a1 = {1,2,3};
+	String s1 = serializer.serialize(a1);		<jc>// Produces "'AQID'"</jc>
+	a1 = parser.parse(s1, <jk>byte</jk>[].<jk>class</jk>);		<jc>// Reproduces {1,2,3}</jc>
+	
+	<jk>byte</jk>[][] a2 = {{1,2,3},{4,5,6},<jk>null</jk>};
+	String s2 = serializer.serialize(a2);		<jc>// Produces "['AQID','BAUG',null]"</jc>
+	a2 = parser.parse(s2, <jk>byte</jk>[][].<jk>class</jk>);		<jc>// Reproduces {{1,2,3},{4,5,6},null}</jc>
+		</p>
+		<p>
+			It should be noted that the sample transforms shown above have already been implemented in the {@link org.apache.juneau.transforms} package.
+			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.
+		</ul>
+		
+		<h6 class='topic'>Valid transformed class types</h6>
+		<p>
+			The transformed class type can be any serializable class type as defined in the <a href='../package-summary.html#PojoCategories'>POJO categories</a> table.
+		</p>
+	</div>
+	
+
+	<!-- ======================================================================================================== -->
+	<a id="PojoTransforms_OneWay"></a>
+	<h3 class='topic' onclick='toggle(this)'>1.3 - One-Way PojoTransforms</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.
+		</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; {
+		
+		<ja>@Override</ja>
+		<jk>public</jk> List transform(Iterator o) {
+			List l = <jk>new</jk> LinkedList();
+			<jk>while</jk> (o.hasNext())
+				l.add(o.next());
+			<jk>return</jk> l;
+		}
+	}
+		</p>
+		<p>
+			Here is an example of our one-way transform being used.  Note that trying to parse the original object will cause a {@link org.apache.juneau.parser.ParseException} to be thrown.
+		</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>);
+	
+	<jc>// Construct an iterator we want to serialize.</jc>
+	Iterator iterator = <jk>new</jk> ObjectList(1,2,3).iterator();
+	
+	<jc>// Serialize our Iterator</jc>
+	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>);
+	iterator = parser.parse(s, Iterator.<jk>class</jk>);		<jc>// Throws ParseException!!!</jc>
+		</p>
+	</div>
+
+	<!-- ======================================================================================================== -->
+	<a id="StopClasses"></a>
+	<h3 class='topic' onclick='toggle(this)'>1.4 - Stop Classes</h3>
+	<div class='topic'>
+		<p>
+			Occassionally, you may want to limit bean properties to only those defined on a parent class or interface.  
+			There are a couple of ways of doing this.
+		</p>
+		<p>
+			For example, let's define the following parent class and subclass:
+		</p>
+		<p class='bcode'>
+	<jc>// Abstract parent class</jc>
+	<jk>public abstract class</jk> MyClass {
+		<jk>public</jk> String <jf>foo</jf>=<js>"foo"</js>;
+	}
+
+	<jc>// Subclass 1</jc>
+	<jk>public class</jk> MyClassBar <jk>extends</jk> MyClass {
+		<jk>public</jk> String <jf>bar</jf>=<js>"bar"</js>;
+	}
+		</p>
+		<p>
+			Suppose we only want to render the properties defined on <code>MyClass</code>, not those defined on child classes. 
+			To do so, we can define the following transform:
+		</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&ltMyClass&gt; {
+		<jk>public</jk> MyClassTransform() {
+			setInterfaceClass(MyClass.<jk>class</jk>);
+		}
+	}
+		</p>
+		<p>
+			When serialized, the serialized bean will only include properties defined on the parent class.
+		</p>
+		<p class='bcode'>
+	<jc>// Serialize to JSON</jc>
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyClassTransform.<jk>class</jk>);
+	MyClass c = <jk>new</jk> MyClassBar();
+	String json = s.serialize(p);  <jc>// Prints "{foo:'foo'}"</jc>
+		</p>	
+		<p>
+			The equivalent can be done through an annotation on the parent class, which applies to all child classes:
+		</p>
+		<p class='bcode'>
+	<ja>@Bean</ja>(interfaceClass=MyClass.<jk>class</jk>)
+	<jk>public abstract class</jk> MyClass {
+		<jk>public</jk> String <jf>foo</jf>=<js>"foo"</js>;
+	}
+		</p>
+		<p>
+			The annotation can also be applied on the individual child classes, like so...
+		</p>
+		<p class='bcode'>
+	<ja>@Bean</ja>(interfaceClass=MyClass.<jk>class</jk>)
+	<jk>public class</jk> MyClassBar <jk>extends</jk> MyClass {
+		<jk>public</jk> String <jf>bar</jf>=<js>"bar"</js>;
+	}
+		</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:
+		</p>
+		<p class='bcode'>
+	<jc>// Serialize to JSON</jc>
+	WriterSerializer s = <jk>new</jk> JsonSerializer().addTransforms(MyClass.<jk>class</jk>);
+		</p>
+	</div>
+
+	<!-- ======================================================================================================== -->
+	<a id="SurrogateClasses"></a>
+	<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.
+		</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
+			properties exposed):  
+		<p class='bcode'>
+	<jk>public class</jk> MyNonSerializableClass {
+		<jk>protected</jk> String <jf>foo</jf>;
+	}
+		</p>
+		<p>
+			This could be solved with the following <code>PojoTransform</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; {
+		
+		<ja>@Override</ja>
+		<jk>public</jk> MySerializableSurrogate transform(MyNonSerializableClass o) {
+			MySerializableSurrogate s = <jk>new</jk> MySerializableSurrogate();
+			s.<jf>foo</jf> = o.<jf>foo</jf>;
+			<jk>return</jk> s;
+		}
+	}
+		</p>
+		<p>
+			However, the same can be accomplished by using a surrogate class that simply contains a constructor with the non-serializable class as an argument:
+		</p>
+		<p class='bcode'>
+	<jk>public class</jk> MySerializableSurrogate {
+		<jk>public</jk> String <jf>foo</jf>;
+		
+		<jk>public</jk> MySerializableSurrogate(MyNonSerializableClass c) {
+			<jk>this</jk>.<jf>foo</jf> = c.<jf>foo</jf>;
+		}
+	}
+		</p>
+		<p>
+			The surrogate class is registered just like any other transform:
+		</p>
+		<p class='bcode'>
+	<jc>// Create a JSON serializer that can serialize Iterators.</jc>
+	Serializer serializer = <jk>new</jk> JsonSerializer().addTransforms(MySerializableSurrogate.<jk>class</jk>);
+		</p>
+		<p>
+			When the serializer encounters the non-serializable class, it will serialize an instance of the surrogate instead.
+		</p>
+	</div>
+	
+	<!-- ======================================================================================================== -->
+	<a id="ToObjectMaps"></a>
+	<h3 class='topic' onclick='toggle(this)'>1.6 - Serializing to ObjectMaps</h3>
+	<div class='topic'>
+	<div class='topic'>
+		<p>
+			A shortcut method for transforming is provided that can often be simpler than defining transforms.
+			In this case, we add methods to our class to serialize to {@link org.apache.juneau.ObjectMap ObjectMaps}
+		</p>
+		<p>
+		<p class='bcode'>
+	<jk>public class</jk> MyClass {
+		<jk>private</jk> String <jf>f1</jf>;
+		
+		<jc>// Constructor that takes in an ObjectMap</jc>
+		<jk>public</jk> MyClass(ObjectMap m) {
+			<jf>f1</jf> = m.getString(<js>"f1"</js>);
+		}
+		
+		<jc>// Method that converts object to an ObjectMap</jc>
+		<jk>public</jk> ObjectMap toObjectMap() {
+			<jk>return new</jk> ObjectMap().append(<js>"f1"</js>, <jf>f1</jf>);
+		}
+		</p>
+		<p>
+			The <code>toObjectMap()</code> method will automatically be used during serialization, and 
+			the constructor will automatically be used during parsing.
+			This will work for all serializers and parsers.
+		</p>
+	</div>
+</div>
+</body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/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
new file mode 100644
index 0000000..51ece7d
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/BeanStringTransform.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 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/e6bf97a8/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
new file mode 100644
index 0000000..f4f809d
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/ByteArrayBase64Transform.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 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/e6bf97a8/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
new file mode 100644
index 0000000..48423c0
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarLongTransform.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 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/e6bf97a8/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
new file mode 100644
index 0000000..1582a61
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarMapTransform.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 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/e6bf97a8/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
new file mode 100644
index 0000000..6847dca
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/CalendarTransform.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 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/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/transforms/DateLongTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/DateLongTransform.java b/juneau-core/src/main/java/org/apache/juneau/transforms/DateLongTransform.java
new file mode 100644
index 0000000..aadc314
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/DateLongTransform.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 DateLongTransform extends PojoTransform<Date,Long> {
+
+	/**
+	 * Converts the specified {@link Date} to a {@link Long}.
+	 */
+	@Override /* PojoTransform */
+	public Long transform(Date o) {
+		return o.getTime();
+	}
+
+	/**
+	 * Converts the specified {@link Long} to a {@link Date}.
+	 */
+	@Override /* PojoTransform */
+	public Date normalize(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("DateLongTransform is unable to narrow object of type ''{0}''", c);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/transforms/DateMapTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/DateMapTransform.java b/juneau-core/src/main/java/org/apache/juneau/transforms/DateMapTransform.java
new file mode 100644
index 0000000..3e34b5e
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/DateMapTransform.java
@@ -0,0 +1,56 @@
+/***************************************************************************************************************************
+ * 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 Map Maps} of the format <tt>{value:long}</tt>.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+@SuppressWarnings("rawtypes")
+public class DateMapTransform extends PojoTransform<Date,Map> {
+
+	/**
+	 * Converts the specified {@link Date} to a {@link Map}.
+	 */
+	@Override /* PojoTransform */
+	public Map transform(Date o) {
+		ObjectMap m = new ObjectMap();
+		m.put("time", o.getTime());
+		return m;
+	}
+
+	/**
+	 * Converts the specified {@link Map} to a {@link Date}.
+	 */
+	@Override /* PojoTransform */
+	public Date normalize(Map o, ClassMeta<?> hint) throws ParseException {
+		Class<?> c = (hint == null ? java.util.Date.class : hint.getInnerClass());
+		long l = Long.parseLong(((Map<?,?>)o).get("time").toString());
+		if (c == java.util.Date.class)
+			return new java.util.Date(l);
+		if (c == java.sql.Date.class)
+			return new java.sql.Date(l);
+		if (c == java.sql.Time.class)
+			return new java.sql.Time(l);
+		if (c == java.sql.Timestamp.class)
+			return new java.sql.Timestamp(l);
+		throw new ParseException("DateMapTransform is unable to narrow object of type ''{0}''", c);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/transforms/DateTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/DateTransform.java b/juneau-core/src/main/java/org/apache/juneau/transforms/DateTransform.java
new file mode 100644
index 0000000..f38a52b
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/DateTransform.java
@@ -0,0 +1,370 @@
+/***************************************************************************************************************************
+ * 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 Date Dates} 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 ISO8601DTP} - Transforms to ISO8601 date-time strings with millisecond precision.
+ * 	<li>{@link ISO8601DTZ} - Same as {@link ISO8601DT}, except always serializes in GMT.
+ * 	<li>{@link ISO8601DTZP} - Same as {@link ISO8601DTZ}, except with millisecond precision.
+ * 	<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 SimpleDT} - Transforms to simple <js>"yyyy/MM/dd HH:mm:ss"</js> strings.
+ * 	<li>{@link SimpleT} - 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 DateTransform extends PojoTransform<Date,String> {
+
+	/**
+	 * Transforms {@link Date Dates} to {@link String Strings} using the {@code Date.toString()} method.
+	 * <p>
+	 * <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 DateTransform {
+		/** Constructor */
+		public ToString() {
+			super("EEE MMM dd HH:mm:ss zzz yyyy");
+		}
+	}
+
+	/**
+	 * Transforms {@link Date Dates} 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 DateTransform {
+		private SimpleDateFormat tzFormat = new SimpleDateFormat("Z");
+
+		/** Constructor */
+		public ISO8601DT() {
+			this("yyyy-MM-dd'T'HH:mm:ss");
+		}
+
+		/**
+		 * Constructor with specific pattern.
+		 *
+		 * @param pattern The {@link MessageFormat}-style format string.
+		 */
+		protected ISO8601DT(String pattern) {
+			super(pattern);
+		}
+
+		@Override /* PojoTransform */
+		public Date normalize(String o, ClassMeta<?> hint) throws ParseException {
+			try {
+				if (StringUtils.isEmpty(o))
+					return null;
+				return convert(DatatypeConverter.parseDateTime(o).getTime(), hint);
+			} catch (ParseException e) {
+				throw e;
+			} catch (Exception e) {
+				throw new ParseException(e);
+			}
+		}
+
+		@Override /* PojoTransform */
+		public String transform(Date o) {
+			String s = super.transform(o);
+			String tz = tzFormat.format(o);
+			if (tz.equals("+0000"))
+				return s + "Z";
+			return s + tz.substring(0,3) + ':' + tz.substring(3);
+		}
+	}
+
+	/**
+	 * Same as {@link ISO8601DT} except serializes to millisecond precision.
+	 * <p>
+	 * Example output: <js>"2001-07-04T15:30:45.123-05:00"</js>
+	 */
+	public static class ISO8601DTP extends ISO8601DT {
+
+		/** Constructor */
+		public ISO8601DTP() {
+			super("yyyy-MM-dd'T'HH:mm:ss.SSS");
+		}
+	}
+
+	/**
+	 * Same as {@link ISO8601DT} except serializes to millisecond precision and doesn't include timezone.
+	 * <p>
+	 * Example output: <js>"2001-07-04T15:30:45.123"</js>
+	 */
+	public static class ISO8601DTPNZ extends DateTransform {
+
+		/** Constructor */
+		public ISO8601DTPNZ() {
+			super("yyyy-MM-dd'T'HH:mm:ss.SSS");
+		}
+	}
+
+	/**
+	 * Same as {@link ISO8601DT}, except always serializes in GMT.
+	 * <p>
+	 * Example output:  <js>"2001-07-04T15:30:45Z"</js>
+	 */
+	public static class ISO8601DTZ extends DateTransform {
+
+		/** Constructor */
+		public ISO8601DTZ() {
+			this("yyyy-MM-dd'T'HH:mm:ss'Z'");
+		}
+
+		/**
+		 * Constructor with specific pattern.
+		 *
+		 * @param pattern The {@link MessageFormat}-style format string.
+		 */
+		protected ISO8601DTZ(String pattern) {
+			super(pattern, "GMT");
+		}
+
+		@Override /* PojoTransform */
+		public Date normalize(String o, ClassMeta<?> hint) throws ParseException {
+			try {
+				if (StringUtils.isEmpty(o))
+					return null;
+				return convert(DatatypeConverter.parseDateTime(o).getTime(), hint);
+			} catch (ParseException e) {
+				throw e;
+			} catch (Exception e) {
+				throw new ParseException(e);
+			}
+		}
+	}
+
+	/**
+	 * Same as {@link ISO8601DTZ} except serializes to millisecond precision.
+	 * <p>
+	 * Example output:  <js>"2001-07-04T15:30:45.123Z"</js>
+	 */
+	public static class ISO8601DTZP extends ISO8601DT {
+
+		/** Constructor */
+		public ISO8601DTZP() {
+			super("yyyy-MM-dd'T'HH:mm:ss.SSS");
+		}
+	}
+
+	/**
+	 * Transforms {@link Date Dates} to RFC2822 date-time strings.
+	 */
+	public static class RFC2822DT extends DateTransform {
+		/** 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>"2001-07-04T15:30:45Z"</js>
+	 */
+	public static class RFC2822DTZ extends DateTransform {
+		/** Constructor */
+		public RFC2822DTZ() {
+			super("EEE, dd MMM yyyy HH:mm:ss z", "GMT");
+		}
+	}
+
+	/**
+	 * Transforms {@link Date Dates} to RFC2822 date strings.
+	 */
+	public static class RFC2822D extends DateTransform {
+		/** Constructor */
+		public RFC2822D() {
+			super("dd MMM yyyy");
+		}
+	}
+
+	/**
+	 * Transforms {@link Date Dates} to simple <js>"yyyy/MM/dd HH:mm:ss"</js> strings.
+	 */
+	public static class SimpleDT extends DateTransform {
+		/** Constructor */
+		public SimpleDT() {
+			super("yyyy/MM/dd HH:mm:ss");
+		}
+	}
+
+	/**
+	 * Transforms {@link Date Dates} to simple <js>"yyyy/MM/dd HH:mm:ss.SSS"</js> strings.
+	 */
+	public static class SimpleDTP extends DateTransform {
+		/** Constructor */
+		public SimpleDTP() {
+			super("yyyy/MM/dd HH:mm:ss.SSS");
+		}
+	}
+
+	/**
+	 * Transforms {@link Date Dates} to simple <js>"HH:mm:ss"</js> strings.
+	 */
+	public static class SimpleT extends DateTransform {
+		/** Constructor */
+		public SimpleT() {
+			super("HH:mm:ss");
+		}
+	}
+
+	/**
+	 * Transforms {@link Date Dates} to simple <js>"HH:mm:ss.SSS"</js> strings.
+	 */
+	public static class SimpleTP extends DateTransform {
+		/** Constructor */
+		public SimpleTP() {
+			super("HH:mm:ss.SSS");
+		}
+	}
+
+	/**
+	 * Transforms {@link Date Dates} to {@link DateFormat#MEDIUM} strings.
+	 */
+	public static class Medium extends DateTransform {
+		/** Constructor */
+		public Medium() {
+			super(DateFormat.getDateInstance(DateFormat.MEDIUM));
+		}
+	}
+
+	/** The formatter to convert dates to Strings. */
+	private DateFormat format;
+
+	/**
+	 * 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 DateTransform(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 DateTransform(String simpleDateFormat, String timeZone) {
+		this(new SimpleDateFormat(simpleDateFormat));
+		format.setTimeZone(TimeZone.getTimeZone(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 DateTransform(DateFormat format) {
+		super();
+		this.format = format;
+	}
+
+	/**
+	 * Converts the specified {@link Date} to a {@link String}.
+	 */
+	@Override /* PojoTransform */
+	public String transform(Date o) {
+		return format.format(o);
+	}
+
+	/**
+	 * Converts the specified {@link String} to a {@link Date}.
+	 */
+	@Override /* PojoTransform */
+	public Date normalize(String o, ClassMeta<?> hint) throws ParseException {
+		try {
+			if (StringUtils.isEmpty(o))
+				return null;
+			Date d = format.parse(o);
+			return convert(d, hint);
+		} catch (ParseException e) {
+			throw e;
+		} catch (Exception e) {
+			throw new ParseException(e);
+		}
+	}
+
+	private static Date convert(Date in, ClassMeta<?> hint) throws Exception {
+		if (in == null)
+			return null;
+		if (hint == null || hint.isInstance(in))
+			return in;
+		Class<?> c = hint.getInnerClass();
+		if (c == java.util.Date.class)
+			return in;
+		if (c == java.sql.Date.class)
+			return new java.sql.Date(in.getTime());
+		if (c == java.sql.Time.class)
+			return new java.sql.Time(in.getTime());
+		if (c == java.sql.Timestamp.class)
+			return new java.sql.Timestamp(in.getTime());
+		throw new ParseException("DateTransform is unable to narrow object of type ''{0}''", c);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/transforms/EnumerationTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/EnumerationTransform.java b/juneau-core/src/main/java/org/apache/juneau/transforms/EnumerationTransform.java
new file mode 100644
index 0000000..6c3b124
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/EnumerationTransform.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 java.util.*;
+
+import org.apache.juneau.transform.*;
+
+/**
+ * Transforms {@link Enumeration Enumerations} to {@code List<Object>} objects.
+ * <p>
+ * 	This is a one-way transform, since {@code Enumerations} cannot be reconstituted.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+@SuppressWarnings({"unchecked","rawtypes"})
+public class EnumerationTransform extends PojoTransform<Enumeration,List> {
+
+	/**
+	 * Converts the specified {@link Enumeration} to a {@link List}.
+	 */
+	@Override /* PojoTransform */
+	public List transform(Enumeration o) {
+		List l = new LinkedList();
+		while (o.hasMoreElements())
+			l.add(o.nextElement());
+		return l;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/transforms/IteratorTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/IteratorTransform.java b/juneau-core/src/main/java/org/apache/juneau/transforms/IteratorTransform.java
new file mode 100644
index 0000000..d5bfa77
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/IteratorTransform.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 java.util.*;
+
+import org.apache.juneau.transform.*;
+
+/**
+ * Transforms {@link Iterator Iterators} to {@code List<Object>} objects.
+ * <p>
+ * 	This is a one-way transform, since {@code Iterators} cannot be reconstituted.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+@SuppressWarnings({"unchecked","rawtypes"})
+public class IteratorTransform extends PojoTransform<Iterator,List> {
+
+	/**
+	 * Converts the specified {@link Iterator} to a {@link List}.
+	 */
+	@Override /* PojoTransform */
+	public List transform(Iterator o) {
+		List l = new LinkedList();
+		while (o.hasNext())
+			l.add(o.next());
+		return l;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/transforms/ReaderTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/ReaderTransform.java b/juneau-core/src/main/java/org/apache/juneau/transforms/ReaderTransform.java
new file mode 100644
index 0000000..77fb532
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/ReaderTransform.java
@@ -0,0 +1,112 @@
+/***************************************************************************************************************************
+ * 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.io.*;
+
+import org.apache.juneau.html.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.transform.*;
+import org.apache.juneau.xml.*;
+
+/**
+ * Transforms the contents of a {@link Reader} into an {@code Object}.
+ *
+ *
+ * <h6 class='topic'>Description</h6>
+ * <p>
+ * 	The {@code Reader} must contain JSON, Juneau-generated XML (output from {@link XmlSerializer}),
+ * 		or Juneau-generated HTML (output from {@link JsonSerializer}) in order to be parsed correctly.
+ * <p>
+ * 	Useful for serializing models that contain {@code Readers} created by {@code RestCall} instances.
+ * <p>
+ * 	This is a one-way transform, since {@code Readers} cannot be reconstituted.
+ *
+ *
+ * <h6 class='topic'>Behavior-specific subclasses</h6>
+ * <p>
+ * 	The following direct subclasses are provided for convenience:
+ * <ul class='spaced-list'>
+ * 	<li>{@link Json} - Parses JSON text.
+ * 	<li>{@link Xml} - Parses XML text.
+ * 	<li>{@link Html} - Parses HTML text.
+ * 	<li>{@link PlainText} - Parses plain text.
+ * </ul>
+ *
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public class ReaderTransform extends PojoTransform<Reader,Object> {
+
+	/** Reader transform for reading JSON text. */
+	public static class Json extends ReaderTransform {
+		/** Constructor */
+		public Json() {
+			super(JsonParser.DEFAULT);
+		}
+	}
+
+	/** Reader transform for reading XML text. */
+	public static class Xml extends ReaderTransform {
+		/** Constructor */
+		public Xml() {
+			super(XmlParser.DEFAULT);
+		}
+	}
+
+	/** Reader transform for reading HTML text. */
+	public static class Html extends ReaderTransform {
+		/** Constructor */
+		public Html() {
+			super(HtmlParser.DEFAULT);
+		}
+	}
+
+	/** Reader transform for reading plain text. */
+	public static class PlainText extends ReaderTransform {
+		/** Constructor */
+		public PlainText() {
+			super(null);
+		}
+	}
+
+	/** The parser to use to parse the contents of the Reader. */
+	private ReaderParser parser;
+
+	/**
+	 * @param parser The parser to use to convert the contents of the reader to Java objects.
+	 */
+	public ReaderTransform(ReaderParser parser) {
+		this.parser = parser;
+	}
+
+	/**
+	 * Converts the specified {@link Reader} to an {@link Object} whose type is determined
+	 * by the contents of the reader.
+	 */
+	@Override /* PojoTransform */
+	public Object transform(Reader o) throws SerializeException {
+		try {
+			if (parser == null)
+				return IOUtils.read(o);
+			return parser.parse(o, beanContext.object());
+		} catch (IOException e) {
+			return e.getLocalizedMessage();
+		} catch (Exception e) {
+			throw new SerializeException("ReaderTransform could not transform object of type ''{0}''", o == null ? null : o.getClass().getName()).initCause(e);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/transforms/XMLGregorianCalendarTransform.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/XMLGregorianCalendarTransform.java b/juneau-core/src/main/java/org/apache/juneau/transforms/XMLGregorianCalendarTransform.java
new file mode 100644
index 0000000..ac56984
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/XMLGregorianCalendarTransform.java
@@ -0,0 +1,64 @@
+/***************************************************************************************************************************
+ * 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 javax.xml.datatype.*;
+
+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 {@link XMLGregorianCalendar XMLGregorianCalendars} to ISO8601 date-time {@link String Strings}.
+ * <p>
+ * 	Objects are converted to strings using {@link XMLGregorianCalendar#toXMLFormat()}.
+ * <p>
+ * 	Strings are converted to objects using {@link DatatypeFactory#newXMLGregorianCalendar(String)}.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public class XMLGregorianCalendarTransform extends PojoTransform<XMLGregorianCalendar,String> {
+
+	private DatatypeFactory dtf;
+
+	/**
+	 * Constructor.
+	 */
+	public XMLGregorianCalendarTransform() {
+		try {
+			this.dtf = DatatypeFactory.newInstance();
+		} catch (DatatypeConfigurationException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * Converts the specified <code>XMLGregorianCalendar</code> to a {@link String}.
+	 */
+	@Override /* PojoTransform */
+	public String transform(XMLGregorianCalendar b) throws SerializeException {
+		return b.toXMLFormat();
+	}
+
+	/**
+	 * Converts the specified {@link String} to an <code>XMLGregorianCalendar</code>.
+	 */
+	@Override /* PojoTransform */
+	public XMLGregorianCalendar normalize(String s, ClassMeta<?> hint) throws ParseException {
+		if (StringUtils.isEmpty(s))
+			return null;
+		return dtf.newXMLGregorianCalendar(s);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/transforms/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transforms/package.html b/juneau-core/src/main/java/org/apache/juneau/transforms/package.html
new file mode 100644
index 0000000..65016d3
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/transforms/package.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<!--
+/***************************************************************************************************************************
+ * 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.
+ *
+ ***************************************************************************************************************************/
+ -->
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+	<style type="text/css">
+		/* For viewing in Page Designer */
+		@IMPORT url("../../../../../../javadoc.css");
+
+		/* For viewing in REST interface */
+		@IMPORT url("../htdocs/javadoc.css");
+		body { 
+			margin: 20px; 
+		}	
+	</style>
+	<script>
+		/* Replace all @code and @link tags. */	
+		window.onload = function() {
+			document.body.innerHTML = document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>');
+			document.body.innerHTML = document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, '<code>$3</code>');
+		}
+	</script>
+</head>
+<body>
+<p>Predefined Transform implementations</p>
+<script>
+	function toggle(x) {
+		var div = x.nextSibling;
+		while (div != null && div.nodeType != 1)
+			div = div.nextSibling;
+		if (div != null) {
+			var d = div.style.display;
+			if (d == 'block' || d == '') {
+				div.style.display = 'none';
+				x.className += " closed";
+			} else {
+				div.style.display = 'block';
+				x.className = x.className.replace(/(?:^|\s)closed(?!\S)/g , '' );
+			}
+		}
+	}
+</script>
+
+<!-- ======================================================================================================== -->
+<a id="PredefinedTransforms"></a><h2 class='topic'>1 - Predefined transform support</h2>
+<p>
+	This package contains various predefined instances of transforms for commonly-serialized/parsed class types.
+</p>
+<p>
+	See {@link org.apache.juneau.transform} for more information about transforms.
+</p>
+</body>