http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
index ade91df..4b6c17a 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
@@ -16,16 +16,18 @@ import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
 import static org.apache.juneau.serializer.SerializerContext.*;
 
+import java.io.*;
 import java.lang.reflect.*;
 import java.text.*;
 import java.util.*;
 
 import org.apache.juneau.*;
-import org.apache.juneau.http.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.soap.*;
 import org.apache.juneau.transform.*;
 
 /**
- * Context object that lives for the duration of a single use of {@link 
Serializer}.
+ * Serializer session that lives for the duration of a single use of {@link 
Serializer}.
  *
  * <p>
  * Used by serializers for the following purposes:
@@ -41,9 +43,10 @@ import org.apache.juneau.transform.*;
  * </ul>
  *
  * <p>
- * This class is NOT thread safe.  It is meant to be discarded after one-time 
use.
+ * This class is NOT thread safe.
+ * It is typically discarded after one-time use although it can be reused 
within the same thread.
  */
-public class SerializerSession extends BeanSession {
+public abstract class SerializerSession extends BeanSession {
 
        private final int maxDepth, initialDepth, maxIndent;
        private final boolean
@@ -61,17 +64,19 @@ public class SerializerSession extends BeanSession {
        private final char quoteChar;
        private final UriResolver uriResolver;
 
-       /** The current indentation depth into the model. */
-       public int indent;
-
        private final Map<Object,Object> set;                                   
        // Contains the current objects in the current branch of the model.
        private final LinkedList<StackElement> stack = new 
LinkedList<StackElement>();  // Contains the current objects in the current 
branch of the model.
-       private boolean isBottom;                                               
        // If 'true', then we're at a leaf in the model (i.e. a String, Number, 
Boolean, or null).
        private final Method javaMethod;                                        
        // Java method that invoked this serializer.
+
+       // Writable properties
+       private boolean isBottom;                                               
        // If 'true', then we're at a leaf in the model (i.e. a String, Number, 
Boolean, or null).
        private BeanPropertyMeta currentProperty;
        private ClassMeta<?> currentClass;
        private final SerializerListener listener;
 
+       /** The current indentation depth into the model. */
+       public int indent;
+
 
        /**
         * Create a new session using properties specified in the context.
@@ -79,29 +84,26 @@ public class SerializerSession extends BeanSession {
         * @param ctx
         *      The context creating this session object.
         *      The context contains all the configuration settings for this 
object.
-        * @param op
-        *      The override properties.
-        *      These override any context properties defined in the context.
-        * @param javaMethod The java method that called this serializer, 
usually the method in a REST servlet.
-        * @param locale
-        *      The session locale.
-        *      If <jk>null</jk>, then the locale defined on the context is 
used.
-        * @param timeZone
-        *      The session timezone.
-        *      If <jk>null</jk>, then the timezone defined on the context is 
used.
-        * @param mediaType The session media type (e.g. 
<js>"application/json"</js>).
-        * @param uriContext
-        *      The URI context.
-        *      Identifies the current request URI used for resolution of URIs 
to absolute or root-relative form.
-        */
-       public SerializerSession(SerializerContext ctx, ObjectMap op, Method 
javaMethod, Locale locale,
-                       TimeZone timeZone, MediaType mediaType, UriContext 
uriContext) {
-               super(ctx, op, locale, timeZone, mediaType);
-               this.javaMethod = javaMethod;
+        *      <br>If <jk>null</jk>, defaults to {@link 
SerializerContext#DEFAULT}.
+        * @param args
+        *      Runtime arguments.
+        *      These specify session-level information such as locale and URI 
context.
+        *      It also include session-level properties that override the 
properties defined on the bean and
+        *      serializer contexts.
+        *      <br>If <jk>null</jk>, defaults to {@link 
SerializerSessionArgs#DEFAULT}.
+        */
+       protected SerializerSession(SerializerContext ctx, 
SerializerSessionArgs args) {
+               super(ctx != null ? ctx : SerializerContext.DEFAULT, args != 
null ? args : SerializerSessionArgs.DEFAULT);
+               if (ctx == null)
+                       ctx = SerializerContext.DEFAULT;
+               if (args == null)
+                       args = SerializerSessionArgs.DEFAULT;
+               this.javaMethod = args.javaMethod;
                UriResolution uriResolution;
                UriRelativity uriRelativity;
                Class<?> listenerClass;
-               if (op == null || op.isEmpty()) {
+               ObjectMap p = getProperties();
+               if (p.isEmpty()) {
                        maxDepth = ctx.maxDepth;
                        initialDepth = ctx.initialDepth;
                        detectRecursions = ctx.detectRecursions;
@@ -121,27 +123,27 @@ public class SerializerSession extends BeanSession {
                        uriRelativity = ctx.uriRelativity;
                        listenerClass = ctx.listener;
                } else {
-                       maxDepth = op.getInt(SERIALIZER_maxDepth, ctx.maxDepth);
-                       initialDepth = op.getInt(SERIALIZER_initialDepth, 
ctx.initialDepth);
-                       detectRecursions = 
op.getBoolean(SERIALIZER_detectRecursions, ctx.detectRecursions);
-                       ignoreRecursions = 
op.getBoolean(SERIALIZER_ignoreRecursions, ctx.ignoreRecursions);
-                       useWhitespace = op.getBoolean(SERIALIZER_useWhitespace, 
ctx.useWhitespace);
-                       maxIndent = op.getInt(SERIALIZER_maxIndent, 
ctx.maxIndent);
-                       addBeanTypeProperties = 
op.getBoolean(SERIALIZER_addBeanTypeProperties, ctx.addBeanTypeProperties);
-                       trimNulls = 
op.getBoolean(SERIALIZER_trimNullProperties, ctx.trimNulls);
-                       trimEmptyCollections = 
op.getBoolean(SERIALIZER_trimEmptyCollections, ctx.trimEmptyCollections);
-                       trimEmptyMaps = op.getBoolean(SERIALIZER_trimEmptyMaps, 
ctx.trimEmptyMaps);
-                       trimStrings = op.getBoolean(SERIALIZER_trimStrings, 
ctx.trimStrings);
-                       quoteChar = op.getString(SERIALIZER_quoteChar, 
""+ctx.quoteChar).charAt(0);
-                       sortCollections = 
op.getBoolean(SERIALIZER_sortCollections, ctx.sortMaps);
-                       sortMaps = op.getBoolean(SERIALIZER_sortMaps, 
ctx.sortMaps);
-                       abridged = op.getBoolean(SERIALIZER_abridged, 
ctx.abridged);
-                       uriResolution = op.get(UriResolution.class, 
SERIALIZER_uriResolution, UriResolution.ROOT_RELATIVE);
-                       uriRelativity = op.get(UriRelativity.class, 
SERIALIZER_uriRelativity, UriRelativity.RESOURCE);
-                       listenerClass = op.get(Class.class, 
SERIALIZER_listener, ctx.listener);
+                       maxDepth = p.getInt(SERIALIZER_maxDepth, ctx.maxDepth);
+                       initialDepth = p.getInt(SERIALIZER_initialDepth, 
ctx.initialDepth);
+                       detectRecursions = 
p.getBoolean(SERIALIZER_detectRecursions, ctx.detectRecursions);
+                       ignoreRecursions = 
p.getBoolean(SERIALIZER_ignoreRecursions, ctx.ignoreRecursions);
+                       useWhitespace = p.getBoolean(SERIALIZER_useWhitespace, 
ctx.useWhitespace);
+                       maxIndent = p.getInt(SERIALIZER_maxIndent, 
ctx.maxIndent);
+                       addBeanTypeProperties = 
p.getBoolean(SERIALIZER_addBeanTypeProperties, ctx.addBeanTypeProperties);
+                       trimNulls = p.getBoolean(SERIALIZER_trimNullProperties, 
ctx.trimNulls);
+                       trimEmptyCollections = 
p.getBoolean(SERIALIZER_trimEmptyCollections, ctx.trimEmptyCollections);
+                       trimEmptyMaps = p.getBoolean(SERIALIZER_trimEmptyMaps, 
ctx.trimEmptyMaps);
+                       trimStrings = p.getBoolean(SERIALIZER_trimStrings, 
ctx.trimStrings);
+                       quoteChar = p.getString(SERIALIZER_quoteChar, 
""+ctx.quoteChar).charAt(0);
+                       sortCollections = 
p.getBoolean(SERIALIZER_sortCollections, ctx.sortMaps);
+                       sortMaps = p.getBoolean(SERIALIZER_sortMaps, 
ctx.sortMaps);
+                       abridged = p.getBoolean(SERIALIZER_abridged, 
ctx.abridged);
+                       uriResolution = p.get(UriResolution.class, 
SERIALIZER_uriResolution, UriResolution.ROOT_RELATIVE);
+                       uriRelativity = p.get(UriRelativity.class, 
SERIALIZER_uriRelativity, UriRelativity.RESOURCE);
+                       listenerClass = p.get(Class.class, SERIALIZER_listener, 
ctx.listener);
                }
 
-               uriResolver = new UriResolver(uriResolution, uriRelativity, 
uriContext == null ? ctx.uriContext : uriContext);
+               uriResolver = new UriResolver(uriResolution, uriRelativity, 
args.uriContext == null ? ctx.uriContext : args.uriContext);
 
                listener = newInstance(SerializerListener.class, listenerClass);
 
@@ -154,11 +156,102 @@ public class SerializerSession extends BeanSession {
        }
 
        /**
+        * Wraps the specified input object into a {@link ParserPipe} object so 
that it can be easily converted into
+        * a stream or reader.
+        *
+        * @param output
+        *      The output location.
+        *      <br>For character-based serializers, this can be any of the 
following types:
+        *      <ul>
+        *              <li>{@link Writer}
+        *              <li>{@link OutputStream} - Output will be written as 
UTF-8 encoded stream.
+        *              <li>{@link File} - Output will be written as 
system-default encoded stream.
+        *              <li>{@link StringBuilder}
+        *      </ul>
+        *      <br>For byte-based serializers, this can be any of the 
following types:
+        *      <ul>
+        *              <li>{@link OutputStream}
+        *              <li>{@link File}
+        *      </ul>
+        * @return
+        *      A new {@link ParserPipe} wrapper around the specified input 
object.
+        */
+       protected SerializerPipe createPipe(Object output) {
+               return new SerializerPipe(output);
+       }
+
+
+       
//--------------------------------------------------------------------------------
+       // Abstract methods
+       
//--------------------------------------------------------------------------------
+
+       /**
+        * Serializes a POJO to the specified output stream or writer.
+        *
+        * <p>
+        * This method should NOT close the context object.
+        *
+        * @param pipe Where to send the output from the serializer.
+        * @param o The object to serialize.
+        * @throws Exception If thrown from underlying stream, or if the input 
contains a syntax error or is malformed.
+        */
+       protected abstract void doSerialize(SerializerPipe pipe, Object o) 
throws Exception;
+
+       /**
+        * Shortcut method for serializing objects directly to either a 
<code>String</code> or <code><jk>byte</jk>[]</code>
+        * depending on the serializer type.
+        *
+        * @param o The object to serialize.
+        * @return
+        *      The serialized object.
+        *      <br>Character-based serializers will return a 
<code>String</code>
+        *      <br>Stream-based serializers will return a 
<code><jk>byte</jk>[]</code>
+        * @throws SerializeException If a problem occurred trying to convert 
the output.
+        */
+       public abstract Object serialize(Object o) throws SerializeException;
+
+       /**
+        * Returns <jk>true</jk> if this serializer subclasses from {@link 
WriterSerializer}.
+        *
+        * @return <jk>true</jk> if this serializer subclasses from {@link 
WriterSerializer}.
+        */
+       public abstract boolean isWriterSerializer();
+
+
+       
//--------------------------------------------------------------------------------
+       // Other methods
+       
//--------------------------------------------------------------------------------
+
+       /**
+        * Serialize the specified object using the specified session.
+        *
+        * @param out Where to send the output from the serializer.
+        * @param o The object to serialize.
+        * @throws SerializeException If a problem occurred trying to convert 
the output.
+        */
+       public final void serialize(Object out, Object o) throws 
SerializeException {
+               SerializerPipe pipe = createPipe(out);
+               try {
+                       doSerialize(pipe, o);
+               } catch (SerializeException e) {
+                       throw e;
+               } catch (StackOverflowError e) {
+                       throw new SerializeException(this,
+                               "Stack overflow occurred.  This can occur when 
trying to serialize models containing loops.  It's recommended you use the 
SerializerContext.SERIALIZER_detectRecursions setting to help locate the 
loop.").initCause(e);
+               } catch (Exception e) {
+                       throw new SerializeException(this, e);
+               } finally {
+                       pipe.close();
+                       close();
+               }
+       }
+
+       /**
         * Sets the current bean property being serialized for proper error 
messages.
         *
         * @param currentProperty The current property being serialized.
         */
-       public void setCurrentProperty(BeanPropertyMeta currentProperty) {
+       protected final void setCurrentProperty(BeanPropertyMeta 
currentProperty) {
                this.currentProperty = currentProperty;
        }
 
@@ -167,7 +260,7 @@ public class SerializerSession extends BeanSession {
         *
         * @param currentClass The current class being serialized.
         */
-       public void setCurrentClass(ClassMeta<?> currentClass) {
+       protected final void setCurrentClass(ClassMeta<?> currentClass) {
                this.currentClass = currentClass;
        }
 
@@ -180,7 +273,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The Java method that invoked this serializer.
        */
-       public final Method getJavaMethod() {
+       protected final Method getJavaMethod() {
                return javaMethod;
        }
 
@@ -189,7 +282,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The URI resolver.
         */
-       public final UriResolver getUriResolver() {
+       protected final UriResolver getUriResolver() {
                return uriResolver;
        }
 
@@ -198,7 +291,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link SerializerContext#SERIALIZER_maxDepth} setting 
value for this session.
         */
-       public final int getMaxDepth() {
+       protected final int getMaxDepth() {
                return maxDepth;
        }
 
@@ -207,7 +300,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link SerializerContext#SERIALIZER_initialDepth} 
setting value for this session.
         */
-       public final int getInitialDepth() {
+       protected final int getInitialDepth() {
                return initialDepth;
        }
 
@@ -216,7 +309,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link SerializerContext#SERIALIZER_detectRecursions} 
setting value for this session.
         */
-       public final boolean isDetectRecursions() {
+       protected final boolean isDetectRecursions() {
                return detectRecursions;
        }
 
@@ -225,7 +318,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link SerializerContext#SERIALIZER_ignoreRecursions} 
setting value for this session.
         */
-       public final boolean isIgnoreRecursions() {
+       protected final boolean isIgnoreRecursions() {
                return ignoreRecursions;
        }
 
@@ -234,7 +327,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link SerializerContext#SERIALIZER_useWhitespace} 
setting value for this session.
         */
-       public final boolean isUseWhitespace() {
+       protected final boolean isUseWhitespace() {
                return useWhitespace;
        }
 
@@ -243,7 +336,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link SerializerContext#SERIALIZER_maxIndent} setting 
value for this session.
         */
-       public final int getMaxIndent() {
+       protected final int getMaxIndent() {
                return maxIndent;
        }
 
@@ -252,7 +345,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link 
SerializerContext#SERIALIZER_addBeanTypeProperties} setting value for this 
session.
         */
-       public boolean isAddBeanTypeProperties() {
+       protected boolean isAddBeanTypeProperties() {
                return addBeanTypeProperties;
        }
 
@@ -261,7 +354,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link SerializerContext#SERIALIZER_quoteChar} setting 
value for this session.
         */
-       public final char getQuoteChar() {
+       protected final char getQuoteChar() {
                return quoteChar;
        }
 
@@ -270,7 +363,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link SerializerContext#SERIALIZER_trimNullProperties} 
setting value for this session.
         */
-       public final boolean isTrimNulls() {
+       protected final boolean isTrimNulls() {
                return trimNulls;
        }
 
@@ -279,7 +372,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link 
SerializerContext#SERIALIZER_trimEmptyCollections} setting value for this 
session.
         */
-       public final boolean isTrimEmptyCollections() {
+       protected final boolean isTrimEmptyCollections() {
                return trimEmptyCollections;
        }
 
@@ -288,7 +381,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link SerializerContext#SERIALIZER_trimEmptyMaps} 
setting value for this session.
         */
-       public final boolean isTrimEmptyMaps() {
+       protected final boolean isTrimEmptyMaps() {
                return trimEmptyMaps;
        }
 
@@ -297,7 +390,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link SerializerContext#SERIALIZER_trimStrings} setting 
value for this session.
         */
-       public final boolean isTrimStrings() {
+       protected final boolean isTrimStrings() {
                return trimStrings;
        }
 
@@ -306,7 +399,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link SerializerContext#SERIALIZER_sortCollections} 
setting value for this session.
         */
-       public final boolean isSortCollections() {
+       protected final boolean isSortCollections() {
                return sortCollections;
        }
 
@@ -315,7 +408,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return The {@link SerializerContext#SERIALIZER_sortMaps} setting 
value for this session.
         */
-       public final boolean isSortMaps() {
+       protected final boolean isSortMaps() {
                return sortMaps;
        }
 
@@ -330,7 +423,7 @@ public class SerializerSession extends BeanSession {
         *      once (since they can be expensive).
         * @throws SerializeException If recursion occurred.
         */
-       public ClassMeta<?> push(String attrName, Object o, ClassMeta<?> eType) 
throws SerializeException {
+       protected final ClassMeta<?> push(String attrName, Object o, 
ClassMeta<?> eType) throws SerializeException {
                indent++;
                isBottom = true;
                if (o == null)
@@ -363,7 +456,7 @@ public class SerializerSession extends BeanSession {
         * @return <jk>true</jk> if recursion detected.
         * @throws SerializeException If recursion occurred.
         */
-       public boolean willRecurse(String attrName, Object o, ClassMeta<?> cm) 
throws SerializeException {
+       protected final boolean willRecurse(String attrName, Object o, 
ClassMeta<?> cm) throws SerializeException {
                if (! (detectRecursions || isDebug()))
                        return false;
                if (! set.containsKey(o))
@@ -378,7 +471,7 @@ public class SerializerSession extends BeanSession {
        /**
         * Pop an object off the stack.
         */
-       public void pop() {
+       protected final void pop() {
                indent--;
                if ((detectRecursions || isDebug()) && ! isBottom)  {
                        Object o = stack.removeLast().o;
@@ -391,21 +484,12 @@ public class SerializerSession extends BeanSession {
        }
 
        /**
-        * The current indentation depth.
-        *
-        * @return The current indentation depth.
-        */
-       public int getIndent() {
-               return indent;
-       }
-
-       /**
         * Specialized warning when an exception is thrown while executing a 
bean getter.
         *
         * @param p The bean map entry representing the bean property.
         * @param t The throwable that the bean getter threw.
         */
-       public void onBeanGetterException(BeanPropertyMeta p, Throwable t) {
+       protected final void onBeanGetterException(BeanPropertyMeta p, 
Throwable t) {
                if (listener != null)
                        listener.onBeanGetterException(this, t, p);
                String prefix = (isDebug() ? getStack(false) + ": " : "");
@@ -420,7 +504,7 @@ public class SerializerSession extends BeanSession {
         * @param msg The warning message.
         * @param args Optional {@link MessageFormat}-style arguments.
         */
-       public final void onError(Throwable t, String msg, Object... args) {
+       protected final void onError(Throwable t, String msg, Object... args) {
                if (listener != null)
                        listener.onError(this, t, format(msg, args));
                super.addWarning(msg, args);
@@ -432,7 +516,7 @@ public class SerializerSession extends BeanSession {
         * @param o The input string to trim.
         * @return The trimmed string, or <jk>null</jk> if the input was 
<jk>null</jk>.
         */
-       public final String trim(Object o) {
+       protected final String trim(Object o) {
                if (o == null)
                        return null;
                String s = o.toString();
@@ -450,7 +534,7 @@ public class SerializerSession extends BeanSession {
         * @throws SerializeException If a problem occurred trying to convert 
the output.
         */
        @SuppressWarnings({ "rawtypes", "unchecked" })
-       public final Object generalize(Object o, ClassMeta<?> type) throws 
SerializeException {
+       protected final Object generalize(Object o, ClassMeta<?> type) throws 
SerializeException {
                if (o == null)
                        return null;
                PojoSwap f = (type == null || type.isObject() ? 
getClassMeta(o.getClass()).getPojoSwap() : type.getPojoSwap());
@@ -468,7 +552,7 @@ public class SerializerSession extends BeanSession {
         * @return <jk>true</jk> if the specified value should not be 
serialized.
         * @throws SerializeException If recursion occurred.
         */
-       public final boolean canIgnoreValue(ClassMeta<?> cm, String attrName, 
Object value) throws SerializeException {
+       protected final boolean canIgnoreValue(ClassMeta<?> cm, String 
attrName, Object value) throws SerializeException {
 
                if (trimNulls && value == null)
                        return true;
@@ -509,7 +593,7 @@ public class SerializerSession extends BeanSession {
         * @param m The map being sorted.
         * @return A new sorted {@link TreeMap}.
         */
-       public final <K,V> Map<K,V> sort(Map<K,V> m) {
+       protected final <K,V> Map<K,V> sort(Map<K,V> m) {
                if (sortMaps && m != null && (! m.isEmpty()) && 
m.keySet().iterator().next() instanceof Comparable<?>)
                        return new TreeMap<K,V>(m);
                return m;
@@ -521,13 +605,40 @@ public class SerializerSession extends BeanSession {
         * @param c The collection being sorted.
         * @return A new sorted {@link TreeSet}.
         */
-       public final <E> Collection<E> sort(Collection<E> c) {
+       protected final <E> Collection<E> sort(Collection<E> c) {
                if (sortCollections && c != null && (! c.isEmpty()) && 
c.iterator().next() instanceof Comparable<?>)
                        return new TreeSet<E>(c);
                return c;
        }
 
        /**
+        * Converts the contents of the specified object array to a list.
+        *
+        * <p>
+        * Works on both object and primitive arrays.
+        *
+        * <p>
+        * In the case of multi-dimensional arrays, the outgoing list will 
contain elements of type n-1 dimension.
+        * i.e. if {@code type} is <code><jk>int</jk>[][]</code> then {@code 
list} will have entries of type
+        * <code><jk>int</jk>[]</code>.
+        *
+        * @param type The type of array.
+        * @param array The array being converted.
+        * @return The array as a list.
+        */
+       protected static final List<Object> toList(Class<?> type, Object array) 
{
+               Class<?> componentType = type.getComponentType();
+               if (componentType.isPrimitive()) {
+                       int l = Array.getLength(array);
+                       List<Object> list = new ArrayList<Object>(l);
+                       for (int i = 0; i < l; i++)
+                               list.add(Array.get(array, i));
+                       return list;
+               }
+               return Arrays.asList((Object[])array);
+       }
+
+       /**
         * Converts a String to an absolute URI based on the {@link UriContext} 
on this session.
         *
         * @param uri
@@ -554,7 +665,7 @@ public class SerializerSession extends BeanSession {
         *      </ul>
         * @return The resolved URI.
         */
-       public String resolveUri(Object uri) {
+       public final String resolveUri(Object uri) {
                return uriResolver.resolve(uri);
        }
 
@@ -592,7 +703,7 @@ public class SerializerSession extends BeanSession {
         * @param uri The URI to relativize.
         * @return The relativized URI.
         */
-       public String relativizeUri(Object relativeTo, Object uri) {
+       protected final String relativizeUri(Object relativeTo, Object uri) {
                return uriResolver.relativize(relativeTo, uri);
        }
 
@@ -602,7 +713,7 @@ public class SerializerSession extends BeanSession {
         * @param o The object to convert to a <code>String</code>.
         * @return The
         */
-       public String toString(Object o) {
+       public final String toString(Object o) {
                if (o == null)
                        return null;
                if (o.getClass() == Class.class)
@@ -613,11 +724,6 @@ public class SerializerSession extends BeanSession {
                return s;
        }
 
-       @Override
-       public boolean close() {
-               return super.close();
-       }
-
        private static class StackElement {
                private int depth;
                private String name;
@@ -663,7 +769,7 @@ public class SerializerSession extends BeanSession {
         *
         * @return A map, typically containing something like 
<code>{line:123,column:456,currentProperty:"foobar"}</code>
         */
-       public Map<String,Object> getLastLocation() {
+       protected final Map<String,Object> getLastLocation() {
                Map<String,Object> m = new LinkedHashMap<String,Object>();
                if (currentClass != null)
                        m.put("currentClass", currentClass);
@@ -681,7 +787,7 @@ public class SerializerSession extends BeanSession {
         * @param typeName The type name of the bean.
         * @return A new bean property value.
         */
-       public BeanPropertyValue createBeanTypeNameProperty(BeanMap<?> m, 
String typeName) {
+       protected final static BeanPropertyValue 
createBeanTypeNameProperty(BeanMap<?> m, String typeName) {
                BeanMeta<?> bm = m.getMeta();
                return new BeanPropertyValue(bm.getTypeProperty(), 
bm.getTypeProperty().getName(), typeName, null);
        }
@@ -694,7 +800,7 @@ public class SerializerSession extends BeanSession {
         * @param pMeta The current bean property being serialized.
         * @return The bean dictionary name, or <jk>null</jk> if a name could 
not be found.
         */
-       public String getBeanTypeName(ClassMeta<?> eType, ClassMeta<?> aType, 
BeanPropertyMeta pMeta) {
+       protected final String getBeanTypeName(ClassMeta<?> eType, ClassMeta<?> 
aType, BeanPropertyMeta pMeta) {
                if (eType == aType)
                        return null;
 
@@ -748,7 +854,25 @@ public class SerializerSession extends BeanSession {
         * @param o The object to get the expected type on.
         * @return The expected type.
         */
-       public ClassMeta<?> getExpectedRootType(Object o) {
+       protected final ClassMeta<?> getExpectedRootType(Object o) {
                return abridged ? getClassMetaForObject(o) : object();
        }
+
+       /**
+        * Optional method that specifies HTTP request headers for this 
serializer.
+        *
+        * <p>
+        * For example, {@link SoapXmlSerializer} needs to set a 
<code>SOAPAction</code> header.
+        *
+        * <p>
+        * This method is typically meaningless if the serializer is being used 
stand-alone (i.e. outside of a REST server
+        * or client).
+        *
+        * @return
+        *      The HTTP headers to set on HTTP requests.
+        *      Never <jk>null</jk>.
+        */
+       public Map<String,String> getResponseHeaders() {
+               return Collections.emptyMap();
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSessionArgs.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSessionArgs.java
 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSessionArgs.java
new file mode 100644
index 0000000..68077b4
--- /dev/null
+++ 
b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSessionArgs.java
@@ -0,0 +1,65 @@
+// 
***************************************************************************************************************************
+// * 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.serializer;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.*;
+
+/**
+ * Runtime arguments common to all serializer sessions.
+ *
+ * <p>
+ * This object specifies information such as session locale or URI context.
+ */
+public final class SerializerSessionArgs extends BeanSessionArgs {
+
+       /**
+        * Default session arguments.
+        */
+       public static final SerializerSessionArgs DEFAULT = new 
SerializerSessionArgs(ObjectMap.EMPTY_MAP, null, null, null, null, null);
+
+       final Method javaMethod;
+       final UriContext uriContext;
+
+       /**
+        * Constructor.
+        *
+        * @param properties
+        *      Session-level properties.
+        *      These override context-level properties.
+        *      Can be <jk>null</jk>.
+        * @param javaMethod
+        *      The java method that called this serializer, usually the method 
in a REST servlet.
+        *      Can be <jk>null</jk>.
+        * @param locale
+        *      The session locale.
+        *      If <jk>null</jk>, then the locale defined on the context is 
used.
+        * @param timeZone
+        *      The session timezone.
+        *      If <jk>null</jk>, then the timezone defined on the context is 
used.
+        * @param mediaType
+        *      The session media type (e.g. <js>"application/json"</js>).
+        *      Can be <jk>null</jk>.
+        * @param uriContext
+        *      The URI context.
+        *      Identifies the current request URI used for resolution of URIs 
to absolute or root-relative form.
+        */
+       public SerializerSessionArgs(ObjectMap properties, Method javaMethod, 
Locale locale, TimeZone timeZone, MediaType mediaType, UriContext uriContext) {
+               super(properties, locale, timeZone, mediaType);
+               this.javaMethod = javaMethod;
+               this.uriContext = uriContext;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java 
b/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
index fc782d7..11d2138 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
@@ -12,29 +12,13 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.serializer;
 
-import java.io.*;
-import java.lang.reflect.*;
-import java.util.*;
-
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
-import org.apache.juneau.http.*;
 import org.apache.juneau.utils.*;
 
 /**
  * Subclass of {@link Serializer} for character-based serializers.
  *
- * <h5 class='section'>Description:</h5>
- *
- * This class is typically the parent class of all character-based serializers.
- * It has 2 abstract methods to implement...
- * <ul class='spaced-list'>
- *     <li>
- *             {@link #createSession(ObjectMap, Method, Locale, TimeZone, 
MediaType, UriContext)}
- *     <li>
- *             {@link #doSerialize(SerializerSession, SerializerOutput, 
Object)}
- * </ul>
- *
  * <h6 class='topic'>@Produces annotation</h6>
  *
  * The media types that this serializer can produce is specified through the 
{@link Produces @Produces} annotation.
@@ -54,16 +38,24 @@ public abstract class WriterSerializer extends Serializer {
                super(propertyStore);
        }
 
-       @Override /* Serializer */
-       public boolean isWriterSerializer() {
-               return true;
-       }
+
+       
//--------------------------------------------------------------------------------
+       // Abstract methods
+       
//--------------------------------------------------------------------------------
+
+       @Override /* SerializerSession */
+       public abstract WriterSerializerSession 
createSession(SerializerSessionArgs args);
 
 
        
//--------------------------------------------------------------------------------
        // Other methods
        
//--------------------------------------------------------------------------------
 
+       @Override /* Serializer */
+       public final boolean isWriterSerializer() {
+               return true;
+       }
+
        /**
         * Convenience method for serializing an object to a 
<code>String</code>.
         *
@@ -71,12 +63,9 @@ public abstract class WriterSerializer extends Serializer {
         * @return The output serialized to a string.
         * @throws SerializeException If a problem occurred trying to convert 
the output.
         */
-       @Override
+       @Override /* Serializer */
        public final String serialize(Object o) throws SerializeException {
-               StringWriter w = new StringWriter();
-               SerializerOutput out = new SerializerOutput(w);
-               serialize(createSession(), out, o);
-               return w.toString();
+               return createSession(null).serialize(o);
        }
 
        /**
@@ -90,10 +79,7 @@ public abstract class WriterSerializer extends Serializer {
         */
        public final String toString(Object o) {
                try {
-                       StringWriter w = new StringWriter();
-                       SerializerOutput out = new SerializerOutput(w);
-                       serialize(createSession(), out, o);
-                       return w.toString();
+                       return serialize(o);
                } catch (Exception e) {
                        throw new RuntimeException(e);
                }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
 
b/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
new file mode 100644
index 0000000..b91085f
--- /dev/null
+++ 
b/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
@@ -0,0 +1,80 @@
+// 
***************************************************************************************************************************
+// * 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.serializer;
+
+import java.io.*;
+
+/**
+ * Subclass of {@link SerializerSession} for character-based serializers.
+ *
+ * <h5 class='section'>Description:</h5>
+ *
+ * This class is typically the parent class of all character-based serializers.
+ * <br>It has 1 abstract method to implement...
+ * <ul class='spaced-list'>
+ *     <li>
+ *             {@link #doSerialize(SerializerPipe, Object)}
+ * </ul>
+ *
+ * <p>
+ * This class is NOT thread safe.
+ * It is typically discarded after one-time use although it can be reused 
within the same thread.
+ */
+public abstract class WriterSerializerSession extends SerializerSession {
+
+       /**
+        * Create a new session using properties specified in the context.
+        *
+        * @param ctx
+        *      The context creating this session object.
+        *      The context contains all the configuration settings for this 
object.
+        * @param args
+        *      Runtime arguments.
+        *      These specify session-level information such as locale and URI 
context.
+        *      It also include session-level properties that override the 
properties defined on the bean and
+        *      serializer contexts.
+        *      <br>If <jk>null</jk>, defaults to {@link 
SerializerSessionArgs#DEFAULT}.
+        */
+       protected WriterSerializerSession(SerializerContext ctx, 
SerializerSessionArgs args) {
+               super(ctx, args);
+       }
+
+       /**
+        * Constructor for sessions that don't require context.
+        *
+        * @param args
+        *      Runtime session arguments.
+        */
+       protected WriterSerializerSession(SerializerSessionArgs args) {
+               this(null, args);
+       }
+
+       @Override /* SerializerSession */
+       public final boolean isWriterSerializer() {
+               return true;
+       }
+
+       /**
+        * Convenience method for serializing an object to a 
<code>String</code>.
+        *
+        * @param o The object to serialize.
+        * @return The output serialized to a string.
+        * @throws SerializeException If a problem occurred trying to convert 
the output.
+        */
+       @Override /* SerializerSession */
+       public final String serialize(Object o) throws SerializeException {
+               StringWriter w = new StringWriter();
+               serialize(w, o);
+               return w.toString();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java 
b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java
index c9053a4..77f722b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java
@@ -12,8 +12,6 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.soap;
 
-import static org.apache.juneau.soap.SoapXmlSerializerContext.*;
-
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.serializer.*;
@@ -44,6 +42,8 @@ import org.apache.juneau.xml.*;
 @Produces(value="text/xml+soap",contentType="text/xml")
 public final class SoapXmlSerializer extends XmlSerializer {
 
+       private final SoapXmlSerializerContext ctx;
+
        /**
         * Constructor.
         *
@@ -51,35 +51,11 @@ public final class SoapXmlSerializer extends XmlSerializer {
         */
        public SoapXmlSerializer(PropertyStore propertyStore) {
                super(propertyStore);
-       }
-
-
-       
//--------------------------------------------------------------------------------
-       // Overridden methods
-       
//--------------------------------------------------------------------------------
-
-       @Override /* Serializer */
-       protected void doSerialize(SerializerSession session, SerializerOutput 
out, Object o) throws Exception {
-               XmlSerializerSession s = (XmlSerializerSession)session;
-               XmlWriter w = s.getXmlWriter(out);
-               w.append("<?xml")
-                       .attr("version", "1.0")
-                       .attr("encoding", "UTF-8")
-                       .appendln("?>");
-               w.oTag("soap", "Envelope")
-                       .attr("xmlns", "soap", 
s.getProperty(SOAPXML_SOAPAction, "http://www.w3.org/2003/05/soap-envelope";))
-                       .appendln(">");
-               w.sTag(1, "soap", "Body").nl(1);
-               s.indent += 2;
-               w.flush();
-               super.doSerialize(s, out, o);
-               w.ie(1).eTag("soap", "Body").nl(1);
-               w.eTag("soap", "Envelope").nl(0);
+               this.ctx = createContext(SoapXmlSerializerContext.class);
        }
 
        @Override /* Serializer */
-       public ObjectMap getResponseHeaders(ObjectMap properties) {
-               return new ObjectMap(super.getResponseHeaders(properties))
-                       .append("SOAPAction", 
properties.getString(SOAPXML_SOAPAction, 
"http://www.w3.org/2003/05/soap-envelope";));
+       public WriterSerializerSession createSession(SerializerSessionArgs 
args) {
+               return new SoapXmlSerializerSession(ctx, args);
        }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerContext.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerContext.java
 
b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerContext.java
index e6eb5d6..77f64cc 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerContext.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerContext.java
@@ -12,6 +12,8 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.soap;
 
+import org.apache.juneau.*;
+import org.apache.juneau.xml.*;
 
 /**
  * Properties associated with the {@link SoapXmlSerializer} class.
@@ -40,7 +42,19 @@ package org.apache.juneau.soap;
  *     </li>
  * </ul>
  */
-public final class SoapXmlSerializerContext {
+public final class SoapXmlSerializerContext extends XmlSerializerContext {
+
+       /**
+        * Constructor
+        *
+        * <p>
+        * Typically only called from {@link PropertyStore#getContext(Class)}.
+        *
+        * @param ps The property store that created this context.
+        */
+       public SoapXmlSerializerContext(PropertyStore ps) {
+               super(ps);
+       }
 
        /**
         * <b>Configuration property:</b>  The <code>SOAPAction</code> HTTP 
header value to set on responses.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerSession.java
 
b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerSession.java
new file mode 100644
index 0000000..3960607
--- /dev/null
+++ 
b/juneau-core/src/main/java/org/apache/juneau/soap/SoapXmlSerializerSession.java
@@ -0,0 +1,75 @@
+// 
***************************************************************************************************************************
+// * 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.soap;
+
+import static org.apache.juneau.soap.SoapXmlSerializerContext.*;
+
+import java.util.*;
+
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.utils.*;
+import org.apache.juneau.xml.*;
+
+/**
+ * Session object that lives for the duration of a single use of {@link 
SoapXmlSerializer}.
+ *
+ * <p>
+ * This class is NOT thread safe.
+ * It is typically discarded after one-time use although it can be reused 
within the same thread.
+ */
+public class SoapXmlSerializerSession extends XmlSerializerSession {
+
+       /**
+        * Create a new session using properties specified in the context.
+        *
+        * @param ctx
+        *      The context creating this session object.
+        *      The context contains all the configuration settings for this 
object.
+        * @param args
+        *      Runtime arguments.
+        *      These specify session-level information such as locale and URI 
context.
+        *      It also include session-level properties that override the 
properties defined on the bean and
+        *      serializer contexts.
+        *      <br>If <jk>null</jk>, defaults to {@link 
SerializerSessionArgs#DEFAULT}.
+        */
+       public SoapXmlSerializerSession(SoapXmlSerializerContext ctx, 
SerializerSessionArgs args) {
+               super(ctx, args);
+       }
+
+       
//--------------------------------------------------------------------------------
+       // Overridden methods
+       
//--------------------------------------------------------------------------------
+
+       @Override /* SerializerSession */
+       protected void doSerialize(SerializerPipe out, Object o) throws 
Exception {
+               XmlWriter w = getXmlWriter(out);
+               w.append("<?xml")
+                       .attr("version", "1.0")
+                       .attr("encoding", "UTF-8")
+                       .appendln("?>");
+               w.oTag("soap", "Envelope")
+                       .attr("xmlns", "soap", getProperty(SOAPXML_SOAPAction, 
"http://www.w3.org/2003/05/soap-envelope";))
+                       .appendln(">");
+               w.sTag(1, "soap", "Body").nl(1);
+               indent += 2;
+               w.flush();
+               super.doSerialize(out, o);
+               w.ie(1).eTag("soap", "Body").nl(1);
+               w.eTag("soap", "Envelope").nl(0);
+       }
+
+       @Override /* Serializer */
+       public Map<String,String> getResponseHeaders() {
+               return new AMap<String,String>().append("SOAPAction", 
getProperty(SOAPXML_SOAPAction, "http://www.w3.org/2003/05/soap-envelope";));
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java 
b/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
index cc8a19c..7410a7d 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
@@ -13,17 +13,10 @@
 package org.apache.juneau.uon;
 
 import static org.apache.juneau.uon.UonParserContext.*;
-import static org.apache.juneau.internal.StringUtils.*;
-
-import java.lang.reflect.*;
-import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
-import org.apache.juneau.http.*;
-import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
-import org.apache.juneau.transform.*;
 
 /**
  * Parses UON (a notation for URL-encoded query parameter values) text into 
POJO models.
@@ -45,7 +38,6 @@ import org.apache.juneau.transform.*;
  *     <li>{@link BeanContext}
  * </ul>
  */
-@SuppressWarnings({ "rawtypes", "unchecked" })
 @Consumes("text/uon")
 public class UonParser extends ReaderParser {
 
@@ -55,11 +47,6 @@ public class UonParser extends ReaderParser {
        /** Reusable instance of {@link UonParser} with decodeChars set to 
true. */
        public static final UonParser DEFAULT_DECODING = new 
UonParser.Decoding(PropertyStore.create());
 
-       // Characters that need to be preceeded with an escape character.
-       private static final AsciiSet escapedChars = new 
AsciiSet("~'\u0001\u0002");
-
-       private static final char AMP='\u0001', EQ='\u0002';  // Flags set in 
reader to denote & and = characters.
-
 
        /** Default parser, decoding. */
        public static class Decoding extends UonParser {
@@ -70,12 +57,7 @@ public class UonParser extends ReaderParser {
                 * @param propertyStore The property store containing all the 
settings for this object.
                 */
                public Decoding(PropertyStore propertyStore) {
-                       super(propertyStore);
-               }
-
-               @Override /* CoreObject */
-               protected ObjectMap getOverrideProperties() {
-                       return 
super.getOverrideProperties().append(UON_decodeChars, true);
+                       super(propertyStore.copy().append(UON_decodeChars, 
true));
                }
        }
 
@@ -98,696 +80,16 @@ public class UonParser extends ReaderParser {
        }
 
        /**
-        * Workhorse method.
-        *
-        * @param session The parser context for this parse.
-        * @param eType The class type being parsed, or <jk>null</jk> if 
unknown.
-        * @param r The reader being parsed.
-        * @param outer The outer object (for constructing nested inner 
classes).
-        * @param isUrlParamValue
-        *      If <jk>true</jk>, then we're parsing a top-level URL-encoded 
value which is treated a bit different than the
-        *      default case.
-        * @param pMeta The current bean property being parsed.
-        * @return The parsed object.
-        * @throws Exception
-        */
-       protected <T> T parseAnything(UonParserSession session, ClassMeta<T> 
eType, ParserReader r, Object outer,
-                       boolean isUrlParamValue, BeanPropertyMeta pMeta) throws 
Exception {
-
-               if (eType == null)
-                       eType = (ClassMeta<T>)object();
-               PojoSwap<T,Object> transform = 
(PojoSwap<T,Object>)eType.getPojoSwap();
-               ClassMeta<?> sType = eType.getSerializedClassMeta();
-
-               Object o = null;
-
-               int c = r.peekSkipWs();
-
-               if (c == -1 || c == AMP) {
-                       // If parameter is blank and it's an array or 
collection, return an empty list.
-                       if (sType.isCollectionOrArray())
-                               o = sType.newInstance();
-                       else if (sType.isString() || sType.isObject())
-                               o = "";
-                       else if (sType.isPrimitive())
-                               o = sType.getPrimitiveDefault();
-                       // Otherwise, leave null.
-               } else if (sType.isVoid()) {
-                       String s = parseString(session, r, isUrlParamValue);
-                       if (s != null)
-                               throw new ParseException(session, "Expected 
''null'' for void value, but was ''{0}''.", s);
-               } else if (sType.isObject()) {
-                       if (c == '(') {
-                               ObjectMap m = new ObjectMap(session);
-                               parseIntoMap(session, r, m, string(), object(), 
pMeta);
-                               o = session.cast(m, pMeta, eType);
-                       } else if (c == '@') {
-                               Collection l = new ObjectList(session);
-                               o = parseIntoCollection(session, r, l, sType, 
isUrlParamValue, pMeta);
-                       } else {
-                               String s = parseString(session, r, 
isUrlParamValue);
-                               if (c != '\'') {
-                                       if ("true".equals(s) || 
"false".equals(s))
-                                               o = Boolean.valueOf(s);
-                                       else if (! "null".equals(s)) {
-                                               if (isNumeric(s))
-                                                       o = 
StringUtils.parseNumber(s, Number.class);
-                                               else
-                                                       o = s;
-                                       }
-                               } else {
-                                       o = s;
-                               }
-                       }
-               } else if (sType.isBoolean()) {
-                       o = parseBoolean(session, r);
-               } else if (sType.isCharSequence()) {
-                       o = parseString(session, r, isUrlParamValue);
-               } else if (sType.isChar()) {
-                       String s = parseString(session, r, isUrlParamValue);
-                       o = s == null ? null : s.charAt(0);
-               } else if (sType.isNumber()) {
-                       o = parseNumber(session, r, (Class<? extends 
Number>)sType.getInnerClass());
-               } else if (sType.isMap()) {
-                       Map m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : new ObjectMap(session));
-                       o = parseIntoMap(session, r, m, sType.getKeyType(), 
sType.getValueType(), pMeta);
-               } else if (sType.isCollection()) {
-                       if (c == '(') {
-                               ObjectMap m = new ObjectMap(session);
-                               parseIntoMap(session, r, m, string(), object(), 
pMeta);
-                               // Handle case where it's a collection, but 
serialized as a map with a _type or _value key.
-                               if 
(m.containsKey(session.getBeanTypePropertyName(sType)))
-                                       o = session.cast(m, pMeta, eType);
-                               // Handle case where it's a collection, but 
only a single value was specified.
-                               else {
-                                       Collection l = (
-                                               
sType.canCreateNewInstance(outer)
-                                               ? 
(Collection)sType.newInstance(outer)
-                                               : new ObjectList(session)
-                                       );
-                                       l.add(m.cast(sType.getElementType()));
-                                       o = l;
-                               }
-                       } else {
-                               Collection l = (
-                                       sType.canCreateNewInstance(outer)
-                                       ? (Collection)sType.newInstance(outer)
-                                       : new ObjectList(session)
-                               );
-                               o = parseIntoCollection(session, r, l, sType, 
isUrlParamValue, pMeta);
-                       }
-               } else if (sType.canCreateNewBean(outer)) {
-                       BeanMap m = session.newBeanMap(outer, 
sType.getInnerClass());
-                       m = parseIntoBeanMap(session, r, m);
-                       o = m == null ? null : m.getBean();
-               } else if (sType.canCreateNewInstanceFromString(outer)) {
-                       String s = parseString(session, r, isUrlParamValue);
-                       if (s != null)
-                               o = sType.newInstanceFromString(outer, s);
-               } else if (sType.canCreateNewInstanceFromNumber(outer)) {
-                       o = sType.newInstanceFromNumber(session, outer, 
parseNumber(session, r, sType.getNewInstanceFromNumberClass()));
-               } else if (sType.isArray() || sType.isArgs()) {
-                       if (c == '(') {
-                               ObjectMap m = new ObjectMap(session);
-                               parseIntoMap(session, r, m, string(), object(), 
pMeta);
-                               // Handle case where it's an array, but 
serialized as a map with a _type or _value key.
-                               if 
(m.containsKey(session.getBeanTypePropertyName(sType)))
-                                       o = session.cast(m, pMeta, eType);
-                               // Handle case where it's an array, but only a 
single value was specified.
-                               else {
-                                       ArrayList l = new ArrayList(1);
-                                       l.add(m.cast(sType.getElementType()));
-                                       o = session.toArray(sType, l);
-                               }
-                       } else {
-                               ArrayList l = 
(ArrayList)parseIntoCollection(session, r, new ArrayList(), sType, 
isUrlParamValue, pMeta);
-                               o = session.toArray(sType, l);
-                       }
-               } else if (c == '(') {
-                       // It could be a non-bean with _type attribute.
-                       ObjectMap m = new ObjectMap(session);
-                       parseIntoMap(session, r, m, string(), object(), pMeta);
-                       if 
(m.containsKey(session.getBeanTypePropertyName(sType)))
-                               o = session.cast(m, pMeta, eType);
-                       else
-                               throw new ParseException(session, "Class 
''{0}'' could not be instantiated.  Reason: ''{1}''",
-                                       sType.getInnerClass().getName(), 
sType.getNotABeanReason());
-               } else if (c == 'n') {
-                       r.read();
-                       parseNull(session, r);
-               } else {
-                       throw new ParseException(session, "Class ''{0}'' could 
not be instantiated.  Reason: ''{1}''",
-                               sType.getInnerClass().getName(), 
sType.getNotABeanReason());
-               }
-
-               if (o == null && sType.isPrimitive())
-                       o = sType.getPrimitiveDefault();
-               if (transform != null && o != null)
-                       o = transform.unswap(session, o, eType);
-
-               if (outer != null)
-                       setParent(eType, o, outer);
-
-               return (T)o;
-       }
-
-       private <K,V> Map<K,V> parseIntoMap(UonParserSession session, 
ParserReader r, Map<K,V> m, ClassMeta<K> keyType,
-                       ClassMeta<V> valueType, BeanPropertyMeta pMeta) throws 
Exception {
-
-               if (keyType == null)
-                       keyType = (ClassMeta<K>)string();
-
-               int c = r.read();
-               if (c == -1 || c == AMP)
-                       return null;
-               if (c == 'n')
-                       return (Map<K,V>)parseNull(session, r);
-               if (c != '(')
-                       throw new ParseException(session, "Expected '(' at 
beginning of object.");
-
-               final int S1=1; // Looking for attrName start.
-               final int S2=2; // Found attrName end, looking for =.
-               final int S3=3; // Found =, looking for valStart.
-               final int S4=4; // Looking for , or )
-               boolean isInEscape = false;
-
-               int state = S1;
-               K currAttr = null;
-               while (c != -1 && c != AMP) {
-                       c = r.read();
-                       if (! isInEscape) {
-                               if (state == S1) {
-                                       if (c == ')')
-                                               return m;
-                                       if (Character.isWhitespace(c))
-                                               skipSpace(r);
-                                       else {
-                                               r.unread();
-                                               Object attr = 
parseAttr(session, r, session.isDecodeChars());
-                                               currAttr = attr == null ? null 
: convertAttrToType(session, m, session.trim(attr.toString()), keyType);
-                                               state = S2;
-                                               c = 0; // Avoid isInEscape if c 
was '\'
-                                       }
-                               } else if (state == S2) {
-                                       if (c == EQ || c == '=')
-                                               state = S3;
-                                       else if (c == -1 || c == ',' || c == 
')' || c == AMP) {
-                                               if (currAttr == null) {
-                                                       // Value was '%00'
-                                                       r.unread();
-                                                       return null;
-                                               }
-                                               m.put(currAttr, null);
-                                               if (c == ')' || c == -1 || c == 
AMP)
-                                                       return m;
-                                               state = S1;
-                                       }
-                               } else if (state == S3) {
-                                       if (c == -1 || c == ',' || c == ')' || 
c == AMP) {
-                                               V value = 
convertAttrToType(session, m, "", valueType);
-                                               m.put(currAttr, value);
-                                               if (c == -1 || c == ')' || c == 
AMP)
-                                                       return m;
-                                               state = S1;
-                                       } else  {
-                                               V value = 
parseAnything(session, valueType, r.unread(), m, false, pMeta);
-                                               setName(valueType, value, 
currAttr);
-                                               m.put(currAttr, value);
-                                               state = S4;
-                                               c = 0; // Avoid isInEscape if c 
was '\'
-                                       }
-                               } else if (state == S4) {
-                                       if (c == ',')
-                                               state = S1;
-                                       else if (c == ')' || c == -1 || c == 
AMP) {
-                                               return m;
-                                       }
-                               }
-                       }
-                       isInEscape = isInEscape(c, r, isInEscape);
-               }
-               if (state == S1)
-                       throw new ParseException(session, "Could not find 
attribute name on object.");
-               if (state == S2)
-                       throw new ParseException(session, "Could not find '=' 
following attribute name on object.");
-               if (state == S3)
-                       throw new ParseException(session, "Dangling '=' found 
in object entry");
-               if (state == S4)
-                       throw new ParseException(session, "Could not find ')' 
marking end of object.");
-
-               return null; // Unreachable.
-       }
-
-       private <E> Collection<E> parseIntoCollection(UonParserSession session, 
ParserReader r, Collection<E> l,
-                       ClassMeta<E> type, boolean isUrlParamValue, 
BeanPropertyMeta pMeta) throws Exception {
-
-               int c = r.readSkipWs();
-               if (c == -1 || c == AMP)
-                       return null;
-               if (c == 'n')
-                       return (Collection<E>)parseNull(session, r);
-
-               int argIndex = 0;
-
-               // If we're parsing a top-level parameter, we're allowed to 
have comma-delimited lists outside parenthesis (e.g. "&foo=1,2,3&bar=a,b,c")
-               // This is not allowed at lower levels since we use comma's as 
end delimiters.
-               boolean isInParens = (c == '@');
-               if (! isInParens) {
-                       if (isUrlParamValue)
-                               r.unread();
-                       else
-                               throw new ParseException(session, "Could not 
find '(' marking beginning of collection.");
-               } else {
-                       r.read();
-               }
-
-               if (isInParens) {
-                       final int S1=1; // Looking for starting of first entry.
-                       final int S2=2; // Looking for starting of subsequent 
entries.
-                       final int S3=3; // Looking for , or ) after first entry.
-
-                       int state = S1;
-                       while (c != -1 && c != AMP) {
-                               c = r.read();
-                               if (state == S1 || state == S2) {
-                                       if (c == ')') {
-                                               if (state == S2) {
-                                                       
l.add((E)parseAnything(session, type.isArgs() ? type.getArg(argIndex++) : 
type.getElementType(),
-                                                                       
r.unread(), l, false, pMeta));
-                                                       r.read();
-                                               }
-                                               return l;
-                                       } else if (Character.isWhitespace(c)) {
-                                               skipSpace(r);
-                                       } else {
-                                               l.add((E)parseAnything(session, 
type.isArgs() ? type.getArg(argIndex++) : type.getElementType(),
-                                                               r.unread(), l, 
false, pMeta));
-                                               state = S3;
-                                       }
-                               } else if (state == S3) {
-                                       if (c == ',') {
-                                               state = S2;
-                                       } else if (c == ')') {
-                                               return l;
-                                       }
-                               }
-                       }
-                       if (state == S1 || state == S2)
-                               throw new ParseException(session, "Could not 
find start of entry in array.");
-                       if (state == S3)
-                               throw new ParseException(session, "Could not 
find end of entry in array.");
-
-               } else {
-                       final int S1=1; // Looking for starting of entry.
-                       final int S2=2; // Looking for , or & or END after 
first entry.
-
-                       int state = S1;
-                       while (c != -1 && c != AMP) {
-                               c = r.read();
-                               if (state == S1) {
-                                       if (Character.isWhitespace(c)) {
-                                               skipSpace(r);
-                                       } else {
-                                               l.add((E)parseAnything(session, 
type.isArgs() ? type.getArg(argIndex++) : type.getElementType(),
-                                                               r.unread(), l, 
false, pMeta));
-                                               state = S2;
-                                       }
-                               } else if (state == S2) {
-                                       if (c == ',') {
-                                               state = S1;
-                                       } else if (Character.isWhitespace(c)) {
-                                               skipSpace(r);
-                                       } else if (c == AMP || c == -1) {
-                                               r.unread();
-                                               return l;
-                                       }
-                               }
-                       }
-               }
-
-               return null;  // Unreachable.
-       }
-
-       private <T> BeanMap<T> parseIntoBeanMap(UonParserSession session, 
ParserReader r, BeanMap<T> m) throws Exception {
-
-               int c = r.readSkipWs();
-               if (c == -1 || c == AMP)
-                       return null;
-               if (c == 'n')
-                       return (BeanMap<T>)parseNull(session, r);
-               if (c != '(')
-                       throw new ParseException(session, "Expected '(' at 
beginning of object.");
-
-               final int S1=1; // Looking for attrName start.
-               final int S2=2; // Found attrName end, looking for =.
-               final int S3=3; // Found =, looking for valStart.
-               final int S4=4; // Looking for , or }
-               boolean isInEscape = false;
-
-               int state = S1;
-               String currAttr = "";
-               int currAttrLine = -1, currAttrCol = -1;
-               while (c != -1 && c != AMP) {
-                       c = r.read();
-                       if (! isInEscape) {
-                               if (state == S1) {
-                                       if (c == ')' || c == -1 || c == AMP) {
-                                               return m;
-                                       }
-                                       if (Character.isWhitespace(c))
-                                               skipSpace(r);
-                                       else {
-                                               r.unread();
-                                               currAttrLine= r.getLine();
-                                               currAttrCol = r.getColumn();
-                                               currAttr = 
parseAttrName(session, r, session.isDecodeChars());
-                                               if (currAttr == null)  // Value 
was '%00'
-                                                       return null;
-                                               state = S2;
-                                       }
-                               } else if (state == S2) {
-                                       if (c == EQ || c == '=')
-                                               state = S3;
-                                       else if (c == -1 || c == ',' || c == 
')' || c == AMP) {
-                                               m.put(currAttr, null);
-                                               if (c == ')' || c == -1 || c == 
AMP)
-                                                       return m;
-                                               state = S1;
-                                       }
-                               } else if (state == S3) {
-                                       if (c == -1 || c == ',' || c == ')' || 
c == AMP) {
-                                               if (! 
currAttr.equals(session.getBeanTypePropertyName(m.getClassMeta()))) {
-                                                       BeanPropertyMeta pMeta 
= m.getPropertyMeta(currAttr);
-                                                       if (pMeta == null) {
-                                                               
session.onUnknownProperty(currAttr, m, currAttrLine, currAttrCol);
-                                                       } else {
-                                                               Object value = 
session.convertToType("", pMeta.getClassMeta());
-                                                               pMeta.set(m, 
currAttr, value);
-                                                       }
-                                               }
-                                               if (c == -1 || c == ')' || c == 
AMP)
-                                                       return m;
-                                               state = S1;
-                                       } else {
-                                               if (! 
currAttr.equals(session.getBeanTypePropertyName(m.getClassMeta()))) {
-                                                       BeanPropertyMeta pMeta 
= m.getPropertyMeta(currAttr);
-                                                       if (pMeta == null) {
-                                                               
session.onUnknownProperty(currAttr, m, currAttrLine, currAttrCol);
-                                                               
parseAnything(session, object(), r.unread(), m.getBean(false), false, null); // 
Read content anyway to ignore it
-                                                       } else {
-                                                               
session.setCurrentProperty(pMeta);
-                                                               ClassMeta<?> cm 
= pMeta.getClassMeta();
-                                                               Object value = 
parseAnything(session, cm, r.unread(), m.getBean(false), false, pMeta);
-                                                               setName(cm, 
value, currAttr);
-                                                               pMeta.set(m, 
currAttr, value);
-                                                               
session.setCurrentProperty(null);
-                                                       }
-                                               }
-                                               state = S4;
-                                       }
-                               } else if (state == S4) {
-                                       if (c == ',')
-                                               state = S1;
-                                       else if (c == ')' || c == -1 || c == 
AMP) {
-                                               return m;
-                                       }
-                               }
-                       }
-                       isInEscape = isInEscape(c, r, isInEscape);
-               }
-               if (state == S1)
-                       throw new ParseException(session, "Could not find 
attribute name on object.");
-               if (state == S2)
-                       throw new ParseException(session, "Could not find '=' 
following attribute name on object.");
-               if (state == S3)
-                       throw new ParseException(session, "Could not find value 
following '=' on object.");
-               if (state == S4)
-                       throw new ParseException(session, "Could not find ')' 
marking end of object.");
-
-               return null; // Unreachable.
-       }
-
-       private static Object parseNull(UonParserSession session, ParserReader 
r) throws Exception {
-               String s = parseString(session, r, false);
-               if ("ull".equals(s))
-                       return null;
-               throw new ParseException(session, "Unexpected character 
sequence: ''{0}''", s);
-       }
-
-       /**
-        * Convenience method for parsing an attribute from the specified 
parser.
-        *
-        * @param session
-        * @param r
-        * @param encoded
-        * @return The parsed object
-        * @throws Exception
-        */
-       protected static final Object parseAttr(UonParserSession session, 
ParserReader r, boolean encoded) throws Exception {
-               Object attr;
-               attr = parseAttrName(session, r, encoded);
-               return attr;
-       }
-
-       /**
-        * Parses an attribute name from the specified reader.
-        *
-        * @param session
-        * @param r
-        * @param encoded
-        * @return The parsed attribute name.
-        * @throws Exception
-        */
-       protected static String parseAttrName(UonParserSession session, 
ParserReader r, boolean encoded) throws Exception {
-
-               // If string is of form 'xxx', we're looking for ' at the end.
-               // Otherwise, we're looking for '&' or '=' or WS or -1 denoting 
the end of this string.
-
-               int c = r.peekSkipWs();
-               if (c == '\'')
-                       return parsePString(session, r);
-
-               r.mark();
-               boolean isInEscape = false;
-               if (encoded) {
-                       while (c != -1) {
-                               c = r.read();
-                               if (! isInEscape) {
-                                       if (c == AMP || c == EQ || c == -1 || 
Character.isWhitespace(c)) {
-                                               if (c != -1)
-                                                       r.unread();
-                                               String s = r.getMarked();
-                                               return ("null".equals(s) ? null 
: s);
-                                       }
-                               }
-                               else if (c == AMP)
-                                       r.replace('&');
-                               else if (c == EQ)
-                                       r.replace('=');
-                               isInEscape = isInEscape(c, r, isInEscape);
-                       }
-               } else {
-                       while (c != -1) {
-                               c = r.read();
-                               if (! isInEscape) {
-                                       if (c == '=' || c == -1 || 
Character.isWhitespace(c)) {
-                                               if (c != -1)
-                                                       r.unread();
-                                               String s = r.getMarked();
-                                               return ("null".equals(s) ? null 
: session.trim(s));
-                                       }
-                               }
-                               isInEscape = isInEscape(c, r, isInEscape);
-                       }
-               }
-
-               // We should never get here.
-               throw new ParseException(session, "Unexpected condition.");
-       }
-
-
-       /**
-        * Returns true if the next character in the stream is preceded by an 
escape '~' character.
-        *
-        * @param c The current character.
-        * @param r The reader.
-        * @param prevIsInEscape What the flag was last time.
-        */
-       private static final boolean isInEscape(int c, ParserReader r, boolean 
prevIsInEscape) throws Exception {
-               if (c == '~' && ! prevIsInEscape) {
-                       c = r.peek();
-                       if (escapedChars.contains(c)) {
-                               r.delete();
-                               return true;
-                       }
-               }
-               return false;
-       }
-
-       /**
-        * Parses a string value from the specified reader.
-        *
-        * @param session
-        * @param r
-        * @param isUrlParamValue
-        * @return The parsed string.
-        * @throws Exception
-        */
-       protected static String parseString(UonParserSession session, 
ParserReader r, boolean isUrlParamValue) throws Exception {
-
-               // If string is of form 'xxx', we're looking for ' at the end.
-               // Otherwise, we're looking for ',' or ')' or -1 denoting the 
end of this string.
-
-               int c = r.peekSkipWs();
-               if (c == '\'')
-                       return parsePString(session, r);
-
-               r.mark();
-               boolean isInEscape = false;
-               String s = null;
-               AsciiSet endChars = (isUrlParamValue ? endCharsParam : 
endCharsNormal);
-               while (c != -1) {
-                       c = r.read();
-                       if (! isInEscape) {
-                               // If this is a URL parameter value, we're 
looking for:  &
-                               // If not, we're looking for:  &,)
-                               if (endChars.contains(c)) {
-                                       r.unread();
-                                       c = -1;
-                               }
-                       }
-                       if (c == -1)
-                               s = r.getMarked();
-                       else if (c == EQ)
-                               r.replace('=');
-                       else if (Character.isWhitespace(c) && ! 
isUrlParamValue) {
-                               s = r.getMarked(0, -1);
-                               skipSpace(r);
-                               c = -1;
-                       }
-                       isInEscape = isInEscape(c, r, isInEscape);
-               }
-
-               if (isUrlParamValue)
-                       s = trim(s);
-
-               return ("null".equals(s) ? null : session.trim(s));
-       }
-
-       private static final AsciiSet endCharsParam = new AsciiSet(""+AMP), 
endCharsNormal = new AsciiSet(",)"+AMP);
-
-
-       /*=
-        * Parses a string of the form "'foo'"
-        * All whitespace within parenthesis are preserved.
-        */
-       static String parsePString(UonParserSession session, ParserReader r) 
throws Exception {
-
-               r.read(); // Skip first quote.
-               r.mark();
-               int c = 0;
-
-               boolean isInEscape = false;
-               while (c != -1) {
-                       c = r.read();
-                       if (! isInEscape) {
-                               if (c == '\'')
-                                       return session.trim(r.getMarked(0, -1));
-                       }
-                       if (c == EQ)
-                               r.replace('=');
-                       isInEscape = isInEscape(c, r, isInEscape);
-               }
-               throw new ParseException(session, "Unmatched parenthesis");
-       }
-
-       private static Boolean parseBoolean(UonParserSession session, 
ParserReader r) throws Exception {
-               String s = parseString(session, r, false);
-               if (s == null || s.equals("null"))
-                       return null;
-               if (s.equals("true"))
-                       return true;
-               if (s.equals("false"))
-                       return false;
-               throw new ParseException(session, "Unrecognized syntax for 
boolean.  ''{0}''.", s);
-       }
-
-       private static Number parseNumber(UonParserSession session, 
ParserReader r, Class<? extends Number> c) throws Exception {
-               String s = parseString(session, r, false);
-               if (s == null)
-                       return null;
-               return StringUtils.parseNumber(s, c);
-       }
-
-       /*
-        * Call this method after you've finished a parsing a string to make 
sure that if there's any
-        * remainder in the input, that it consists only of whitespace and 
comments.
-        */
-       private static void validateEnd(UonParserSession session, ParserReader 
r) throws Exception {
-               while (true) {
-                       int c = r.read();
-                       if (c == -1)
-                               return;
-                       if (! Character.isWhitespace(c))
-                               throw new ParseException(session, "Remainder 
after parse: ''{0}''.", (char)c);
-               }
-       }
-
-       private static void skipSpace(ParserReader r) throws Exception {
-               int c = 0;
-               while ((c = r.read()) != -1) {
-                       if (c <= 2 || ! Character.isWhitespace(c)) {
-                               r.unread();
-                               return;
-                       }
-               }
-       }
-
-       /**
         * Create a UON parser session for parsing parameter values.
         *
-        * @param input
         * @return A new parser session.
         */
-       protected final UonParserSession createParameterSession(Object input) {
-               return new UonParserSession(ctx, input);
+       protected final UonParserSession createParameterSession() {
+               return new UonParserSession(ctx);
        }
 
-
-       
//--------------------------------------------------------------------------------
-       // Entry point methods
-       
//--------------------------------------------------------------------------------
-
        @Override /* Parser */
-       public UonParserSession createSession(Object input, ObjectMap op, 
Method javaMethod, Object outer, Locale locale,
-                       TimeZone timeZone, MediaType mediaType) {
-               return new UonParserSession(ctx, op, input, javaMethod, outer, 
locale, timeZone, mediaType);
-       }
-
-       @Override /* Parser */
-       protected <T> T doParse(ParserSession session, ClassMeta<T> type) 
throws Exception {
-               UonParserSession s = (UonParserSession)session;
-               UonReader r = s.getReader();
-               T o = parseAnything(s, type, r, s.getOuter(), true, null);
-               validateEnd(s, r);
-               return o;
-       }
-
-       @Override /* ReaderParser */
-       protected <K,V> Map<K,V> doParseIntoMap(ParserSession session, Map<K,V> 
m, Type keyType, Type valueType) throws Exception {
-               UonParserSession s = (UonParserSession)session;
-               UonReader r = s.getReader();
-               m = parseIntoMap(s, r, m, 
(ClassMeta<K>)session.getClassMeta(keyType), 
(ClassMeta<V>)session.getClassMeta(valueType), null);
-               validateEnd(s, r);
-               return m;
-       }
-
-       @Override /* ReaderParser */
-       protected <E> Collection<E> doParseIntoCollection(ParserSession 
session, Collection<E> c, Type elementType) throws Exception {
-               UonParserSession s = (UonParserSession)session;
-               UonReader r = s.getReader();
-               c = parseIntoCollection(s, r, c, 
(ClassMeta<E>)session.getClassMeta(elementType), false, null);
-               validateEnd(s, r);
-               return c;
+       public UonParserSession createSession(ParserSessionArgs args) {
+               return new UonParserSession(ctx, args);
        }
 }

Reply via email to