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:14 UTC

[18/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/parser/ParserBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
new file mode 100644
index 0000000..bb397dd
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserBuilder.java
@@ -0,0 +1,571 @@
+// ***************************************************************************************************************************
+// * 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.parser;
+
+import static org.apache.juneau.parser.ParserContext.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.json.*;
+
+/**
+ * Builder class for building instances of parsers.
+ */
+public class ParserBuilder extends CoreObjectBuilder {
+
+	/**
+	 * Constructor, default settings.
+	 */
+	public ParserBuilder() {
+		super();
+	}
+
+	/**
+	 * Constructor.
+	 * @param propertyStore The initial configuration settings for this builder.
+	 */
+	public ParserBuilder(PropertyStore propertyStore) {
+		super(propertyStore);
+	}
+
+	@Override /* CoreObjectBuilder */
+	public Parser build() {
+		return null;
+	}
+
+
+	//--------------------------------------------------------------------------------
+	// Properties
+	//--------------------------------------------------------------------------------
+
+	/**
+	 * <b>Configuration property:</b>  Trim parsed strings.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Parser.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 added to the POJO.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>PARSER_trimStrings</jsf>, value)</code>.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see ParserContext#PARSER_trimStrings
+	 */
+	public ParserBuilder trimStrings(boolean value) {
+		return property(PARSER_trimStrings, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Strict mode.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Parser.strict"</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>, strict mode for the parser is enabled.
+	 * <p>
+	 * Strict mode can mean different things for different parsers.
+	 * <p>
+	 * <table class='styled'>
+	 * 	<tr><th>Parser class</th><th>Strict behavior</th></tr>
+	 * 	<tr>
+	 * 		<td>All reader-based parsers</td>
+	 * 		<td>
+	 * 			When enabled, throws {@link ParseException ParseExceptions} on malformed charset input.
+	 * 			Otherwise, malformed input is ignored.
+	 * 		</td>
+	 * 	</tr>
+	 * 	<tr>
+	 * 		<td>{@link JsonParser}</td>
+	 * 		<td>
+	 * 			When enabled, throws exceptions on the following invalid JSON syntax:
+	 * 			<ul>
+	 * 				<li>Unquoted attributes.
+	 * 				<li>Missing attribute values.
+	 * 				<li>Concatenated strings.
+	 * 				<li>Javascript comments.
+	 * 				<li>Numbers and booleans when Strings are expected.
+	 * 				<li>Numbers valid in Java but not JSON (e.g. octal notation, etc...)
+	 * 			</ul>
+	 * 		</td>
+	 * 	</tr>
+	 * </table>
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>PARSER_strict</jsf>,value)</code>.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see ParserContext#PARSER_strict
+	 */
+	public ParserBuilder strict(boolean value) {
+		return property(PARSER_strict, value);
+	}
+
+	/**
+	 * Shortcut for calling <code>strict(<jk>true</jk>)</code>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public ParserBuilder strict() {
+		return strict(true);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  Input stream charset.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Parser.inputStreamCharset"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <js>"UTF-8"</js>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * The character set to use for converting <code>InputStreams</code> and byte arrays to readers.
+	 * <p>
+	 * Used when passing in input streams and byte arrays to {@link Parser#parse(Object, Class)}.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>PARSER_inputStreamCharset</jsf>, value)</code>.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see ParserContext#PARSER_inputStreamCharset
+	 */
+	public ParserBuilder inputStreamCharset(String value) {
+		return property(PARSER_inputStreamCharset, value);
+	}
+
+	/**
+	 * <b>Configuration property:</b>  File charset.
+	 * <p>
+	 * <ul>
+	 * 	<li><b>Name:</b> <js>"Parser.fileCharset"</js>
+	 * 	<li><b>Data type:</b> <code>String</code>
+	 * 	<li><b>Default:</b> <js>"default"</js>
+	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
+	 * </ul>
+	 * <p>
+	 * The character set to use for reading <code>Files</code> from the file system.
+	 * <p>
+	 * Used when passing in files to {@link Parser#parse(Object, Class)}.
+	 * <p>
+	 * <js>"default"</js> can be used to indicate the JVM default file system charset.
+	 * <p>
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul>
+	 * 	<li>This is equivalent to calling <code>property(<jsf>PARSER_fileCharset</jsf>,value)</code>.
+	 * </ul>
+	 *
+	 * @param value The new value for this property.
+	 * @return This object (for method chaining).
+	 * @see ParserContext#PARSER_fileCharset
+	 */
+	public ParserBuilder fileCharset(String value) {
+		return property(PARSER_fileCharset, value);
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder beansRequireDefaultConstructor(boolean value) {
+		super.beansRequireDefaultConstructor(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder beansRequireSerializable(boolean value) {
+		super.beansRequireSerializable(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder beansRequireSettersForGetters(boolean value) {
+		super.beansRequireSettersForGetters(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder beansRequireSomeProperties(boolean value) {
+		super.beansRequireSomeProperties(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder beanMapPutReturnsOldValue(boolean value) {
+		super.beanMapPutReturnsOldValue(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder beanConstructorVisibility(Visibility value) {
+		super.beanConstructorVisibility(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder beanClassVisibility(Visibility value) {
+		super.beanClassVisibility(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder beanFieldVisibility(Visibility value) {
+		super.beanFieldVisibility(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder methodVisibility(Visibility value) {
+		super.methodVisibility(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder useJavaBeanIntrospector(boolean value) {
+		super.useJavaBeanIntrospector(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder useInterfaceProxies(boolean value) {
+		super.useInterfaceProxies(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder ignoreUnknownBeanProperties(boolean value) {
+		super.ignoreUnknownBeanProperties(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder ignoreUnknownNullBeanProperties(boolean value) {
+		super.ignoreUnknownNullBeanProperties(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder ignorePropertiesWithoutSetters(boolean value) {
+		super.ignorePropertiesWithoutSetters(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder ignoreInvocationExceptionsOnGetters(boolean value) {
+		super.ignoreInvocationExceptionsOnGetters(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder ignoreInvocationExceptionsOnSetters(boolean value) {
+		super.ignoreInvocationExceptionsOnSetters(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder sortProperties(boolean value) {
+		super.sortProperties(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder notBeanPackages(String...values) {
+		super.notBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder notBeanPackages(Collection<String> values) {
+		super.notBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder setNotBeanPackages(String...values) {
+		super.setNotBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder setNotBeanPackages(Collection<String> values) {
+		super.setNotBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder removeNotBeanPackages(String...values) {
+		super.removeNotBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder removeNotBeanPackages(Collection<String> values) {
+		super.removeNotBeanPackages(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder notBeanClasses(Class<?>...values) {
+		super.notBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder notBeanClasses(Collection<Class<?>> values) {
+		super.notBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder setNotBeanClasses(Class<?>...values) {
+		super.setNotBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder setNotBeanClasses(Collection<Class<?>> values) {
+		super.setNotBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder removeNotBeanClasses(Class<?>...values) {
+		super.removeNotBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder removeNotBeanClasses(Collection<Class<?>> values) {
+		super.removeNotBeanClasses(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder beanFilters(Class<?>...values) {
+		super.beanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder beanFilters(Collection<Class<?>> values) {
+		super.beanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder setBeanFilters(Class<?>...values) {
+		super.setBeanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder setBeanFilters(Collection<Class<?>> values) {
+		super.setBeanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder removeBeanFilters(Class<?>...values) {
+		super.removeBeanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder removeBeanFilters(Collection<Class<?>> values) {
+		super.removeBeanFilters(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder pojoSwaps(Class<?>...values) {
+		super.pojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder pojoSwaps(Collection<Class<?>> values) {
+		super.pojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder setPojoSwaps(Class<?>...values) {
+		super.setPojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder setPojoSwaps(Collection<Class<?>> values) {
+		super.setPojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder removePojoSwaps(Class<?>...values) {
+		super.removePojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder removePojoSwaps(Collection<Class<?>> values) {
+		super.removePojoSwaps(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder 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 ParserBuilder beanDictionary(Class<?>...values) {
+		super.beanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder beanDictionary(Collection<Class<?>> values) {
+		super.beanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder setBeanDictionary(Class<?>...values) {
+		super.setBeanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder setBeanDictionary(Collection<Class<?>> values) {
+		super.setBeanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder removeFromBeanDictionary(Class<?>...values) {
+		super.removeFromBeanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder removeFromBeanDictionary(Collection<Class<?>> values) {
+		super.removeFromBeanDictionary(values);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder beanTypePropertyName(String value) {
+		super.beanTypePropertyName(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder defaultParser(Class<?> value) {
+		super.defaultParser(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder locale(Locale value) {
+		super.locale(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder timeZone(TimeZone value) {
+		super.timeZone(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder mediaType(MediaType value) {
+		super.mediaType(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder debug(boolean value) {
+		super.debug(value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder property(String name, Object value) {
+		super.property(name, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder properties(Map<String,Object> properties) {
+		super.properties(properties);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder addToProperty(String name, Object value) {
+		super.addToProperty(name, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder putToProperty(String name, Object key, Object value) {
+		super.putToProperty(name, key, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder putToProperty(String name, Object value) {
+		super.putToProperty(name, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder removeFromProperty(String name, Object value) {
+		super.removeFromProperty(name, value);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder classLoader(ClassLoader classLoader) {
+		super.classLoader(classLoader);
+		return this;
+	}
+
+	@Override /* CoreObjectBuilder */
+	public ParserBuilder 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/parser/ParserContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserContext.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserContext.java
index 1432efb..e0ee73c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserContext.java
@@ -117,14 +117,14 @@ public class ParserContext extends BeanContext {
 	/**
 	 * Constructor.
 	 *
-	 * @param cf The factory that created this context.
+	 * @param ps The property store that created this context.
 	 */
-	public ParserContext(ContextFactory cf) {
-		super(cf);
-		this.trimStrings = cf.getProperty(PARSER_trimStrings, boolean.class, false);
-		this.strict = cf.getProperty(PARSER_strict, boolean.class, false);
-		this.inputStreamCharset = cf.getProperty(PARSER_inputStreamCharset, String.class, "UTF-8");
-		this.fileCharset = cf.getProperty(PARSER_fileCharset, String.class, "default");
+	public ParserContext(PropertyStore ps) {
+		super(ps);
+		this.trimStrings = ps.getProperty(PARSER_trimStrings, boolean.class, false);
+		this.strict = ps.getProperty(PARSER_strict, boolean.class, false);
+		this.inputStreamCharset = ps.getProperty(PARSER_inputStreamCharset, String.class, "UTF-8");
+		this.fileCharset = ps.getProperty(PARSER_fileCharset, String.class, "default");
 	}
 
 	@Override /* Context */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
index f78f733..3dd0dc7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
@@ -12,12 +12,11 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.parser;
 
-import static org.apache.juneau.internal.ArrayUtils.*;
-
 import java.util.*;
 import java.util.concurrent.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
 
 /**
  * Represents a group of {@link Parser Parsers} that can be looked up by media type.
@@ -44,16 +43,17 @@ import org.apache.juneau.*;
  *
  * <h5 class='section'>Example:</h5>
  * <p class='bcode'>
- * 	<jc>// Construct a new parser group</jc>
- * 	ParserGroup g = <jk>new</jk> ParserGroup();
+ * 	<jc>// Construct a new parser group builder</jc>
+ * 	ParserGroupBuilder b = <jk>new</jk> ParserGroupBuilder();
  *
  * 	<jc>// Add some parsers to it</jc>
- * 	g.append(JsonParser.<jk>class</jk>, XmlParser.<jk>class</jk>);
+ * 	b.append(JsonParser.<jk>class</jk>, XmlParser.<jk>class</jk>);
  *
  * 	<jc>// Change settings on parsers simultaneously</jc>
- * 	g.setProperty(BeanContext.<jsf>BEAN_beansRequireSerializable</jsf>, <jk>true</jk>)
- * 		.addPojoSwaps(CalendarSwap.ISO8601DT.<jk>class</jk>)
- * 		.lock();
+ * 	b.property(BeanContext.<jsf>BEAN_beansRequireSerializable</jsf>, <jk>true</jk>)
+ * 		.pojoSwaps(CalendarSwap.ISO8601DT.<jk>class</jk>);
+ *
+ * 	ParserGroup g = b.build();
  *
  * 	<jc>// Find the appropriate parser by Content-Type</jc>
  * 	ReaderParser p = (ReaderParser)g.getParser(<js>"text/json"</js>);
@@ -63,68 +63,26 @@ import org.apache.juneau.*;
  * 	AddressBook addressBook = p.parse(json, AddressBook.<jk>class</jk>);
  * </p>
  */
-public final class ParserGroup extends Lockable {
+public final class ParserGroup {
 
 	// Maps Content-Type headers to matches.
 	private final Map<String,ParserMatch> cache = new ConcurrentHashMap<String,ParserMatch>();
 
-	private final CopyOnWriteArrayList<Parser> parsers = new CopyOnWriteArrayList<Parser>();
-
-	/**
-	 * Adds the specified parser to the beginning of this group.
-	 *
-	 * @param p The parser to add to this group.
-	 * @return This object (for method chaining).
-	 */
-	public ParserGroup append(Parser p) {
-		checkLock();
-		synchronized(this) {
-			cache.clear();
-			parsers.add(0, p);
-		}
-		return this;
-	}
-
-	/**
-	 * Registers the specified parsers with this group.
-	 *
-	 * @param p The parsers to append to this group.
-	 * @return This object (for method chaining).
-	 * @throws Exception Thrown if {@link Parser} could not be constructed.
-	 */
-	public ParserGroup append(Class<? extends Parser>...p) throws Exception {
-		for (Class<? extends Parser> pp : reverse(p))
-			append(pp);
-		return this;
-	}
+	final Parser[] parsers;
+	private final PropertyStore propertyStore;
 
 	/**
-	 * Same as {@link #append(Class[])}, except specify a single class to avoid unchecked compile warnings.
+	 * Constructor.
 	 *
-	 * @param p The parser to append to this group.
-	 * @return This object (for method chaining).
-	 * @throws Exception Thrown if {@link Parser} could not be constructed.
+	 * @param propertyStore The modifiable properties that were used to initialize the parsers.
+	 * A snapshot of these will be made so that we can clone and modify this group.
+	 * @param parsers The parsers defined in this group.
+	 * The order is important because they will be tried in reverse order (e.g.
+	 * 	newer first) in which they will be tried to match against media types.
 	 */
-	public ParserGroup append(Class<? extends Parser> p) throws Exception {
-		try {
-			append(p.newInstance());
-		} catch (NoClassDefFoundError e) {
-			// Ignore if dependent library not found (e.g. Jena).
-			System.err.println(e); // NOT DEBUG
-		}
-		return this;
-	}
-
-	/**
-	 * Adds the parsers in the specified group to this group.
-	 *
-	 * @param g The group containing the parsers to add to this group.
-	 * @return This object (for method chaining).
-	 */
-	public ParserGroup append(ParserGroup g) {
-		for (Parser p : reverse(g.parsers.toArray(new Parser[g.parsers.size()])))
-			append(p);
-		return this;
+	public ParserGroup(PropertyStore propertyStore, Parser[] parsers) {
+		this.propertyStore = PropertyStore.create(propertyStore);
+		this.parsers = ArrayUtils.reverse(parsers);
 	}
 
 	/**
@@ -203,1060 +161,23 @@ public final class ParserGroup extends Lockable {
 		return l;
 	}
 
-
-	//--------------------------------------------------------------------------------
-	// Properties
-	//--------------------------------------------------------------------------------
-
-	/**
-	 * Calls {@link Parser#setTrimStrings(boolean)} on all parsers in this group.
-	 *
-	 * @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 ParserContext#PARSER_trimStrings
-	 */
-	public ParserGroup setTrimStrings(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setTrimStrings(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setStrict(boolean)} on all parsers in this group.
-	 *
-	 * @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 ParserContext#PARSER_strict
-	 */
-	public ParserGroup setStrict(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setStrict(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setInputStreamCharset(String)} on all parsers in this group.
-	 *
-	 * @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 ParserContext#PARSER_inputStreamCharset
-	 */
-	public ParserGroup setInputStreamCharset(String value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setInputStreamCharset(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setFileCharset(String)} on all parsers in this group.
-	 *
-	 * @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 ParserContext#PARSER_fileCharset
-	 */
-	public ParserGroup setFileCharset(String value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setFileCharset(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setBeansRequireDefaultConstructor(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_beansRequireDefaultConstructor
-	 */
-	public ParserGroup setBeansRequireDefaultConstructor(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setBeansRequireDefaultConstructor(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setBeansRequireSerializable(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_beansRequireSerializable
-	 */
-	public ParserGroup setBeansRequireSerializable(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setBeansRequireSerializable(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setBeansRequireSettersForGetters(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_beansRequireSettersForGetters
-	 */
-	public ParserGroup setBeansRequireSettersForGetters(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setBeansRequireSettersForGetters(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setBeansRequireSomeProperties(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_beansRequireSomeProperties
-	 */
-	public ParserGroup setBeansRequireSomeProperties(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setBeansRequireSomeProperties(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setBeanMapPutReturnsOldValue(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_beanMapPutReturnsOldValue
-	 */
-	public ParserGroup setBeanMapPutReturnsOldValue(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setBeanMapPutReturnsOldValue(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setBeanConstructorVisibility(Visibility)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_beanConstructorVisibility
-	 */
-	public ParserGroup setBeanConstructorVisibility(Visibility value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setBeanConstructorVisibility(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setBeanClassVisibility(Visibility)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_beanClassVisibility
-	 */
-	public ParserGroup setBeanClassVisibility(Visibility value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setBeanClassVisibility(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setBeanFieldVisibility(Visibility)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_beanFieldVisibility
-	 */
-	public ParserGroup setBeanFieldVisibility(Visibility value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setBeanFieldVisibility(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setMethodVisibility(Visibility)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_methodVisibility
-	 */
-	public ParserGroup setMethodVisibility(Visibility value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setMethodVisibility(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setUseJavaBeanIntrospector(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_useJavaBeanIntrospector
-	 */
-	public ParserGroup setUseJavaBeanIntrospector(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setUseJavaBeanIntrospector(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setUseInterfaceProxies(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_useInterfaceProxies
-	 */
-	public ParserGroup setUseInterfaceProxies(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setUseInterfaceProxies(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setIgnoreUnknownBeanProperties(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_ignoreUnknownBeanProperties
-	 */
-	public ParserGroup setIgnoreUnknownBeanProperties(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setIgnoreUnknownBeanProperties(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setIgnoreUnknownNullBeanProperties(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_ignoreUnknownNullBeanProperties
-	 */
-	public ParserGroup setIgnoreUnknownNullBeanProperties(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setIgnoreUnknownNullBeanProperties(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setIgnorePropertiesWithoutSetters(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_ignorePropertiesWithoutSetters
-	 */
-	public ParserGroup setIgnorePropertiesWithoutSetters(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setIgnorePropertiesWithoutSetters(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setIgnoreInvocationExceptionsOnGetters(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_ignoreInvocationExceptionsOnGetters
-	 */
-	public ParserGroup setIgnoreInvocationExceptionsOnGetters(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setIgnoreInvocationExceptionsOnGetters(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setIgnoreInvocationExceptionsOnSetters(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_ignoreInvocationExceptionsOnSetters
-	 */
-	public ParserGroup setIgnoreInvocationExceptionsOnSetters(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setIgnoreInvocationExceptionsOnSetters(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setSortProperties(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_sortProperties
-	 */
-	public ParserGroup setSortProperties(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setSortProperties(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setNotBeanPackages(String...)} on all parsers in this group.
-	 *
-	 * @param values The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_notBeanPackages
-	 */
-	public ParserGroup setNotBeanPackages(String...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setNotBeanPackages(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setNotBeanPackages(Collection)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_notBeanPackages
-	 */
-	public ParserGroup setNotBeanPackages(Collection<String> value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setNotBeanPackages(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#addNotBeanPackages(String...)} on all parsers in this group.
-	 *
-	 * @param values The values to remove from this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_notBeanPackages
-	 * @see BeanContext#BEAN_notBeanPackages_remove
-	 */
-	public ParserGroup addNotBeanPackages(String...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.addNotBeanPackages(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#addNotBeanPackages(Collection)} on all parsers in this group.
-	 *
-	 * @param values The values to remove from this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_notBeanPackages
-	 * @see BeanContext#BEAN_notBeanPackages_remove
-	 */
-	public ParserGroup addNotBeanPackages(Collection<String> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.addNotBeanPackages(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#removeNotBeanPackages(String...)} on all parsers in this group.
-	 *
-	 * @param values The values to remove from this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_notBeanPackages
-	 * @see BeanContext#BEAN_notBeanPackages_remove
-	 */
-	public ParserGroup removeNotBeanPackages(String...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.removeNotBeanPackages(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#removeNotBeanPackages(Collection)} on all parsers in this group.
-	 *
-	 * @param values The values to remove from this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_notBeanPackages
-	 * @see BeanContext#BEAN_notBeanPackages_remove
-	 */
-	public ParserGroup removeNotBeanPackages(Collection<String> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.removeNotBeanPackages(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setNotBeanClasses(Class...)} on all parsers in this group.
-	 *
-	 * @param values The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_notBeanClasses
-	 */
-	public ParserGroup setNotBeanClasses(Class<?>...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setNotBeanClasses(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setNotBeanClasses(Collection)} on all parsers in this group.
-	 *
-	 * @param values The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_notBeanPackages
-	 */
-	public ParserGroup setNotBeanClasses(Collection<Class<?>> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setNotBeanClasses(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#addNotBeanClasses(Class...)} on all parsers in this group.
-	 *
-	 * @param values The values to add to this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_notBeanClasses
-	 * @see BeanContext#BEAN_notBeanClasses_add
-	 */
-	public ParserGroup addNotBeanClasses(Class<?>...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.addNotBeanClasses(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#addNotBeanClasses(Collection)} on all parsers in this group.
-	 *
-	 * @param values The values to add to this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_notBeanClasses
-	 * @see BeanContext#BEAN_notBeanClasses_add
-	 */
-	public ParserGroup addNotBeanClasses(Collection<Class<?>> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.addNotBeanClasses(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#removeNotBeanClasses(Class...)} on all parsers in this group.
-	 *
-	 * @param values The values to remove from this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_notBeanClasses
-	 * @see BeanContext#BEAN_notBeanClasses_remove
-	 */
-	public ParserGroup removeNotBeanClasses(Class<?>...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.removeNotBeanClasses(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#removeNotBeanClasses(Collection)} on all parsers in this group.
-	 *
-	 * @param values The values to remove from this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_notBeanClasses
-	 * @see BeanContext#BEAN_notBeanClasses_remove
-	 */
-	public ParserGroup removeNotBeanClasses(Collection<Class<?>> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.removeNotBeanClasses(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setBeanFilters(Class...)} on all parsers in this group.
-	 *
-	 * @param values The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_beanFilters
-	 */
-	public ParserGroup setBeanFilters(Class<?>...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setBeanFilters(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setBeanFilters(Collection)} on all parsers in this group.
-	 *
-	 * @param values The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_beanFilters
-	 */
-	public ParserGroup setBeanFilters(Collection<Class<?>> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setBeanFilters(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#addBeanFilters(Class...)} on all parsers in this group.
-	 *
-	 * @param values The values to add to this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_beanFilters
-	 * @see BeanContext#BEAN_beanFilters_add
-	 */
-	public ParserGroup addBeanFilters(Class<?>...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.addBeanFilters(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#addBeanFilters(Collection)} on all parsers in this group.
-	 *
-	 * @param values The values to add to this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_beanFilters
-	 * @see BeanContext#BEAN_beanFilters_add
-	 */
-	public ParserGroup addBeanFilters(Collection<Class<?>> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.addBeanFilters(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#removeBeanFilters(Class...)} on all parsers in this group.
-	 *
-	 * @param values The values to remove from this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_beanFilters
-	 * @see BeanContext#BEAN_beanFilters_remove
-	 */
-	public ParserGroup removeBeanFilters(Class<?>...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.removeBeanFilters(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#removeBeanFilters(Collection)} on all parsers in this group.
-	 *
-	 * @param values The values to remove from this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_beanFilters
-	 * @see BeanContext#BEAN_beanFilters_remove
-	 */
-	public ParserGroup removeBeanFilters(Collection<Class<?>> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.removeBeanFilters(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setPojoSwaps(Class...)} on all parsers in this group.
-	 *
-	 * @param values The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_pojoSwaps
-	 */
-	public ParserGroup setPojoSwaps(Class<?>...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setPojoSwaps(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setPojoSwaps(Collection)} on all parsers in this group.
-	 *
-	 * @param values The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_pojoSwaps
-	 */
-	public ParserGroup setPojoSwaps(Collection<Class<?>> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setPojoSwaps(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#addPojoSwaps(Class...)} on all parsers in this group.
-	 *
-	 * @param values The values to add to this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_pojoSwaps
-	 * @see BeanContext#BEAN_pojoSwaps_add
-	 */
-	public ParserGroup addPojoSwaps(Class<?>...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.addPojoSwaps(values);
-		return this;
-	}
-
 	/**
-	 * Calls {@link Parser#addPojoSwaps(Collection)} on all parsers in this group.
+	 * Returns a copy of the property store that was used to create the parsers in this group.
+	 * This method returns a new factory each time so is somewhat expensive.
 	 *
-	 * @param values The values to add to this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_pojoSwaps
-	 * @see BeanContext#BEAN_pojoSwaps_add
+	 * @return A new copy of the property store passed in to the constructor.
 	 */
-	public ParserGroup addPojoSwaps(Collection<Class<?>> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.addPojoSwaps(values);
-		return this;
+	public PropertyStore createPropertyStore() {
+		return PropertyStore.create(propertyStore);
 	}
 
 	/**
-	 * Calls {@link Parser#removePojoSwaps(Class...)} on all parsers in this group.
+	 * Returns a copy of the parsers in this group.
+	 * This method returns a new array each time so is somewhat expensive.
 	 *
-	 * @param values The values to remove from this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_pojoSwaps
-	 * @see BeanContext#BEAN_pojoSwaps_remove
+	 * @return A new array containing the parsers in this group.
 	 */
-	public ParserGroup removePojoSwaps(Class<?>...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.removePojoSwaps(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#removePojoSwaps(Collection)} on all parsers in this group.
-	 *
-	 * @param values The values to remove from this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_pojoSwaps
-	 * @see BeanContext#BEAN_pojoSwaps_remove
-	 */
-	public ParserGroup removePojoSwaps(Collection<Class<?>> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.removePojoSwaps(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setImplClasses(Map)} on all parsers in this group.
-	 *
-	 * @param values The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_implClasses
-	 */
-	public ParserGroup setImplClasses(Map<Class<?>,Class<?>> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setImplClasses(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#addImplClass(Class,Class)} on all parsers in this group.
-	 *
-	 * @param interfaceClass The interface class.
-	 * @param implClass The implementation class.
-	 * @param <T> The class type of the interface.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_implClasses
-	 * @see BeanContext#BEAN_implClasses_put
-	 */
-	public <T> ParserGroup addImplClass(Class<T> interfaceClass, Class<? extends T> implClass) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.addImplClass(interfaceClass, implClass);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setBeanDictionary(Class...)} on all parsers in this group.
-	 *
-	 * @param values The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_beanDictionary
-	 */
-	public ParserGroup setBeanDictionary(Class<?>...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setBeanDictionary(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setBeanDictionary(Collection)} on all parsers in this group.
-	 *
-	 * @param values The values to add to this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_beanDictionary
-	 * @see BeanContext#BEAN_beanDictionary_add
-	 */
-	public ParserGroup setBeanDictionary(Collection<Class<?>> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setBeanDictionary(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#addToBeanDictionary(Class...)} on all parsers in this group.
-	 *
-	 * @param values The values to add to this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_beanDictionary
-	 * @see BeanContext#BEAN_beanDictionary_add
-	 */
-	public ParserGroup addToBeanDictionary(Class<?>...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.addToBeanDictionary(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#addToBeanDictionary(Collection)} on all parsers in this group.
-	 *
-	 * @param values The values to add to this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_beanDictionary
-	 * @see BeanContext#BEAN_beanDictionary_add
-	 */
-	public ParserGroup addToBeanDictionary(Collection<Class<?>> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.addToBeanDictionary(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#removeFromBeanDictionary(Class...)} on all parsers in this group.
-	 *
-	 * @param values The values to remove from this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_beanDictionary
-	 * @see BeanContext#BEAN_beanDictionary_remove
-	 */
-	public ParserGroup removeFromBeanDictionary(Class<?>...values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.removeFromBeanDictionary(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#removeFromBeanDictionary(Collection)} on all parsers in this group.
-	 *
-	 * @param values The values to remove from this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see BeanContext#BEAN_beanDictionary
-	 * @see BeanContext#BEAN_beanDictionary_remove
-	 */
-	public ParserGroup removeFromBeanDictionary(Collection<Class<?>> values) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.removeFromBeanDictionary(values);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setBeanTypePropertyName(String)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_beanTypePropertyName
-	 */
-	public ParserGroup setBeanTypePropertyName(String value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setBeanTypePropertyName(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setDefaultParser(Class)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_defaultParser
-	 */
-	public ParserGroup setDefaultParser(Class<?> value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setDefaultParser(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setLocale(Locale)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_locale
-	 */
-	public ParserGroup setLocale(Locale value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setLocale(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setTimeZone(TimeZone)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_timeZone
-	 */
-	public ParserGroup setTimeZone(TimeZone value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setTimeZone(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setMediaType(MediaType)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_mediaType
-	 */
-	public ParserGroup setMediaType(MediaType value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setMediaType(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setDebug(boolean)} on all parsers in this group.
-	 *
-	 * @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 BeanContext#BEAN_debug
-	 */
-	public ParserGroup setDebug(boolean value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setDebug(value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setProperty(String,Object)} on all parsers in this group.
-	 *
-	 * @param name The property name.
-	 * @param value The property value.
-	 * @return This class (for method chaining).
-	 * @throws LockedException If {@link #lock()} has been called on this object or {@link ContextFactory} object.
-	 * @see ContextFactory#setProperty(String, Object)
-	 */
-	public ParserGroup setProperty(String name, Object value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setProperty(name, value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#setProperties(ObjectMap)} on all parsers in this group.
-	 *
-	 * @param properties The properties to set on this class.
-	 * @return This class (for method chaining).
-	 * @throws LockedException If {@link #lock()} has been called on this object.
-	 * @see ContextFactory#setProperties(java.util.Map)
-	 */
-	public ParserGroup setProperties(ObjectMap properties) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setProperties(properties);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#addToProperty(String,Object)} on all parsers in this group.
-	 *
-	 * @param name The property name.
-	 * @param value The new value to add to the SET property.
-	 * @return This object (for method chaining).
-	 * @throws ConfigException If property is not a SET property.
-	 * @throws LockedException If {@link #lock()} has been called on this object.
-	 */
-	public ParserGroup addToProperty(String name, Object value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.addToProperty(name, value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#putToProperty(String,Object,Object)} on all parsers in this group.
-	 *
-	 * @param name The property name.
-	 * @param key The property value map key.
-	 * @param value The property value map value.
-	 * @return This object (for method chaining).
-	 * @throws ConfigException If property is not a MAP property.
-	 * @throws LockedException If {@link #lock()} has been called on this object.
-	 */
-	public ParserGroup putToProperty(String name, Object key, Object value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.putToProperty(name, key, value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#putToProperty(String,Object)} on all parsers in this group.
-	 *
-	 * @param name The property value.
-	 * @param value The property value map value.
-	 * @return This object (for method chaining).
-	 * @throws ConfigException If property is not a MAP property.
-	 * @throws LockedException If {@link #lock()} has been called on this object.
-	 */
-	public ParserGroup putToProperty(String name, Object value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.putToProperty(name, value);
-		return this;
-	}
-
-	/**
-	 * Calls {@link Parser#removeFromProperty(String,Object)} on all parsers in this group.
-	 *
-	 * @param name The property name.
-	 * @param value The property value in the SET property.
-	 * @return This object (for method chaining).
-	 * @throws ConfigException If property is not a SET property.
-	 * @throws LockedException If {@link #lock()} has been called on this object.
-	 */
-	public ParserGroup removeFromProperty(String name, Object value) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.removeFromProperty(name, value);
-		return this;
-	}
-
-
-	//--------------------------------------------------------------------------------
-	// Overridden methods
-	//--------------------------------------------------------------------------------
-
-	/**
-	 * Calls {@link Parser#setClassLoader(ClassLoader)} on all parsers in this group.
-	 *
-	 * @param classLoader The new classloader.
-	 * @throws LockedException If {@link ContextFactory#lock()} was called on this class or the bean context.
-	 * @return This object (for method chaining).
-	 * @see ContextFactory#setClassLoader(ClassLoader)
-	 */
-	public ParserGroup setClassLoader(ClassLoader classLoader) throws LockedException {
-		checkLock();
-		for (Parser p : parsers)
-			p.setClassLoader(classLoader);
-		return this;
-	}
-
-	/**
-	 * Locks this group and all parsers in this group.
-	 */
-	@Override /* Lockable */
-	public ParserGroup lock() {
-		super.lock();
-		for (Parser p : parsers)
-			p.lock();
-		return this;
-	}
-
-	/**
-	 * Clones this group and all parsers in this group.
-	 */
-	@Override /* Lockable */
-	public ParserGroup clone() throws CloneNotSupportedException {
-		ParserGroup g = new ParserGroup();
-
-		List<Parser> l = new ArrayList<Parser>(parsers.size());
-		for (Parser p : parsers)
-			l.add(p.clone());
-
-		g.parsers.addAll(l);
-
-		return g;
+	public Parser[] getParsers() {
+		return ArrayUtils.reverse(parsers);
 	}
 }