You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2017/03/10 16:51:12 UTC

[16/34] incubator-juneau git commit: Add builder classes for all serializers and parsers.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java b/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java
index abd00f5..a655048 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java
@@ -12,8 +12,6 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.serializer;
 
-import static org.apache.juneau.serializer.SerializerContext.*;
-
 import java.io.*;
 import java.lang.reflect.*;
 import java.text.*;
@@ -39,18 +37,18 @@ import org.apache.juneau.soap.*;
  * <p>
  * However, the media types can also be specified programmatically by overriding the {@link #getMediaTypes()}
  * 	and {@link #getResponseContentType()} methods.
- *
- * <h5 class='section'>Configurable properties:</h5>
- * See {@link SerializerContext} for a list of configurable properties that can be set on this class
- * 	using the {@link #setProperty(String, Object)} method.
  */
-public abstract class Serializer extends CoreApi {
+public abstract class Serializer extends CoreObject {
 
 	private final MediaType[] mediaTypes;
 	private final MediaType contentType;
+	private final SerializerContext ctx;
 
 	// Hidden constructors to force subclass from OuputStreamSerializer or WriterSerializer.
-	Serializer() {
+	Serializer(PropertyStore propertyStore) {
+		super(propertyStore);
+		this.ctx = createContext(SerializerContext.class);
+
 		Produces p = ReflectionUtils.getAnnotation(Produces.class, getClass());
 		if (p == null)
 			throw new RuntimeException(MessageFormat.format("Class ''{0}'' is missing the @Produces annotation", getClass().getName()));
@@ -65,10 +63,15 @@ public abstract class Serializer extends CoreApi {
 		contentType = ct.isEmpty() ? null : MediaType.forString(ct);
 	}
 
+	@Override /* CoreObject */
+	public SerializerBuilder builder() {
+		return new SerializerBuilder(propertyStore);
+	}
+
 	/**
-	 * Returns <jk>true</jk> if this parser subclasses from {@link WriterSerializer}.
+	 * Returns <jk>true</jk> if this serializer subclasses from {@link WriterSerializer}.
 	 *
-	 * @return <jk>true</jk> if this parser subclasses from {@link WriterSerializer}.
+	 * @return <jk>true</jk> if this serializer subclasses from {@link WriterSerializer}.
 	 */
 	public abstract boolean isWriterSerializer();
 
@@ -182,7 +185,7 @@ public abstract class Serializer extends CoreApi {
 	 * @return The new session.
 	 */
 	public SerializerSession createSession(Object output, ObjectMap op, Method javaMethod, Locale locale, TimeZone timeZone, MediaType mediaType) {
-		return new SerializerSession(getContext(SerializerContext.class), op, output, javaMethod, locale, timeZone, mediaType);
+		return new SerializerSession(ctx, op, output, javaMethod, locale, timeZone, mediaType);
 	}
 
 	/**
@@ -245,7 +248,7 @@ public abstract class Serializer extends CoreApi {
 	}
 
 	/**
-	 * Returns the first media type specified on this parser via the {@link Produces} annotation.
+	 * Returns the first media type specified on this serializer via the {@link Produces} annotation.
 	 *
 	 * @return The media type.
 	 */
@@ -284,863 +287,4 @@ public abstract class Serializer extends CoreApi {
 	public MediaType getResponseContentType() {
 		return contentType;
 	}
-
-
-	//--------------------------------------------------------------------------------
-	// Properties
-	//--------------------------------------------------------------------------------
-
-	/**
-	 * <b>Configuration property:</b>  Max serialization depth.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.maxDepth"</js>
-	 * 	<li><b>Data type:</b> <code>Integer</code>
-	 * 	<li><b>Default:</b> <code>100</code>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * Abort serialization if specified depth is reached in the POJO tree.
-	 * If this depth is exceeded, an exception is thrown.
-	 * This prevents stack overflows from occurring when trying to serialize models with recursive references.
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_maxDepth</jsf>, value)</code>.
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_maxDepth
-	 */
-	public Serializer setMaxDepth(int value) throws LockedException {
-		return setProperty(SERIALIZER_maxDepth, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  Initial depth.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.initialDepth"</js>
-	 * 	<li><b>Data type:</b> <code>Integer</code>
-	 * 	<li><b>Default:</b> <code>0</code>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * The initial indentation level at the root.
-	 * Useful when constructing document fragments that need to be indented at a certain level.
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_initialDepth</jsf>, value)</code>.
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_initialDepth
-	 */
-	public Serializer setInitialDepth(int value) throws LockedException {
-		return setProperty(SERIALIZER_initialDepth, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  Automatically detect POJO recursions.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.detectRecursions"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>false</jk>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * Specifies that recursions should be checked for during serialization.
-	 * <p>
-	 * Recursions can occur when serializing models that aren't true trees, but rather contain loops.
-	 * <p>
-	 * The behavior when recursions are detected depends on the value for {@link SerializerContext#SERIALIZER_ignoreRecursions}.
-	 * <p>
-	 * For example, if a model contains the links A-&gt;B-&gt;C-&gt;A, then the JSON generated will look like
-	 * 	the following when <jsf>SERIALIZER_ignoreRecursions</jsf> is <jk>true</jk>...
-	 * <code>{A:{B:{C:null}}}</code><br>
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_detectRecursions</jsf>, value)</code>.
-	 * 	<li>Checking for recursion can cause a small performance penalty.
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_detectRecursions
-	 */
-	public Serializer setDetectRecursions(boolean value) throws LockedException {
-		return setProperty(SERIALIZER_detectRecursions, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  Ignore recursion errors.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.ignoreRecursions"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>false</jk>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * Used in conjunction with {@link SerializerContext#SERIALIZER_detectRecursions}.
-	 * Setting is ignored if <jsf>SERIALIZER_detectRecursions</jsf> is <jk>false</jk>.
-	 * <p>
-	 * If <jk>true</jk>, when we encounter the same object when serializing a tree,
-	 * 	we set the value to <jk>null</jk>.
-	 * Otherwise, an exception is thrown.
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_ignoreRecursions</jsf>, value)</code>.
-	 * 	<li>Checking for recursion can cause a small performance penalty.
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_ignoreRecursions
-	 */
-	public Serializer setIgnoreRecursions(boolean value) throws LockedException {
-		return setProperty(SERIALIZER_ignoreRecursions, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  Use whitespace.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.useWhitepace"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>false</jk>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * If <jk>true</jk>, newlines and indentation and spaces are added to the output to improve readability.
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_useWhitespace</jsf>, value)</code>.
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_useWhitespace
-	 */
-	public Serializer setUseWhitespace(boolean value) throws LockedException {
-		return setProperty(SERIALIZER_useWhitespace, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  Add <js>"_type"</js> properties when needed.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.addBeanTypeProperties"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>false</jk>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * If <jk>true</jk>, then <js>"_type"</js> properties will be added to beans if their type cannot be inferred through reflection.
-	 * This is used to recreate the correct objects during parsing if the object types cannot be inferred.
-	 * For example, when serializing a {@code Map<String,Object>} field, where the bean class cannot be determined from the value type.
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_addBeanTypeProperties</jsf>, value)</code>.
-	 * 	<li>Checking for recursion can cause a small performance penalty.
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_addBeanTypeProperties
-	 */
-	public Serializer setAddBeanTypeProperties(boolean value) throws LockedException {
-		return setProperty(SERIALIZER_addBeanTypeProperties, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  Quote character.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.quoteChar"</js>
-	 * 	<li><b>Data type:</b> <code>Character</code>
-	 * 	<li><b>Default:</b> <js>'"'</js>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * This is the character used for quoting attributes and values.
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_quoteChar</jsf>, value)</code>.
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_quoteChar
-	 */
-	public Serializer setQuoteChar(char value) throws LockedException {
-		return setProperty(SERIALIZER_quoteChar, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  Trim null bean property values.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.trimNullProperties"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>true</jk>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * If <jk>true</jk>, null bean values will not be serialized to the output.
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_trimNullProperties</jsf>, value)</code>.
-	 * 	<li>Enabling this setting has the following effects on parsing:
-	 * 	<ul>
-	 * 		<li>Map entries with <jk>null</jk> values will be lost.
-	 * 	</ul>
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_trimNullProperties
-	 */
-	public Serializer setTrimNullProperties(boolean value) throws LockedException {
-		return setProperty(SERIALIZER_trimNullProperties, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  Trim empty lists and arrays.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.trimEmptyLists"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>false</jk>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * If <jk>true</jk>, empty list values will not be serialized to the output.
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_trimEmptyCollections</jsf>, value)</code>.
-	 * 	<li>Enabling this setting has the following effects on parsing:
-	 * 	<ul>
-	 * 		<li>Map entries with empty list values will be lost.
-	 * 		<li>Bean properties with empty list values will not be set.
-	 * 	</ul>
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_trimEmptyCollections
-	 */
-	public Serializer setTrimEmptyCollections(boolean value) throws LockedException {
-		return setProperty(SERIALIZER_trimEmptyCollections, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  Trim empty maps.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.trimEmptyMaps"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>false</jk>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * If <jk>true</jk>, empty map values will not be serialized to the output.
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_trimEmptyMaps</jsf>, value)</code>.
-	 * 	<li>Enabling this setting has the following effects on parsing:
-	 * 	<ul>
-	 * 		<li>Bean properties with empty map values will not be set.
-	 * 	</ul>
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_trimEmptyMaps
-	 */
-	public Serializer setTrimEmptyMaps(boolean value) throws LockedException {
-		return setProperty(SERIALIZER_trimEmptyMaps, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  Trim strings.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.trimStrings"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>false</jk>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * If <jk>true</jk>, string values will be trimmed of whitespace using {@link String#trim()} before being serialized.
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_trimStrings</jsf>, value)</code>.
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_trimStrings
-	 */
-	public Serializer setTrimStrings(boolean value) throws LockedException {
-		return setProperty(SERIALIZER_trimStrings, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  URI base for relative URIs.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.relativeUriBase"</js>
-	 * 	<li><b>Data type:</b> <code>String</code>
-	 * 	<li><b>Default:</b> <js>""</js>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * Prepended to relative URIs during serialization (along with the {@link SerializerContext#SERIALIZER_absolutePathUriBase} if specified.
-	 * (i.e. URIs not containing a schema and not starting with <js>'/'</js>).
-	 * (e.g. <js>"foo/bar"</js>)
-	 *
-	 * <h5 class='section'>Example:</h5>
-	 * <table class='styled'>
-	 * 	<tr><th>SERIALIZER_relativeUriBase</th><th>URI</th><th>Serialized URI</th></tr>
-	 * 	<tr>
-	 * 		<td><code>http://foo:9080/bar/baz</code></td>
-	 * 		<td><code>mywebapp</code></td>
-	 * 		<td><code>http://foo:9080/bar/baz/mywebapp</code></td>
-	 * 	</tr>
-	 * 	<tr>
-	 * 		<td><code>http://foo:9080/bar/baz</code></td>
-	 * 		<td><code>/mywebapp</code></td>
-	 * 		<td><code>/mywebapp</code></td>
-	 * 	</tr>
-	 * 	<tr>
-	 * 		<td><code>http://foo:9080/bar/baz</code></td>
-	 * 		<td><code>http://mywebapp</code></td>
-	 * 		<td><code>http://mywebapp</code></td>
-	 * 	</tr>
-	 * </table>
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_relativeUriBase</jsf>, value)</code>.
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_relativeUriBase
-	 */
-	public Serializer setRelativeUriBase(String value) throws LockedException {
-		return setProperty(SERIALIZER_relativeUriBase, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  URI base for relative URIs with absolute paths.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.absolutePathUriBase"</js>
-	 * 	<li><b>Data type:</b> <code>String</code>
-	 * 	<li><b>Default:</b> <js>""</js>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * Prepended to relative absolute-path URIs during serialization.
-	 * (i.e. URIs starting with <js>'/'</js>).
-	 * (e.g. <js>"/foo/bar"</js>)
-	 *
-	 * <h5 class='section'>Examples:</h5>
-	 * <table class='styled'>
-	 * 	<tr><th>SERIALIZER_absolutePathUriBase</th><th>URI</th><th>Serialized URI</th></tr>
-	 * 	<tr>
-	 * 		<td><code>http://foo:9080/bar/baz</code></td>
-	 * 		<td><code>mywebapp</code></td>
-	 * 		<td><code>mywebapp</code></td>
-	 * 	</tr>
-	 * 	<tr>
-	 * 		<td><code>http://foo:9080/bar/baz</code></td>
-	 * 		<td><code>/mywebapp</code></td>
-	 * 		<td><code>http://foo:9080/bar/baz/mywebapp</code></td>
-	 * 	</tr>
-	 * 	<tr>
-	 * 		<td><code>http://foo:9080/bar/baz</code></td>
-	 * 		<td><code>http://mywebapp</code></td>
-	 * 		<td><code>http://mywebapp</code></td>
-	 * 	</tr>
-	 * </table>
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_absolutePathUriBase</jsf>, value)</code>.
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_absolutePathUriBase
-	 */
-	public Serializer setAbsolutePathUriBase(String value) throws LockedException {
-		return setProperty(SERIALIZER_absolutePathUriBase, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  Sort arrays and collections alphabetically.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.sortCollections"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>false</jk>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_sortCollections</jsf>, value)</code>.
-	 * 	<li>This introduces a slight performance penalty.
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_sortCollections
-	 */
-	public Serializer setSortCollections(boolean value) throws LockedException {
-		return setProperty(SERIALIZER_sortCollections, value);
-	}
-
-	/**
-	 * <b>Configuration property:</b>  Sort maps alphabetically.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.sortMaps"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>false</jk>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_sortMaps</jsf>, value)</code>.
-	 * 	<li>This introduces a slight performance penalty.
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_sortMaps
-	 */
-	public Serializer setSortMaps(boolean value) throws LockedException {
-		return setProperty(SERIALIZER_sortMaps, value);
-	}
-
-	@Override /* CoreApi */
-	public Serializer setBeansRequireDefaultConstructor(boolean value) throws LockedException {
-		super.setBeansRequireDefaultConstructor(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setBeansRequireSerializable(boolean value) throws LockedException {
-		super.setBeansRequireSerializable(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setBeansRequireSettersForGetters(boolean value) throws LockedException {
-		super.setBeansRequireSettersForGetters(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setBeansRequireSomeProperties(boolean value) throws LockedException {
-		super.setBeansRequireSomeProperties(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setBeanMapPutReturnsOldValue(boolean value) throws LockedException {
-		super.setBeanMapPutReturnsOldValue(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setBeanConstructorVisibility(Visibility value) throws LockedException {
-		super.setBeanConstructorVisibility(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setBeanClassVisibility(Visibility value) throws LockedException {
-		super.setBeanClassVisibility(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setBeanFieldVisibility(Visibility value) throws LockedException {
-		super.setBeanFieldVisibility(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setMethodVisibility(Visibility value) throws LockedException {
-		super.setMethodVisibility(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setUseJavaBeanIntrospector(boolean value) throws LockedException {
-		super.setUseJavaBeanIntrospector(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setUseInterfaceProxies(boolean value) throws LockedException {
-		super.setUseInterfaceProxies(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setIgnoreUnknownBeanProperties(boolean value) throws LockedException {
-		super.setIgnoreUnknownBeanProperties(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setIgnoreUnknownNullBeanProperties(boolean value) throws LockedException {
-		super.setIgnoreUnknownNullBeanProperties(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setIgnorePropertiesWithoutSetters(boolean value) throws LockedException {
-		super.setIgnorePropertiesWithoutSetters(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setIgnoreInvocationExceptionsOnGetters(boolean value) throws LockedException {
-		super.setIgnoreInvocationExceptionsOnGetters(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setIgnoreInvocationExceptionsOnSetters(boolean value) throws LockedException {
-		super.setIgnoreInvocationExceptionsOnSetters(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setSortProperties(boolean value) throws LockedException {
-		super.setSortProperties(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setNotBeanPackages(String...values) throws LockedException {
-		super.setNotBeanPackages(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setNotBeanPackages(Collection<String> values) throws LockedException {
-		super.setNotBeanPackages(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer addNotBeanPackages(String...values) throws LockedException {
-		super.addNotBeanPackages(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer addNotBeanPackages(Collection<String> values) throws LockedException {
-		super.addNotBeanPackages(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer removeNotBeanPackages(String...values) throws LockedException {
-		super.removeNotBeanPackages(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer removeNotBeanPackages(Collection<String> values) throws LockedException {
-		super.removeNotBeanPackages(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setNotBeanClasses(Class<?>...values) throws LockedException {
-		super.setNotBeanClasses(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setNotBeanClasses(Collection<Class<?>> values) throws LockedException {
-		super.setNotBeanClasses(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer addNotBeanClasses(Class<?>...values) throws LockedException {
-		super.addNotBeanClasses(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer addNotBeanClasses(Collection<Class<?>> values) throws LockedException {
-		super.addNotBeanClasses(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer removeNotBeanClasses(Class<?>...values) throws LockedException {
-		super.removeNotBeanClasses(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer removeNotBeanClasses(Collection<Class<?>> values) throws LockedException {
-		super.removeNotBeanClasses(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setBeanFilters(Class<?>...values) throws LockedException {
-		super.setBeanFilters(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setBeanFilters(Collection<Class<?>> values) throws LockedException {
-		super.setBeanFilters(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer addBeanFilters(Class<?>...values) throws LockedException {
-		super.addBeanFilters(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer addBeanFilters(Collection<Class<?>> values) throws LockedException {
-		super.addBeanFilters(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer removeBeanFilters(Class<?>...values) throws LockedException {
-		super.removeBeanFilters(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer removeBeanFilters(Collection<Class<?>> values) throws LockedException {
-		super.removeBeanFilters(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setPojoSwaps(Class<?>...values) throws LockedException {
-		super.setPojoSwaps(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setPojoSwaps(Collection<Class<?>> values) throws LockedException {
-		super.setPojoSwaps(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer addPojoSwaps(Class<?>...values) throws LockedException {
-		super.addPojoSwaps(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer addPojoSwaps(Collection<Class<?>> values) throws LockedException {
-		super.addPojoSwaps(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer removePojoSwaps(Class<?>...values) throws LockedException {
-		super.removePojoSwaps(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer removePojoSwaps(Collection<Class<?>> values) throws LockedException {
-		super.removePojoSwaps(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setImplClasses(Map<Class<?>,Class<?>> values) throws LockedException {
-		super.setImplClasses(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public <T> CoreApi addImplClass(Class<T> interfaceClass, Class<? extends T> implClass) throws LockedException {
-		super.addImplClass(interfaceClass, implClass);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setBeanDictionary(Class<?>...values) throws LockedException {
-		super.setBeanDictionary(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setBeanDictionary(Collection<Class<?>> values) throws LockedException {
-		super.setBeanDictionary(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer addToBeanDictionary(Class<?>...values) throws LockedException {
-		super.addToBeanDictionary(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer addToBeanDictionary(Collection<Class<?>> values) throws LockedException {
-		super.addToBeanDictionary(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer removeFromBeanDictionary(Class<?>...values) throws LockedException {
-		super.removeFromBeanDictionary(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer removeFromBeanDictionary(Collection<Class<?>> values) throws LockedException {
-		super.removeFromBeanDictionary(values);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setBeanTypePropertyName(String value) throws LockedException {
-		super.setBeanTypePropertyName(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setDefaultParser(Class<?> value) throws LockedException {
-		super.setDefaultParser(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setLocale(Locale value) throws LockedException {
-		super.setLocale(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setTimeZone(TimeZone value) throws LockedException {
-		super.setTimeZone(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setMediaType(MediaType value) throws LockedException {
-		super.setMediaType(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setDebug(boolean value) throws LockedException {
-		super.setDebug(value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setProperty(String name, Object value) throws LockedException {
-		super.setProperty(name, value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer setProperties(ObjectMap properties) throws LockedException {
-		super.setProperties(properties);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer addToProperty(String name, Object value) throws LockedException {
-		super.addToProperty(name, value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer putToProperty(String name, Object key, Object value) throws LockedException {
-		super.putToProperty(name, key, value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer putToProperty(String name, Object value) throws LockedException {
-		super.putToProperty(name, value);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer removeFromProperty(String name, Object value) throws LockedException {
-		super.removeFromProperty(name, value);
-		return this;
-	}
-
-
-	//--------------------------------------------------------------------------------
-	// Overridden methods
-	//--------------------------------------------------------------------------------
-
-	@Override /* CoreApi */
-	public Serializer setClassLoader(ClassLoader classLoader) throws LockedException {
-		super.setClassLoader(classLoader);
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer lock() {
-		super.lock();
-		return this;
-	}
-
-	@Override /* CoreApi */
-	public Serializer clone() throws CloneNotSupportedException {
-		Serializer c = (Serializer)super.clone();
-		return c;
-	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
new file mode 100644
index 0000000..a059d46
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
@@ -0,0 +1,896 @@
+// ***************************************************************************************************************************
+// * 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 static org.apache.juneau.serializer.SerializerContext.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+
+/**
+ * Builder class for building instances of serializers.
+ */
+public class SerializerBuilder extends CoreObjectBuilder {
+
+	/**
+	 * Constructor, default settings.
+	 */
+	public SerializerBuilder() {
+		super();
+	}
+
+	/**
+	 * Constructor.
+	 * @param propertyStore The initial configuration settings for this builder.
+	 */
+	public SerializerBuilder(PropertyStore propertyStore) {
+		super(propertyStore);
+	}
+
+	@Override /* CoreObjectBuilder */
+	public Serializer build() {
+		return null;
+	}
+
+
+	//--------------------------------------------------------------------------------
+	// Properties
+	//--------------------------------------------------------------------------------
+
+	/**
+	 * <b>Configuration property:</b>  Max serialization depth.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.maxDepth"</js>
+	 * 	<li><b>Data type:</b> <code>Integer</code>
+	 * 	<li><b>Default:</b> <code>100</code>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Abort serialization if specified depth is reached in the POJO tree.
+	 * If this depth is exceeded, an exception is thrown.
+	 * This prevents stack overflows from occurring when trying to serialize models with recursive references.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_maxDepth</jsf>, value)</code>.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_maxDepth
+	 */
+	public SerializerBuilder maxDepth(int value) {
+		return property(SERIALIZER_maxDepth, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Initial depth.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.initialDepth"</js>
+	 * 	<li><b>Data type:</b> <code>Integer</code>
+	 * 	<li><b>Default:</b> <code>0</code>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * The initial indentation level at the root.
+	 * Useful when constructing document fragments that need to be indented at a certain level.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_initialDepth</jsf>, value)</code>.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_initialDepth
+	 */
+	public SerializerBuilder initialDepth(int value) {
+		return property(SERIALIZER_initialDepth, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Automatically detect POJO recursions.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.detectRecursions"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Specifies that recursions should be checked for during serialization.
+	 * <p>
+	 * Recursions can occur when serializing models that aren't true trees, but rather contain loops.
+	 * <p>
+	 * The behavior when recursions are detected depends on the value for {@link SerializerContext#SERIALIZER_ignoreRecursions}.
+	 * <p>
+	 * For example, if a model contains the links A-&gt;B-&gt;C-&gt;A, then the JSON generated will look like
+	 * 	the following when <jsf>SERIALIZER_ignoreRecursions</jsf> is <jk>true</jk>...
+	 * <code>{A:{B:{C:null}}}</code><br>
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_detectRecursions</jsf>, value)</code>.
+	 * 	<li>Checking for recursion can cause a small performance penalty.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_detectRecursions
+	 */
+	public SerializerBuilder detectRecursions(boolean value) {
+		return property(SERIALIZER_detectRecursions, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Ignore recursion errors.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.ignoreRecursions"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Used in conjunction with {@link SerializerContext#SERIALIZER_detectRecursions}.
+	 * Setting is ignored if <jsf>SERIALIZER_detectRecursions</jsf> is <jk>false</jk>.
+	 * <p>
+	 * If <jk>true</jk>, when we encounter the same object when serializing a tree,
+	 * 	we set the value to <jk>null</jk>.
+	 * Otherwise, an exception is thrown.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_ignoreRecursions</jsf>, value)</code>.
+	 * 	<li>Checking for recursion can cause a small performance penalty.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_ignoreRecursions
+	 */
+	public SerializerBuilder ignoreRecursions(boolean value) {
+		return property(SERIALIZER_ignoreRecursions, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Use whitespace.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.useWhitepace"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * If <jk>true</jk>, newlines and indentation and spaces are added to the output to improve readability.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_useWhitespace</jsf>, value)</code>.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_useWhitespace
+	 */
+	public SerializerBuilder useWhitespace(boolean value) {
+		return property(SERIALIZER_useWhitespace, value);
+	}
+
+	/**
+	 * Shortcut for calling <code>useWhitespace(<jk>true</jk>)</code>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public SerializerBuilder ws() {
+		return useWhitespace(true);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Add <js>"_type"</js> properties when needed.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.addBeanTypeProperties"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * If <jk>true</jk>, then <js>"_type"</js> properties will be added to beans if their type cannot be inferred through reflection.
+	 * This is used to recreate the correct objects during parsing if the object types cannot be inferred.
+	 * For example, when serializing a {@code Map<String,Object>} field, where the bean class cannot be determined from the value type.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_addBeanTypeProperties</jsf>, value)</code>.
+	 * 	<li>Checking for recursion can cause a small performance penalty.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_addBeanTypeProperties
+	 */
+	public SerializerBuilder addBeanTypeProperties(boolean value) {
+		return property(SERIALIZER_addBeanTypeProperties, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Quote character.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.quoteChar"</js>
+	 * 	<li><b>Data type:</b> <code>Character</code>
+	 * 	<li><b>Default:</b> <js>'"'</js>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * This is the character used for quoting attributes and values.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_quoteChar</jsf>, value)</code>.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_quoteChar
+	 */
+	public SerializerBuilder quoteChar(char value) {
+		return property(SERIALIZER_quoteChar, value);
+	}
+
+	/**
+	 * Shortcut for calling <code>quoteChar(<js>'\''</js>)</code>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public SerializerBuilder sq() {
+		return quoteChar('\'');
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Trim null bean property values.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.trimNullProperties"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>true</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * If <jk>true</jk>, null bean values will not be serialized to the output.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_trimNullProperties</jsf>, value)</code>.
+	 * 	<li>Enabling this setting has the following effects on parsing:
+	 * 	<ul>
+	 * 		<li>Map entries with <jk>null</jk> values will be lost.
+	 * 	</ul>
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_trimNullProperties
+	 */
+	public SerializerBuilder trimNullProperties(boolean value) {
+		return property(SERIALIZER_trimNullProperties, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Trim empty lists and arrays.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.trimEmptyLists"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * If <jk>true</jk>, empty list values will not be serialized to the output.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_trimEmptyCollections</jsf>, value)</code>.
+	 * 	<li>Enabling this setting has the following effects on parsing:
+	 * 	<ul>
+	 * 		<li>Map entries with empty list values will be lost.
+	 * 		<li>Bean properties with empty list values will not be set.
+	 * 	</ul>
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_trimEmptyCollections
+	 */
+	public SerializerBuilder trimEmptyCollections(boolean value) {
+		return property(SERIALIZER_trimEmptyCollections, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Trim empty maps.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.trimEmptyMaps"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * If <jk>true</jk>, empty map values will not be serialized to the output.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_trimEmptyMaps</jsf>, value)</code>.
+	 * 	<li>Enabling this setting has the following effects on parsing:
+	 * 	<ul>
+	 * 		<li>Bean properties with empty map values will not be set.
+	 * 	</ul>
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_trimEmptyMaps
+	 */
+	public SerializerBuilder trimEmptyMaps(boolean value) {
+		return property(SERIALIZER_trimEmptyMaps, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Trim strings.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.trimStrings"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * If <jk>true</jk>, string values will be trimmed of whitespace using {@link String#trim()} before being serialized.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_trimStrings</jsf>, value)</code>.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_trimStrings
+	 */
+	public SerializerBuilder trimStrings(boolean value) {
+		return property(SERIALIZER_trimStrings, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  URI base for relative URIs.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.relativeUriBase"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <js>""</js>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Prepended to relative URIs during serialization (along with the {@link SerializerContext#SERIALIZER_absolutePathUriBase} if specified.
+	 * (i.e. URIs not containing a schema and not starting with <js>'/'</js>).
+	 * (e.g. <js>"foo/bar"</js>)
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <table class='styled'>
+	 * 	<tr><th>SERIALIZER_relativeUriBase</th><th>URI</th><th>Serialized URI</th></tr>
+	 * 	<tr>
+	 * 		<td><code>http://foo:9080/bar/baz</code></td>
+	 * 		<td><code>mywebapp</code></td>
+	 * 		<td><code>http://foo:9080/bar/baz/mywebapp</code></td>
+	 * 	</tr>
+	 * 	<tr>
+	 * 		<td><code>http://foo:9080/bar/baz</code></td>
+	 * 		<td><code>/mywebapp</code></td>
+	 * 		<td><code>/mywebapp</code></td>
+	 * 	</tr>
+	 * 	<tr>
+	 * 		<td><code>http://foo:9080/bar/baz</code></td>
+	 * 		<td><code>http://mywebapp</code></td>
+	 * 		<td><code>http://mywebapp</code></td>
+	 * 	</tr>
+	 * </table>
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_relativeUriBase</jsf>, value)</code>.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_relativeUriBase
+	 */
+	public SerializerBuilder relativeUriBase(String value) {
+		return property(SERIALIZER_relativeUriBase, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  URI base for relative URIs with absolute paths.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.absolutePathUriBase"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <js>""</js>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * Prepended to relative absolute-path URIs during serialization.
+	 * (i.e. URIs starting with <js>'/'</js>).
+	 * (e.g. <js>"/foo/bar"</js>)
+	 *
+	 * <h5 class='section'>Examples:</h5>
+	 * <table class='styled'>
+	 * 	<tr><th>SERIALIZER_absolutePathUriBase</th><th>URI</th><th>Serialized URI</th></tr>
+	 * 	<tr>
+	 * 		<td><code>http://foo:9080/bar/baz</code></td>
+	 * 		<td><code>mywebapp</code></td>
+	 * 		<td><code>mywebapp</code></td>
+	 * 	</tr>
+	 * 	<tr>
+	 * 		<td><code>http://foo:9080/bar/baz</code></td>
+	 * 		<td><code>/mywebapp</code></td>
+	 * 		<td><code>http://foo:9080/bar/baz/mywebapp</code></td>
+	 * 	</tr>
+	 * 	<tr>
+	 * 		<td><code>http://foo:9080/bar/baz</code></td>
+	 * 		<td><code>http://mywebapp</code></td>
+	 * 		<td><code>http://mywebapp</code></td>
+	 * 	</tr>
+	 * </table>
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_absolutePathUriBase</jsf>, value)</code>.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_absolutePathUriBase
+	 */
+	public SerializerBuilder absolutePathUriBase(String value) {
+		return property(SERIALIZER_absolutePathUriBase, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Sort arrays and collections alphabetically.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.sortCollections"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_sortCollections</jsf>, value)</code>.
+	 * 	<li>This introduces a slight performance penalty.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_sortCollections
+	 */
+	public SerializerBuilder sortCollections(boolean value) {
+		return property(SERIALIZER_sortCollections, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Sort maps alphabetically.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Serializer.sortMaps"</js>
+	 * 	<li><b>Data type:</b> <code>Boolean</code>
+	 * 	<li><b>Default:</b> <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>SERIALIZER_sortMaps</jsf>, value)</code>.
+	 * 	<li>This introduces a slight performance penalty.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see SerializerContext#SERIALIZER_sortMaps
+	 */
+	public SerializerBuilder sortMaps(boolean value) {
+		return property(SERIALIZER_sortMaps, value);
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder beansRequireDefaultConstructor(boolean value) {
+		super.beansRequireDefaultConstructor(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder beansRequireSerializable(boolean value) {
+		super.beansRequireSerializable(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder beansRequireSettersForGetters(boolean value) {
+		super.beansRequireSettersForGetters(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder beansRequireSomeProperties(boolean value) {
+		super.beansRequireSomeProperties(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder beanMapPutReturnsOldValue(boolean value) {
+		super.beanMapPutReturnsOldValue(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder beanConstructorVisibility(Visibility value) {
+		super.beanConstructorVisibility(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder beanClassVisibility(Visibility value) {
+		super.beanClassVisibility(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder beanFieldVisibility(Visibility value) {
+		super.beanFieldVisibility(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder methodVisibility(Visibility value) {
+		super.methodVisibility(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder useJavaBeanIntrospector(boolean value) {
+		super.useJavaBeanIntrospector(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder useInterfaceProxies(boolean value) {
+		super.useInterfaceProxies(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder ignoreUnknownBeanProperties(boolean value) {
+		super.ignoreUnknownBeanProperties(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder ignoreUnknownNullBeanProperties(boolean value) {
+		super.ignoreUnknownNullBeanProperties(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder ignorePropertiesWithoutSetters(boolean value) {
+		super.ignorePropertiesWithoutSetters(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder ignoreInvocationExceptionsOnGetters(boolean value) {
+		super.ignoreInvocationExceptionsOnGetters(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder ignoreInvocationExceptionsOnSetters(boolean value) {
+		super.ignoreInvocationExceptionsOnSetters(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder sortProperties(boolean value) {
+		super.sortProperties(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder notBeanPackages(String...values) {
+		super.notBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder notBeanPackages(Collection<String> values) {
+		super.notBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder setNotBeanPackages(String...values) {
+		super.setNotBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder setNotBeanPackages(Collection<String> values) {
+		super.setNotBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder removeNotBeanPackages(String...values) {
+		super.removeNotBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder removeNotBeanPackages(Collection<String> values) {
+		super.removeNotBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder notBeanClasses(Class<?>...values) {
+		super.notBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder notBeanClasses(Collection<Class<?>> values) {
+		super.notBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder setNotBeanClasses(Class<?>...values) {
+		super.setNotBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder setNotBeanClasses(Collection<Class<?>> values) {
+		super.setNotBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder removeNotBeanClasses(Class<?>...values) {
+		super.removeNotBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder removeNotBeanClasses(Collection<Class<?>> values) {
+		super.removeNotBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder beanFilters(Class<?>...values) {
+		super.beanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder beanFilters(Collection<Class<?>> values) {
+		super.beanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder setBeanFilters(Class<?>...values) {
+		super.setBeanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder setBeanFilters(Collection<Class<?>> values) {
+		super.setBeanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder removeBeanFilters(Class<?>...values) {
+		super.removeBeanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder removeBeanFilters(Collection<Class<?>> values) {
+		super.removeBeanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder pojoSwaps(Class<?>...values) {
+		super.pojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder pojoSwaps(Collection<Class<?>> values) {
+		super.pojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder setPojoSwaps(Class<?>...values) {
+		super.setPojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder setPojoSwaps(Collection<Class<?>> values) {
+		super.setPojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder removePojoSwaps(Class<?>...values) {
+		super.removePojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder removePojoSwaps(Collection<Class<?>> values) {
+		super.removePojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder implClasses(Map<Class<?>,Class<?>> values) {
+		super.implClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public <T> CoreObjectBuilder implClass(Class<T> interfaceClass, Class<? extends T> implClass) {
+		super.implClass(interfaceClass, implClass);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder beanDictionary(Class<?>...values) {
+		super.beanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder beanDictionary(Collection<Class<?>> values) {
+		super.beanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder setBeanDictionary(Class<?>...values) {
+		super.setBeanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder setBeanDictionary(Collection<Class<?>> values) {
+		super.setBeanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder removeFromBeanDictionary(Class<?>...values) {
+		super.removeFromBeanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder removeFromBeanDictionary(Collection<Class<?>> values) {
+		super.removeFromBeanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder beanTypePropertyName(String value) {
+		super.beanTypePropertyName(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder defaultParser(Class<?> value) {
+		super.defaultParser(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder locale(Locale value) {
+		super.locale(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder timeZone(TimeZone value) {
+		super.timeZone(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder mediaType(MediaType value) {
+		super.mediaType(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder debug(boolean value) {
+		super.debug(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder property(String name, Object value) {
+		super.property(name, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder properties(Map<String,Object> properties) {
+		super.properties(properties);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder addToProperty(String name, Object value) {
+		super.addToProperty(name, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder putToProperty(String name, Object key, Object value) {
+		super.putToProperty(name, key, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder putToProperty(String name, Object value) {
+		super.putToProperty(name, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder removeFromProperty(String name, Object value) {
+		super.removeFromProperty(name, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder classLoader(ClassLoader classLoader) {
+		super.classLoader(classLoader);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public SerializerBuilder apply(PropertyStore copyFrom) {
+		super.apply(copyFrom);
+		return this;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
index ba93403..f3ea90f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
@@ -332,25 +332,25 @@ public class SerializerContext extends BeanContext {
 	/**
 	 * Constructor.
 	 *
-	 * @param cf The factory that created this context.
+	 * @param ps The property store that created this context.
 	 */
-	public SerializerContext(ContextFactory cf) {
-		super(cf);
-		maxDepth = cf.getProperty(SERIALIZER_maxDepth, int.class, 100);
-		initialDepth = cf.getProperty(SERIALIZER_initialDepth, int.class, 0);
-		detectRecursions = cf.getProperty(SERIALIZER_detectRecursions, boolean.class, false);
-		ignoreRecursions = cf.getProperty(SERIALIZER_ignoreRecursions, boolean.class, false);
-		useWhitespace = cf.getProperty(SERIALIZER_useWhitespace, boolean.class, false);
-		addBeanTypeProperties = cf.getProperty(SERIALIZER_addBeanTypeProperties, boolean.class, true);
-		trimNulls = cf.getProperty(SERIALIZER_trimNullProperties, boolean.class, true);
-		trimEmptyCollections = cf.getProperty(SERIALIZER_trimEmptyCollections, boolean.class, false);
-		trimEmptyMaps = cf.getProperty(SERIALIZER_trimEmptyMaps, boolean.class, false);
-		trimStrings = cf.getProperty(SERIALIZER_trimStrings, boolean.class, false);
-		sortCollections = cf.getProperty(SERIALIZER_sortCollections, boolean.class, false);
-		sortMaps = cf.getProperty(SERIALIZER_sortMaps, boolean.class, false);
-		quoteChar = cf.getProperty(SERIALIZER_quoteChar, String.class, "\"").charAt(0);
-		relativeUriBase = resolveRelativeUriBase(cf.getProperty(SERIALIZER_relativeUriBase, String.class, ""));
-		absolutePathUriBase = resolveAbsolutePathUriBase(cf.getProperty(SERIALIZER_absolutePathUriBase, String.class, ""));
+	public SerializerContext(PropertyStore ps) {
+		super(ps);
+		maxDepth = ps.getProperty(SERIALIZER_maxDepth, int.class, 100);
+		initialDepth = ps.getProperty(SERIALIZER_initialDepth, int.class, 0);
+		detectRecursions = ps.getProperty(SERIALIZER_detectRecursions, boolean.class, false);
+		ignoreRecursions = ps.getProperty(SERIALIZER_ignoreRecursions, boolean.class, false);
+		useWhitespace = ps.getProperty(SERIALIZER_useWhitespace, boolean.class, false);
+		addBeanTypeProperties = ps.getProperty(SERIALIZER_addBeanTypeProperties, boolean.class, true);
+		trimNulls = ps.getProperty(SERIALIZER_trimNullProperties, boolean.class, true);
+		trimEmptyCollections = ps.getProperty(SERIALIZER_trimEmptyCollections, boolean.class, false);
+		trimEmptyMaps = ps.getProperty(SERIALIZER_trimEmptyMaps, boolean.class, false);
+		trimStrings = ps.getProperty(SERIALIZER_trimStrings, boolean.class, false);
+		sortCollections = ps.getProperty(SERIALIZER_sortCollections, boolean.class, false);
+		sortMaps = ps.getProperty(SERIALIZER_sortMaps, boolean.class, false);
+		quoteChar = ps.getProperty(SERIALIZER_quoteChar, String.class, "\"").charAt(0);
+		relativeUriBase = resolveRelativeUriBase(ps.getProperty(SERIALIZER_relativeUriBase, String.class, ""));
+		absolutePathUriBase = resolveAbsolutePathUriBase(ps.getProperty(SERIALIZER_absolutePathUriBase, String.class, ""));
 	}
 
 	private String resolveRelativeUriBase(String s) {