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

[29/51] [partial] incubator-juneau git commit: Initial Juno contents from IBM JazzHub repo

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/CoreApi.java
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/CoreApi.java b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/CoreApi.java
new file mode 100755
index 0000000..304bc25
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/CoreApi.java
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2014, 2015. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ *******************************************************************************/
+package com.ibm.juno.core;
+
+/**
+ * Common super class for all core-API serializers, parsers, and serializer/parser groups.
+ *
+ * <h6 class='topic'>Description</h6>
+ * <p>
+ * 	Maintains an inner {@link BeanContextFactory} instance that can be used by serializer and parser subclasses
+ * 		to work with beans in a consistent way.
+ * <p>
+ * 	Provides several duplicate convenience methods from the {@link BeanContextFactory} class to set properties on that class from this class.
+ * <p>
+ * 	Also implements the {@link Lockable} interface to allow for easy locking and cloning.
+ *
+ *
+ * @author James Bognar (jbognar@us.ibm.com)
+ */
+public abstract class CoreApi extends Lockable {
+
+	/** The bean context used by this object. */
+	protected transient BeanContextFactory beanContextFactory = new BeanContextFactory();
+	private BeanContext beanContext;
+
+
+	/**
+	 * Returns the current value of the {@code beanContext} setting.
+	 *
+	 * @return The current setting value.
+	 */
+	public final BeanContext getBeanContext() {
+		if (beanContext == null)
+			beanContext = beanContextFactory.getBeanContext();
+		return beanContext;
+	}
+
+	/**
+	 * Sets a property on this class.
+	 *
+	 * @param property 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.
+	 */
+	public CoreApi setProperty(String property, Object value) throws LockedException {
+		checkLock();
+		beanContextFactory.setProperty(property, value);
+		return this;
+	}
+
+	/**
+	 * Sets multiple properties on this class.
+	 *
+	 * @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.
+	 */
+	public CoreApi setProperties(ObjectMap properties) throws LockedException {
+		checkLock();
+		beanContextFactory.setProperties(properties);
+		return this;
+	}
+
+	/**
+	 * Shortcut for calling <code>getBeanContext().addNotBeanClasses(Class...)</code>.
+	 *
+	 * @see BeanContextFactory#addNotBeanClasses(Class...)
+	 * @param classes The new setting value for the bean context.
+	 * @throws LockedException If {@link BeanContextFactory#lock()} was called on this class or the bean context.
+	 * @return This object (for method chaining).
+	 */
+	public CoreApi addNotBeanClasses(Class<?>...classes) throws LockedException {
+		checkLock();
+		beanContextFactory.addNotBeanClasses(classes);
+		return this;
+	}
+
+	/**
+	 * Shortcut for calling <code>getBeanContext().addFilters(Class...)</code>.
+	 *
+	 * @see BeanContextFactory#addFilters(Class...)
+	 * @param classes The new setting value for the bean context.
+	 * @throws LockedException If {@link BeanContextFactory#lock()} was called on this class or the bean context.
+	 * @return This object (for method chaining).
+	 */
+	public CoreApi addFilters(Class<?>...classes) throws LockedException {
+		checkLock();
+		beanContextFactory.addFilters(classes);
+		return this;
+	}
+
+	/**
+	 * Shortcut for calling <code>getBeanContext().addImplClass(Class, Class)</code>.
+	 *
+	 * @see BeanContextFactory#addImplClass(Class, Class)
+	 * @param interfaceClass The interface class.
+	 * @param implClass The implementation class.
+	 * @throws LockedException If {@link BeanContextFactory#lock()} was called on this class or the bean context.
+	 * @param <T> The class type of the interface.
+	 * @return This object (for method chaining).
+	 */
+	public <T> CoreApi addImplClass(Class<T> interfaceClass, Class<? extends T> implClass) throws LockedException {
+		checkLock();
+		beanContextFactory.addImplClass(interfaceClass, implClass);
+		return this;
+	}
+
+	/**
+	 * Shortcut for calling <code>getBeanContext().setClassLoader(ClassLoader)</code>.
+	 *
+	 * @see BeanContextFactory#setClassLoader(ClassLoader)
+	 * @param classLoader The new classloader.
+	 * @throws LockedException If {@link BeanContextFactory#lock()} was called on this class or the bean context.
+	 * @return This object (for method chaining).
+	 */
+	public CoreApi setClassLoader(ClassLoader classLoader) throws LockedException {
+		checkLock();
+		beanContextFactory.setClassLoader(classLoader);
+		return this;
+	}
+
+	/**
+	 * Shortcut for calling {@link BeanContext#object()}.
+	 *
+	 * @return The reusable {@link ClassMeta} for representing the {@link Object} class.
+	 */
+	public ClassMeta<Object> object() {
+		return getBeanContext().object();
+	}
+
+	/**
+	 * Shortcut for calling  {@link BeanContext#string()}.
+	 *
+	 * @return The reusable {@link ClassMeta} for representing the {@link String} class.
+	 */
+	public ClassMeta<String> string() {
+		return getBeanContext().string();
+	}
+
+	//--------------------------------------------------------------------------------
+	// Overridden methods
+	//--------------------------------------------------------------------------------
+
+	@Override /* Lockable */
+	public void checkLock() {
+		super.checkLock();
+		beanContext = null;
+	}
+
+	@Override /* Lockable */
+	public CoreApi lock() {
+		super.lock();
+		beanContextFactory.lock();
+		beanContext = beanContextFactory.getBeanContext();
+		return this;
+	}
+
+	@Override /* Lockable */
+	public CoreApi clone() throws CloneNotSupportedException{
+		CoreApi c = (CoreApi)super.clone();
+		c.beanContextFactory = beanContextFactory.clone();
+		c.beanContext = null;
+		return c;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Delegate.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Delegate.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Delegate.class
new file mode 100755
index 0000000..1099224
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Delegate.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Delegate.java
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Delegate.java b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Delegate.java
new file mode 100755
index 0000000..27e1b6d
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Delegate.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2014, 2015. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ *******************************************************************************/
+package com.ibm.juno.core;
+
+/**
+ * An object that represents another object, often wrapping that object.
+ * <p>
+ * <b>*** Internal Interface - Not intended for external use ***</b>
+ * <p>
+ * 	For example, {@link BeanMap} is a map representation of a bean.
+ *
+ * @author James Bognar (jbognar@us.ibm.com)
+ * @param <T> The represented class type.
+ */
+public interface Delegate<T> {
+
+	/**
+	 * The {@link ClassMeta} of the class of the represented object.
+	 *
+	 * @return The class type of the represented object.
+	 */
+	public ClassMeta<T> getClassMeta();
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/InvalidDataConversionException.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/InvalidDataConversionException.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/InvalidDataConversionException.class
new file mode 100755
index 0000000..9ad36e2
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/InvalidDataConversionException.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/InvalidDataConversionException.java
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/InvalidDataConversionException.java b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/InvalidDataConversionException.java
new file mode 100755
index 0000000..4353979
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/InvalidDataConversionException.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2011, 2014. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ *******************************************************************************/
+package com.ibm.juno.core;
+
+import java.text.*;
+
+/**
+ * General invalid conversion exception.
+ * <p>
+ * 	Exception that gets thrown if you try to perform an invalid conversion, such as when calling {@code ObjectMap.getInt(...)} on a non-numeric <code>String</code>.
+ *
+ * @author James Bognar (jbognar@us.ibm.com)
+ */
+public final class InvalidDataConversionException extends RuntimeException {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * @param toType Attempting to convert to this class type.
+	 * @param cause The cause.
+	 * @param value The value being converted.
+	 */
+	public InvalidDataConversionException(Object value, Class<?> toType, Exception cause) {
+		super(MessageFormat.format("Invalid data conversion from type ''{0}'' to type ''{1}''.  Value=''{2}''.", value == null ? null : value.getClass().getName(), toType.getName(), value), cause);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Lockable.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Lockable.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Lockable.class
new file mode 100755
index 0000000..0600ad8
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Lockable.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Lockable.java
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Lockable.java b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Lockable.java
new file mode 100755
index 0000000..0b8ecd8
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/Lockable.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2014, 2015. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ *******************************************************************************/
+package com.ibm.juno.core;
+
+/**
+ * Superclass of all classes that have a locked state.
+ * <p>
+ * 	Used to mark bean contexts, serializers, and parsers as read-only so that
+ * 	settings can no longer be modified.
+ * <p>
+ * 	Also keeps track of when the object has been cloned and allows for lazy cloning through
+ * 	the {@link #onUnclone()} method.  The idea behind this is that certain expensive fields don't
+ * 	need to be cloned unless the object is actually being modified.
+ * <p>
+ * 	Calling {@link #lock()} on the object causes it to be put into a read-only state.
+ * 	Once called, subsequent calls to {@link #checkLock()} will cause {@link LockedException LockedExceptions}
+ * 		to be thrown.
+ * <p>
+ * 	As a rule, cloned objects are unlocked by default.
+ *
+ * @author James Bognar (jbognar@us.ibm.com)
+ */
+public abstract class Lockable implements Cloneable {
+
+	private boolean isLocked = false;
+	private boolean isCloned = false;
+
+	/**
+	 * Locks this object so that settings on it cannot be modified.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public Lockable lock() {
+		isLocked = true;
+		return this;
+	}
+
+	/**
+	 * @return <code><jk>true</jk></code> if this object has been locked.
+	 */
+	public boolean isLocked() {
+		return isLocked;
+	}
+
+	/**
+	 * Causes a {@link LockedException} to be thrown if this object has been locked.
+	 * <p>
+	 * 	Also calls {@link #onUnclone()} if this is the first time this method has been called since cloning.
+	 *
+	 * @throws LockedException If {@link #lock()} has been called on this object.
+	 */
+	public void checkLock() throws LockedException {
+		if (isLocked)
+			throw new LockedException();
+		if (isCloned)
+			onUnclone();
+		isCloned = false;
+	}
+
+	/**
+	 * Subclass can override this method to handle lazy-cloning on the first time {@link #checkLock()} is called after
+	 * the object has been cloned.
+	 */
+	public void onUnclone() {}
+
+	/**
+	 * Creates an unlocked clone of this object.
+	 *
+	 * @throws CloneNotSupportedException If class cannot be cloned.
+	 */
+	@Override /* Object */
+	public Lockable clone() throws CloneNotSupportedException {
+		Lockable c = (Lockable)super.clone();
+		c.isLocked = false;
+		c.isCloned = true;
+		return c;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/LockedException.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/LockedException.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/LockedException.class
new file mode 100755
index 0000000..422d647
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/LockedException.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/LockedException.java
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/LockedException.java b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/LockedException.java
new file mode 100755
index 0000000..ce2f31e
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/LockedException.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2014. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ *******************************************************************************/
+package com.ibm.juno.core;
+
+/**
+ * Exception that gets thrown when trying to modify settings on a locked {@link Lockable} object.
+ * <p>
+ * A locked exception indicates a programming error.
+ * Certain objects that are meant for reuse, such as serializers and parsers, provide
+ * the ability to lock the current settings so that they cannot be later changed.
+ * This exception indicates that a setting change was attempted on a previously locked object.
+ *
+ * @author James Bognar (jbognar@us.ibm.com)
+ */
+public final class LockedException extends RuntimeException {
+
+	private static final long serialVersionUID = 1L;
+
+	LockedException() {
+		super("Object is locked and object settings cannot be modified.");
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/MediaRange.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/MediaRange.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/MediaRange.class
new file mode 100755
index 0000000..53d21c1
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/MediaRange.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/MediaRange.java
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/MediaRange.java b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/MediaRange.java
new file mode 100755
index 0000000..c10e07c
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/MediaRange.java
@@ -0,0 +1,312 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2013, 2015. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ *******************************************************************************/
+package com.ibm.juno.core;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * Describes a single type used in content negotiation between an HTTP client and server, as described in
+ * Section 14.1 and 14.7 of RFC2616 (the HTTP/1.1 specification).
+ */
+public final class MediaRange implements Comparable<MediaRange>  {
+
+	private final String type;								// The media type (e.g. "text" for Accept, "utf-8" for Accept-Charset)
+	private final String subType;                   // The media sub-type (e.g. "json" for Accept, not used for Accept-Charset)
+	private final Float qValue;
+	private final Map<String,Set<String>> parameters, extensions;
+
+	/**
+	 * Returns the media type enclosed by this media range.
+	 * <p>
+	 * Examples:
+	 * <ul>
+	 * 	<li><js>"text/html"</js>
+	 * 	<li><js>"text/*"</js>
+	 * 	<li><js>"*\/*"</js>
+	 * </ul>
+	 *
+	 * @return The media type of this media range, lowercased, never <jk>null</jk>.
+	 */
+	public String getMediaType() {
+		return type + "/" + subType;
+	}
+
+	/**
+	 * Return just the type portion of this media range.
+	 *
+	 * @return The type portion of this media range.
+	 */
+	public String getType() {
+		return type;
+	}
+
+	/**
+	 * Returns the <js>'q'</js> (quality) value for this type, as described in Section 3.9 of RFC2616.
+	 * <p>
+	 * The quality value is a float between <code>0.0</code> (unacceptable) and <code>1.0</code> (most acceptable).
+	 * <p>
+	 * If 'q' value doesn't make sense for the context (e.g. this range was extracted from a <js>"content-*"</js> header, as opposed to <js>"accept-*"</js>
+	 * header, its value will always be <js>"1"</js>.
+	 *
+	 * @return The 'q' value for this type, never <jk>null</jk>.
+	 */
+	public Float getQValue() {
+		return qValue;
+	}
+
+	/**
+	 * Returns the optional set of parameters associated to the type as returned by {@link #getMediaType()}.
+	 * <p>
+	 * The parameters are those values as described in standardized MIME syntax.
+	 * An example of such a parameter in string form might be <js>"level=1"</js>.
+	 * <p>
+	 * Values are lowercase and never <jk>null</jk>.
+	 *
+	 * @return The optional list of parameters, never <jk>null</jk>.
+	 */
+	public Map<String,Set<String>> getParameters() {
+		return parameters;
+	}
+
+	/**
+	 * Returns the optional set of custom extensions defined for this type.
+	 * <p>
+	 * Values are lowercase and never <jk>null</jk>.
+	 *
+	 * @return The optional list of extensions, never <jk>null</jk>.
+	 */
+	public Map<String,Set<String>> getExtensions() {
+		return extensions;
+	}
+
+	/**
+	 * Provides a string representation of this media range, suitable for use as an <code>Accept</code> header value.
+	 * <p>
+	 * The literal text generated will be all lowercase.
+	 *
+	 * @return A media range suitable for use as an Accept header value, never <code>null</code>.
+	 */
+	@Override /* Object */
+	public String toString() {
+		StringBuffer sb = new StringBuffer().append(type).append('/').append(subType);
+
+		if (! parameters.isEmpty())
+			for (Entry<String,Set<String>> e : parameters.entrySet()) {
+				String k = e.getKey();
+				for (String v : e.getValue())
+					sb.append(';').append(k).append('=').append(v);
+			}
+
+		// '1' is equivalent to specifying no qValue. If there's no extensions, then we won't include a qValue.
+		if (qValue.floatValue() == 1.0) {
+			if (! extensions.isEmpty()) {
+				sb.append(";q=").append(qValue);
+				for (Entry<String,Set<String>> e : extensions.entrySet()) {
+					String k = e.getKey();
+					for (String v : e.getValue())
+						sb.append(';').append(k).append('=').append(v);
+				}
+			}
+		} else {
+			sb.append(";q=").append(qValue);
+			for (Entry<String,Set<String>> e : extensions.entrySet()) {
+				String k = e.getKey();
+				for (String v : e.getValue())
+					sb.append(';').append(k).append('=').append(v);
+			}
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified object is also a <code>MediaType</code>, and has the same qValue, type, parameters, and extensions.
+	 *
+	 * @return <jk>true</jk> if object is equivalent.
+	 */
+	@Override /* Object */
+	public boolean equals(Object o) {
+
+		if (o == null || !(o instanceof MediaRange))
+			return false;
+
+		if (this == o)
+			return true;
+
+		MediaRange o2 = (MediaRange) o;
+		return qValue.equals(o2.qValue)
+			&& type.equals(o2.type)
+			&& subType.equals(o2.subType)
+			&& parameters.equals(o2.parameters)
+			&& extensions.equals(o2.extensions);
+	}
+
+	/**
+	 * Returns a hash based on this instance's <code>media-type</code>.
+	 *
+	 * @return A hash based on this instance's <code>media-type</code>.
+	 */
+	@Override /* Object */
+	public int hashCode() {
+		return type.hashCode() + subType.hashCode();
+	}
+
+	/**
+	 * Creates a <code>MediaRange</code> object with the referenced values.
+	 *
+	 * @param type The MIME type of this media range (e.g. <js>"application"</js> in <js>"application/json"</js>)
+	 * @param subType The MIME subtype of this media range (e.g. <js>"json"</js> in <js>"application/json"</js>).
+	 * @param parameters The optional parameters for this range.
+	 * @param qValue The quality value of this range.  Must be between <code>0</code> and <code>1.0</code>.
+	 * @param extensions The optional extensions to this quality value.
+	 */
+	private MediaRange(String type, String subType, Map<String,Set<String>> parameters, Float qValue, Map<String,Set<String>> extensions) {
+		this.type = type;
+		this.subType = subType;
+		this.parameters = (parameters == null ? new TreeMap<String,Set<String>>() : parameters);
+		this.extensions = (extensions == null ? new TreeMap<String,Set<String>>() : extensions);
+		this.qValue = qValue;
+	}
+
+	/**
+	 * Parses an <code>Accept</code> header value into an array of media ranges.
+	 * <p>
+	 * The returned media ranges are sorted such that the most acceptable media is available at ordinal position <js>'0'</js>, and the least acceptable at position n-1.
+	 * <p>
+	 * The syntax expected to be found in the referenced <code>value</code> complies with the syntax described in RFC2616, Section 14.1, as described below:
+	 * <p class='bcode'>
+	 * 	Accept         = "Accept" ":"
+	 * 	                  #( media-range [ accept-params ] )
+	 *
+	 * 	media-range    = ( "*\/*"
+	 * 	                  | ( type "/" "*" )
+	 * 	                  | ( type "/" subtype )
+	 * 	                  ) *( ";" parameter )
+	 * 	accept-params  = ";" "q" "=" qvalue *( accept-extension )
+	 * 	accept-extension = ";" token [ "=" ( token | quoted-string ) ]
+	 * </p>
+	 * This method can also be used on other headers such as <code>Accept-Charset</code> and <code>Accept-Encoding</code>...
+	 * <p class='bcode'>
+	 * 	Accept-Charset = "Accept-Charset" ":"
+	 * 	1#( ( charset | "*" )[ ";" "q" "=" qvalue ] )
+	 * </p>
+	 *
+	 * @param value The value to parse.  If <jk>null</jk> or empty, returns a single <code>MediaRange</code> is returned that represents all types.
+	 * @return The media ranges described by the string.
+	 * 	The ranges are sorted such that the most acceptable media is available at ordinal position <js>'0'</js>, and the least acceptable at position n-1.
+	 */
+	public static MediaRange[] parse(String value) {
+
+		Set<MediaRange> ranges = new TreeSet<MediaRange>();
+
+		if (value == null || value.length() == 0)
+			return new MediaRange[]{new MediaRange("*", "*", null, 1f, null)};
+
+		value = value.toLowerCase(Locale.ENGLISH);
+
+		for (String r : value.trim().split("\\s*,\\s*")) {
+			r = r.trim();
+
+			if (r.isEmpty())
+				continue;
+
+			String[] tokens = r.split("\\s*;\\s*");
+
+			tokens[0] = tokens[0].replace(' ', '+');
+
+			// There is at least a type.
+			String[] t = tokens[0].split("/");
+			String type = t[0], subType = (t.length == 1 ? "*" : t[1]);
+
+			// Only the type of the range is specified
+			if (tokens.length == 1) {
+				ranges.add(new MediaRange(type, subType, null, 1f, null));
+				continue;
+			}
+
+			Float qValue = 1f;
+			Map<String,Set<String>> params = new TreeMap<String,Set<String>>();
+			Map<String,Set<String>> exts = new TreeMap<String,Set<String>>();
+
+			boolean isInExtensions = false;
+			for (int i = 1; i < tokens.length; i++) {
+				String[] parm = tokens[i].split("\\s*=\\s*");
+				if (parm.length == 2) {
+					String k = parm[0], v = parm[1];
+					if (isInExtensions) {
+						if (! exts.containsKey(parm[0]))
+							exts.put(parm[0], new TreeSet<String>());
+						exts.get(parm[0]).add(parm[1]);
+					} else if (k.equals("q")) {
+						qValue = new Float(v);
+						isInExtensions = true;
+					} else /*(! isInExtensions)*/ {
+						if (! params.containsKey(parm[0]))
+							params.put(parm[0], new TreeSet<String>());
+						params.get(parm[0]).add(parm[1]);
+					}
+				}
+			}
+
+			ranges.add(new MediaRange(type, subType, params, qValue, exts));
+		}
+
+		return ranges.toArray(new MediaRange[ranges.size()]);
+	}
+
+	/**
+	 * Compares two MediaRanges for equality.
+	 * <p>
+	 * The values are first compared according to <code>qValue</code> values.
+	 * Should those values be equal, the <code>type</code> is then lexicographically compared (case-insensitive) in ascending order,
+	 * 	with the <js>"*"</js> type demoted last in that order.
+	 * <code>MediaRanges</code> with the same type but different sub-types are compared - a more specific subtype is
+	 * 	promoted over the 'wildcard' subtype.
+	 * <code>MediaRanges</code> with the same types but with extensions are promoted over those same types with no extensions.
+	 *
+	 * @param o The range to compare to.  Never <jk>null</jk>.
+	 */
+	@Override /* Comparable */
+	public int compareTo(MediaRange o) {
+
+		// Compare q-values.
+		int qCompare = Float.compare(o.qValue, qValue);
+		if (qCompare != 0)
+			return qCompare;
+
+		// Compare media-types.
+		// Note that '*' comes alphabetically before letters, so just do a reverse-alphabetical comparison.
+		int i = o.type.compareTo(type);
+		if (i == 0)
+			i = o.subType.compareTo(subType);
+		return i;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified <code>MediaRange</code> matches this range.
+	 * <p>
+	 * This implies the types and subtypes are the same as or encompasses the other (e.g. <js>'application/xml'</js> and <js>'application/*'</js>).
+	 *
+	 * @param o The other media rage.
+	 * @return <jk>true</jk> if the media ranges are the same or one encompasses the other.
+	 */
+	public boolean matches(MediaRange o) {
+		if (this == o)
+			return true;
+
+		if (qValue == 0 || o.qValue == 0)
+			return false;
+
+		if (type.equals(o.type) || (type.equals("*")) || (o.type.equals("*")))
+			if (subType.equals(o.subType) || subType.equals("*") || o.subType.equals("*"))
+				return true;
+
+		return false;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList$1.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList$1.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList$1.class
new file mode 100755
index 0000000..cb9fa76
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList$1.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList$2$1.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList$2$1.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList$2$1.class
new file mode 100755
index 0000000..229273b
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList$2$1.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList$2.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList$2.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList$2.class
new file mode 100755
index 0000000..5dba15e
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList$2.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList.class
new file mode 100755
index 0000000..3204758
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList.java
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList.java b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList.java
new file mode 100755
index 0000000..74f00b0
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectList.java
@@ -0,0 +1,447 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2011, 2015. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ *******************************************************************************/
+package com.ibm.juno.core;
+
+import java.io.*;
+import java.util.*;
+
+import com.ibm.juno.core.json.*;
+import com.ibm.juno.core.parser.*;
+import com.ibm.juno.core.serializer.*;
+import com.ibm.juno.core.utils.*;
+
+/**
+ * Java implementation of a JSON array.
+ * <p>
+ * 	An extension of {@link LinkedList}, so all methods available to in that class are also available
+ * 	to this class.
+ * <p>
+ * 	Note that the use of this class is optional.  The serializers will accept any objects that implement
+ * 	the {@link Collection} interface.  But this class provides some useful additional functionality
+ * 	when working with JSON models constructed from Java Collections Framework objects.  For example, a
+ * 	constructor is provided for converting a JSON array string directly into a {@link List}.  It also contains
+ * 	accessor methods for to avoid common typecasting when accessing elements in a list.
+ *
+ * <h6 class='topic'>Examples</h6>
+ * <p class='bcode'>
+ * 	<jc>// Construct an empty List</jc>
+ * 	List l = <jk>new</jk> ObjectList();
+ *
+ * 	<jc>// Construct a list of objects using various methods</jc>
+ * 	l = <jk>new</jk> ObjectList().append(<js>"foo"</js>).append(123).append(<jk>true</jk>);
+ * 	l = <jk>new</jk> ObjectList().append(<js>"foo"</js>, 123, <jk>true</jk>);  <jc>// Equivalent</jc>
+ * 	l = <jk>new</jk> ObjectList(<js>"foo"</js>, 123, <jk>true</jk>);  <jc>// Equivalent</jc>
+ *
+ * 	<jc>// Construct a list of integers from JSON</jc>
+ * 	l = <jk>new</jk> ObjectList(<js>"[1,2,3]"</js>);
+ *
+ * 	<jc>// Construct a list of generic ObjectMap objects from JSON</jc>
+ * 	l = <jk>new</jk> ObjectList(<js>"[{foo:'bar'},{baz:'bing'}]"</js>);
+ *
+ * 	<jc>// Construct a list of integers from XML</jc>
+ * 	String xml = <js>"&lt;array&gt;&lt;number&gt;1&lt;/number&gt;&lt;number&gt;2&lt;/number&gt;&lt;number&gt;3&lt;/number&gt;&lt;/array&gt;"</js>;
+ * 	l = <jk>new</jk> ObjectList(xml, DataFormat.<jsf>XML</jsf>);
+ * 	l = (List)XmlParser.<jsf>DEFAULT</jsf>.parse(xml);  <jc>// Equivalent</jc>
+ * 	l = (List)XmlParser.<jsf>DEFAULT</jsf>.parse(Object.<jk>class</jk>, xml);  <jc>// Equivalent</jc>
+ * 	l = XmlParser.<jsf>DEFAULT</jsf>.parse(List.<jk>class</jk>, xml);  <jc>// Equivalent</jc>
+ * 	l = XmlParser.<jsf>DEFAULT</jsf>.parse(ObjectList.<jk>class</jk>, xml);  <jc>// Equivalent</jc>
+ *
+ * 	<jc>// Construct JSON from ObjectList</jc>
+ * 	l = <jk>new</jk> ObjectList(<js>"[{foo:'bar'},{baz:'bing'}]"</js>);
+ * 	String json = l.toString();  <jc>// Produces "[{foo:'bar'},{baz:'bing'}]"</jc>
+ * 	json = l.toString(JsonSerializer.<jsf>DEFAULT_CONDENSED</jsf>);  <jc>// Equivalent</jc>
+ * 	json = JsonSerializer.<jsf>DEFAULT_CONDENSED</jsf>.serialize(l);  <jc>// Equivalent</jc>
+ *
+ * 	<jc>// Get one of the entries in the list as an Integer</jc>
+ * 	l = <jk>new</jk> ObjectList(<js>"[1,2,3]"</js>);
+ * 	Integer i = l.getInt(1);
+ * 	i = l.get(Integer.<jk>class</jk>, 1);  <jc>// Equivalent</jc>
+ *
+ * 	<jc>// Get one of the entries in the list as an Float</jc>
+ * 	l = <jk>new</jk> ObjectList(<js>"[1,2,3]"</js>);
+ * 	Float f = l.getFloat(1); <jc>// Returns 2f </jc>
+ * 	f = l.get(Float.<jk>class</jk>, 1);  <jc>// Equivalent</jc>
+ *
+ * 	<jc>// Same as above, except converted to a String</jc>
+ * 	l = <jk>new</jk> ObjectList(<js>"[1,2,3]"</js>);
+ * 	String s = l.getString(1); <jc>// Returns "2" </jc>
+ * 	s = l.get(String.<jk>class</jk>, 1);  <jc>// Equivalent</jc>
+ *
+ * 	<jc>// Get one of the entries in the list as a bean (converted to a bean if it isn't already one)</jc>
+ * 	l = <jk>new</jk> ObjectList(<js>"[{name:'John Smith',age:45}]"</js>);
+ * 	Person p = l.get(Person.<jk>class</jk>, 0);
+ *
+ * 	<jc>// Iterate over a list of beans using the elements() method</jc>
+ * 	ObjectList ObjectList = <jk>new</jk> ObjectList(<js>"[{name:'John Smith',age:45}]"</js>);
+ * 	<jk>for</jk> (Person p : ObjectList.elements(Person.<jk>class</jk>) {
+ * 		<jc>// Do something with p</jc>
+ * 	}
+ * </p>
+ *
+ * @author James Bognar (jbognar@us.ibm.com)
+ */
+public class ObjectList extends LinkedList<Object> {
+	private static final long serialVersionUID = 1L;
+
+	private transient BeanContext beanContext = BeanContext.DEFAULT;
+
+	/**
+	 * An empty read-only ObjectList.
+	 */
+	public static final ObjectList EMPTY_LIST = new ObjectList() {
+		private static final long serialVersionUID = 1L;
+
+		@Override /* List */
+		public void add(int location, Object object) {
+			throw new UnsupportedOperationException();
+		}
+
+		@Override /* List */
+		public ListIterator<Object> listIterator(final int location) {
+			return Collections.emptyList().listIterator(location);
+		}
+
+		@Override /* List */
+		public Object remove(int location) {
+			throw new UnsupportedOperationException();
+		}
+
+		@Override /* List */
+		public Object set(int location, Object object) {
+			throw new UnsupportedOperationException();
+		}
+
+		@Override /* List */
+		public List<Object> subList(int start, int end) {
+			return Collections.emptyList().subList(start, end);
+		}
+	};
+
+	/**
+	 * Construct a JSON array directly from text using the specified parser.
+	 *
+	 * @param s The string being parsed.
+	 * @param p The parser to use to parse the input.
+	 * @throws ParseException If the input contains a syntax error or is malformed.
+	 */
+	public ObjectList(CharSequence s, ReaderParser p) throws ParseException {
+		this(p == null ? BeanContext.DEFAULT : p.getBeanContext());
+		try {
+			if (p == null)
+				p = JsonParser.DEFAULT;
+			if (s != null)
+				p.parseIntoCollection(new CharSequenceReader(s), s.length(), this, beanContext.object());
+		} catch (IOException e) {
+			throw new ParseException(e);
+		}
+	}
+
+	/**
+	 * Shortcut for <code><jk>new</jk> ObjectList(String,JsonParser.<jsf>DEFAULT</jsf>);</code>
+	 *
+	 * @param s The string being parsed.
+	 * @throws ParseException If the input contains a syntax error or is malformed.
+	 */
+	public ObjectList(CharSequence s) throws ParseException {
+		this(s, null);
+	}
+
+	/**
+	 * Construct a JSON array directly from a reader using the specified parser.
+	 *
+	 * @param r The reader to read from.  Will automatically be wrapped in a {@link BufferedReader} if it isn't already a BufferedReader.
+	 * @param p The parser to use to parse the input.
+	 * @throws ParseException If the input contains a syntax error or is malformed.
+	 * @throws IOException If a problem occurred trying to read from the reader.
+	 */
+	public ObjectList(Reader r, ReaderParser p) throws ParseException, IOException {
+		parseReader(r, p);
+	}
+
+	private void parseReader(Reader r, ReaderParser p) throws IOException, ParseException {
+		if (p == null)
+			p = JsonParser.DEFAULT;
+		p.parseIntoCollection(r, -1, this, beanContext.object());
+	}
+
+	/**
+	 * Construct an empty JSON array. (i.e. an empty {@link LinkedList}).
+	 */
+	public ObjectList() {
+		this(BeanContext.DEFAULT);
+	}
+
+	/**
+	 * Construct an empty JSON array with the specified bean context. (i.e. an empty {@link LinkedList}).
+	 *
+	 * @param beanContext The bean context to associate with this object list for creating beans.
+	 */
+	public ObjectList(BeanContext beanContext) {
+		super();
+		this.beanContext = beanContext;
+	}
+
+	/**
+	 * Construct a JSON array and fill it with the specified objects.
+	 *
+	 * @param o A list of objects to add to this list.
+	 */
+	public ObjectList(Object... o) {
+		super(Arrays.asList(o));
+	}
+
+	/**
+	 * Construct a JSON array and fill it with the specified collection of objects.
+	 *
+	 * @param c A list of objects to add to this list.
+	 */
+	public ObjectList(Collection<?> c) {
+		super(c);
+	}
+
+	/**
+	 * Override the default bean context used for converting POJOs.
+	 * <p>
+	 * Default is {@link BeanContext#DEFAULT}, which is sufficient in most cases.
+	 * <p>
+	 * Useful if you're serializing/parsing beans with filters defined.
+	 *
+	 * @param beanContext The new bean context.
+	 * @return This object (for method chaining).
+	 */
+	public ObjectList setBeanContext(BeanContext beanContext) {
+		this.beanContext = beanContext;
+		return this;
+	}
+
+	/**
+	 * Convenience method for adding multiple objects to this list.
+	 * @param o The objects to add to the list.
+	 * @return This object (for method chaining).
+	 */
+	public ObjectList append(Object...o) {
+		for (Object o2 : o)
+			add(o2);
+		return this;
+	}
+
+	/**
+	 * Get the entry at the specified index, converted to the specified type (if possible).
+	 * <p>
+	 * 	See {@link BeanContext#convertToType(Object, ClassMeta)} for the list of valid data conversions.
+	 *
+	 * @param type The type of object to convert the entry to.
+	 * @param index The index into this list.
+	 * @param <T> The type of object to convert the entry to.
+	 * @return The converted entry.
+	 */
+	public <T> T get(Class<T> type, int index) {
+		return beanContext.convertToType(get(index), type);
+	}
+
+	/**
+	 * Shortcut for calling <code>get(String.<jk>class</jk>, index)</code>.
+	 *
+	 * @param index The index.
+	 * @return The converted value.
+	 */
+	public String getString(int index) {
+		return get(String.class, index);
+	}
+
+	/**
+	 * Shortcut for calling <code>get(Integer.<jk>class</jk>, index)</code>.
+	 *
+	 * @param index The index.
+	 * @return The converted value.
+	 * @throws InvalidDataConversionException If value cannot be converted.
+	 */
+	public Integer getInt(int index) {
+		return get(Integer.class, index);
+	}
+
+	/**
+	 * Shortcut for calling <code>get(Boolean.<jk>class</jk>, index)</code>.
+	 *
+	 * @param index The index.
+	 * @return The converted value.
+	 * @throws InvalidDataConversionException If value cannot be converted.
+	 */
+	public Boolean getBoolean(int index) {
+		return get(Boolean.class, index);
+	}
+
+	/**
+	 * Shortcut for calling <code>get(Long.<jk>class</jk>, index)</code>.
+	 *
+	 * @param index The index.
+	 * @return The converted value.
+	 * @throws InvalidDataConversionException If value cannot be converted.
+	 */
+	public Long getLong(int index) {
+		return get(Long.class, index);
+	}
+
+	/**
+	 * Shortcut for calling <code>get(Map.<jk>class</jk>, index)</code>.
+	 *
+	 * @param index The index.
+	 * @return The converted value.
+	 * @throws InvalidDataConversionException If value cannot be converted.
+	 */
+	public Map<?,?> getMap(int index) {
+		return get(Map.class, index);
+	}
+
+	/**
+	 * Shortcut for calling <code>get(List.<jk>class</jk>, index)</code>.
+	 *
+	 * @param index The index.
+	 * @return The converted value.
+	 * @throws InvalidDataConversionException If value cannot be converted.
+	 */
+	public List<?> getList(int index) {
+		return get(List.class, index);
+	}
+
+	/**
+	 * Shortcut for calling <code>get(ObjectMap.<jk>class</jk>, index)</code>.
+	 *
+	 * @param index The index.
+	 * @return The converted value.
+	 * @throws InvalidDataConversionException If value cannot be converted.
+	 */
+	public ObjectMap getObjectMap(int index) {
+		return get(ObjectMap.class, index);
+	}
+
+	/**
+	 * Shortcut for calling <code>get(ObjectList.<jk>class</jk>, index)</code>.
+	 *
+	 * @param index The index.
+	 * @return The converted value.
+	 * @throws InvalidDataConversionException If value cannot be converted.
+	 */
+	public ObjectList getObjectList(int index) {
+		return get(ObjectList.class, index);
+	}
+
+	/**
+	 * Creates an {@link Iterable} with elements of the specified child type.
+	 * <p>
+	 * Attempts to convert the child objects to the correct type if they aren't already the correct type.
+	 * <p>
+	 * The <code>next()</code> method on the returned iterator may throw a {@link InvalidDataConversionException} if
+	 * 	the next element cannot be converted to the specified type.
+	 * <p>
+	 * See {@link BeanContext#convertToType(Object, ClassMeta)} for a description of valid conversions.
+	 *
+	 * <dl>
+	 * 	<dt>Example:</dt>
+	 * 	<dd>
+	 * <p class='bcode'>
+	 * 	<jc>// Iterate over a list of ObjectMaps.</jc>
+	 * 	ObjectList l = <jk>new</jk> ObjectList(<js>"[{foo:'bar'},{baz:123}]"</js>);
+	 * 	for (ObjectMap m : l.elements(ObjectMap.<jk>class</jk>)) {
+	 * 		<jc>// Do something with m.</jc>
+	 * 	}
+	 *
+	 * 	<jc>// Iterate over a list of ints.</jc>
+	 * 	ObjectList l = <jk>new</jk> ObjectList(<js>"[1,2,3]"</js>);
+	 * 	for (Integer i : l.elements(Integer.<jk>class</jk>)) {
+	 * 		<jc>// Do something with i.</jc>
+	 * 	}
+	 *
+	 * 	<jc>// Iterate over a list of beans.</jc>
+	 * 	<jc>// Automatically converts to beans.</jc>
+	 * 	ObjectList l = <jk>new</jk> ObjectList(<js>"[{name:'John Smith',age:45}]"</js>);
+	 * 	for (Person p : l.elements(Person.<jk>class</jk>)) {
+	 * 		<jc>// Do something with p.</jc>
+	 * 	}
+	 * </p>
+	 * 	</dd>
+	 * </dl>
+	 *
+	 * @param <E> The child object type.
+	 * @param childType The child object type.
+	 * @return A new <code>Iterable</code> object over this list.
+	 */
+	public <E> Iterable<E> elements(final Class<E> childType) {
+		final Iterator<?> i = iterator();
+		return new Iterable<E>() {
+
+			@Override /* Iterable */
+			public Iterator<E> iterator() {
+				return new Iterator<E>() {
+
+					@Override /* Iterator */
+					public boolean hasNext() {
+						return i.hasNext();
+					}
+
+					@Override /* Iterator */
+					public E next() {
+						return beanContext.convertToType(i.next(), childType);
+					}
+
+					@Override /* Iterator */
+					public void remove() {
+						i.remove();
+					}
+
+				};
+			}
+		};
+	}
+
+	/**
+	 * Returns the {@link ClassMeta} of the class of the object at the specified index.
+	 *
+	 * @param index An index into this list, zero-based.
+	 * @return The data type of the object at the specified index, or <jk>null</jk> if the value is null.
+	 */
+	public ClassMeta<?> getClassMeta(int index) {
+		return beanContext.getClassMetaForObject(get(index));
+	}
+
+	/**
+	 * Serialize this array to a string using the specified serializer.
+	 *
+	 * @param serializer The serializer to use to convert this object to a string.
+	 * @return This object as a serialized string.
+	 * @throws SerializeException If a problem occurred trying to convert the output.
+	 */
+	public String toString(WriterSerializer serializer) throws SerializeException {
+		return serializer.serialize(this);
+	}
+
+	/**
+	 * Serialize this array to JSON using the {@link JsonSerializer#DEFAULT} serializer.
+	 */
+	@Override /* Object */
+	public String toString() {
+		try {
+			return this.toString(JsonSerializer.DEFAULT_LAX);
+		} catch (SerializeException e) {
+			return e.getLocalizedMessage();
+		}
+	}
+
+	/**
+	 * Convenience method for serializing this ObjectList to the specified Writer using
+	 * the JsonSerializer.DEFAULT serializer.
+	 *
+	 * @param w The writer to send the serialized contents of this object.
+	 * @throws IOException If a problem occurred trying to write to the writer.
+	 * @throws SerializeException If a problem occurred trying to convert the output.
+	 */
+	public void serializeTo(Writer w) throws IOException, SerializeException {
+		JsonSerializer.DEFAULT.serialize(this);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$1.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$1.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$1.class
new file mode 100755
index 0000000..a58f23d
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$1.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$2$1$1.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$2$1$1.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$2$1$1.class
new file mode 100755
index 0000000..57b81a7
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$2$1$1.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$2$1.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$2$1.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$2$1.class
new file mode 100755
index 0000000..0ccaec1
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$2$1.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$2.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$2.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$2.class
new file mode 100755
index 0000000..777a312
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap$2.class differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap.class
new file mode 100755
index 0000000..5ed2e03
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/ObjectMap.class differ