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:07:52 UTC

[03/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/xml/XmlParserContext.java
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlParserContext.java b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlParserContext.java
new file mode 100755
index 0000000..322cdc8
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlParserContext.java
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * 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.xml;
+
+import static com.ibm.juno.core.xml.XmlParserProperties.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+
+import javax.xml.stream.*;
+import javax.xml.stream.util.*;
+
+import com.ibm.juno.core.*;
+import com.ibm.juno.core.parser.*;
+import com.ibm.juno.core.utils.*;
+
+/**
+ * Context object that lives for the duration of a single parsing of {@link XmlParser}.
+ * <p>
+ *
+ * @author James Bognar (jbognar@us.ibm.com)
+ */
+public final class XmlParserContext extends ParserContext {
+
+	/**
+	 * XMLSchema namespace URI ({@link String}, default=<js>"http://www.w3.org/2001/XMLSchema-instance"</js>).
+	 * <p>
+	 * The XMLSchema namespace.
+	 */
+	private final String xsiNs;
+	private final boolean
+		trimWhitespace,
+		validating,
+		coalescing,
+		replaceEntityReferences,
+		preserveRootElement;
+	private final XMLReporter reporter;
+	private final XMLResolver resolver;
+	private final XMLEventAllocator eventAllocator;
+	private XMLStreamReader xmlStreamReader;
+
+
+	/**
+	 * Create a new parser context with the specified options.
+	 *
+	 * @param beanContext The bean context being used.
+	 * @param pp The default parser properties.
+	 * @param xpp The default XML parser properties.
+	 * @param op The override properties.
+	 * @param javaMethod The java method that called this parser, usually the method in a REST servlet.
+	 * @param outer The outer object for instantiating top-level non-static inner classes.
+	 */
+	public XmlParserContext(BeanContext beanContext, ParserProperties pp, XmlParserProperties xpp, ObjectMap op, Method javaMethod, Object outer) {
+		super(beanContext, pp, op, javaMethod, outer);
+		if (op == null || op.isEmpty()) {
+			xsiNs = xpp.getXsiNs();
+			trimWhitespace = xpp.isTrimWhitespace();
+			validating = xpp.isValidating();
+			coalescing = xpp.isCoalescing();
+			replaceEntityReferences = xpp.isReplaceEntityReferences();
+			reporter = xpp.getReporter();
+			resolver = xpp.getResolver();
+			eventAllocator = xpp.getEventAllocator();
+			preserveRootElement = xpp.isPreserveRootElement();
+		} else {
+			xsiNs = op.getString(XML_xsiNs, xpp.getXsiNs());
+			trimWhitespace = op.getBoolean(XML_trimWhitespace, xpp.isTrimWhitespace());
+			validating = op.getBoolean(XML_validating, xpp.isValidating());
+			coalescing = op.getBoolean(XML_coalescing, xpp.isCoalescing());
+			replaceEntityReferences = op.getBoolean(XML_replaceEntityReferences, xpp.isReplaceEntityReferences());
+			reporter = (XMLReporter)op.get(XML_reporter, xpp.getReporter());
+			resolver = (XMLResolver)op.get(XML_resolver, xpp.getResolver());
+			eventAllocator = (XMLEventAllocator)op.get(XML_eventAllocator, xpp.getEventAllocator());
+			preserveRootElement = op.getBoolean(XML_preserveRootElement, xpp.isPreserveRootElement());
+		}
+	}
+
+	/**
+	 * Returns the {@link XmlParserProperties#XML_xsiNs} setting in this context.
+	 *
+	 * @return The {@link XmlParserProperties#XML_xsiNs} setting in this context.
+	 */
+	public String getXsiNs() {
+		return xsiNs;
+	}
+
+	/**
+	 * Returns the {@link XmlParserProperties#XML_trimWhitespace} setting in this context.
+	 *
+	 * @return The {@link XmlParserProperties#XML_trimWhitespace} setting in this context.
+	 */
+	public boolean isTrimWhitespace() {
+		return trimWhitespace;
+	}
+
+	/**
+	 * Returns the {@link XmlParserProperties#XML_preserveRootElement} setting in this context.
+	 *
+	 * @return The {@link XmlParserProperties#XML_preserveRootElement} setting in this context.
+	 */
+	public boolean isPreserveRootElement() {
+		return preserveRootElement;
+	}
+
+	/**
+	 * Returns the {@link XmlParserProperties#XML_validating} setting in this context.
+	 *
+	 * @return The {@link XmlParserProperties#XML_validating} setting in this context.
+	 */
+	public boolean isValidating() {
+		return validating;
+	}
+
+	/**
+	 * Returns the {@link XmlParserProperties#XML_coalescing} setting in this context.
+	 *
+	 * @return The {@link XmlParserProperties#XML_coalescing} setting in this context.
+	 */
+	public boolean isCoalescing() {
+		return coalescing;
+	}
+
+	/**
+	 * Returns the {@link XmlParserProperties#XML_replaceEntityReferences} setting in this context.
+	 *
+	 * @return The {@link XmlParserProperties#XML_replaceEntityReferences} setting in this context.
+	 */
+	public boolean isReplaceEntityReferences() {
+		return replaceEntityReferences;
+	}
+
+	/**
+	 * Returns the {@link XmlParserProperties#XML_reporter} setting in this context.
+	 *
+	 * @return The {@link XmlParserProperties#XML_reporter} setting in this context.
+	 */
+	public XMLReporter getReporter() {
+		return reporter;
+	}
+
+	/**
+	 * Returns the {@link XmlParserProperties#XML_resolver} setting in this context.
+	 *
+	 * @return The {@link XmlParserProperties#XML_resolver} setting in this context.
+	 */
+	public XMLResolver getResolver() {
+		return resolver;
+	}
+
+	/**
+	 * Returns the {@link XmlParserProperties#XML_eventAllocator} setting in this context.
+	 *
+	 * @return The {@link XmlParserProperties#XML_eventAllocator} setting in this context.
+	 */
+	public XMLEventAllocator getEventAllocator() {
+		return eventAllocator;
+	}
+
+
+	/**
+	 * Wrap the specified reader in a STAX reader based on settings in this context.
+	 *
+	 * @param r The input reader.
+	 * @param estimatedSize The estimated size of the contents of the reader.
+	 * @return The new STAX reader.
+	 * @throws ParseException If problem occurred trying to create reader.
+	 */
+	public XMLStreamReader getReader(Reader r, int estimatedSize) throws ParseException {
+		try {
+			r = IOUtils.getBufferedReader(r, estimatedSize);
+			XMLInputFactory factory = XMLInputFactory.newInstance();
+			factory.setProperty(XMLInputFactory.IS_VALIDATING, validating);
+			factory.setProperty(XMLInputFactory.IS_COALESCING, coalescing);
+			factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, replaceEntityReferences);
+			if (factory.isPropertySupported(XMLInputFactory.REPORTER) && reporter != null)
+				factory.setProperty(XMLInputFactory.REPORTER, reporter);
+			if (factory.isPropertySupported(XMLInputFactory.RESOLVER) && resolver != null)
+				factory.setProperty(XMLInputFactory.RESOLVER, resolver);
+			if (factory.isPropertySupported(XMLInputFactory.ALLOCATOR) && eventAllocator != null)
+				factory.setProperty(XMLInputFactory.ALLOCATOR, eventAllocator);
+			xmlStreamReader = factory.createXMLStreamReader(r);
+			xmlStreamReader.nextTag();
+		} catch (Error e) {
+			close();
+			throw new ParseException(e.getLocalizedMessage());
+		} catch (XMLStreamException e) {
+			close();
+			throw new ParseException(e);
+		}
+
+		return xmlStreamReader;
+	}
+
+	/**
+	 * Silently closes the XML stream returned by the call to {@link #getReader(Reader, int)}.
+	 */
+	@Override /* ParserContext */
+	public void close() throws ParseException {
+		super.close();
+		try {
+			if (xmlStreamReader != null)
+				xmlStreamReader.close();
+		} catch (XMLStreamException e) {
+			// Ignore.
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlParserProperties.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlParserProperties.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlParserProperties.class
new file mode 100755
index 0000000..c5e5e4f
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlParserProperties.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/xml/XmlParserProperties.java
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlParserProperties.java b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlParserProperties.java
new file mode 100755
index 0000000..23b9503
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlParserProperties.java
@@ -0,0 +1,244 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * � 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.xml;
+
+import javax.xml.stream.*;
+import javax.xml.stream.util.*;
+
+import com.ibm.juno.core.*;
+import com.ibm.juno.core.parser.*;
+
+/**
+ * Configurable properties on the {@link XmlParser} class.
+ * <p>
+ * 	Use the {@link XmlParser#setProperty(String, Object)} method to set property values.
+ * <p>
+ * 	In addition to these properties, the following properties are also applicable for {@link XmlParser}.
+ * <ul>
+ * 	<li>{@link ParserProperties}
+ * 	<li>{@link BeanContextProperties}
+ * </ul>
+ *
+ * @author James Bognar (jbognar@us.ibm.com)
+ */
+public final class XmlParserProperties implements Cloneable {
+
+	/**
+	 * XMLSchema-instance namespace URI ({@link String}, default=<js>"http://www.w3.org/2001/XMLSchema-instance"</js>).
+	 * <p>
+	 * The XMLSchema namespace.
+	 */
+	public static final String XML_xsiNs = "XmlParser.xsiNs";
+
+	/**
+	 * Trim whitespace from text elements ({@link Boolean}, default=<jk>false</jk>).
+	 * <p>
+	 * If <jk>true</jk>, whitespace in text elements will be automatically trimmed.
+	 */
+	public static final String XML_trimWhitespace = "XmlParser.trimWhitespace";
+
+	/**
+	 * Set validating mode ({@link Boolean}, default=<jk>false</jk>).
+	 * <p>
+	 * If <jk>true</jk>, XML document will be validated.
+	 * See {@link XMLInputFactory#IS_VALIDATING} for more info.
+	 */
+	public static final String XML_validating = "XmlParser.validating";
+
+	/**
+	 * Set coalescing mode ({@link Boolean}, default=<jk>false</jk>).
+	 * <p>
+	 * If <jk>true</jk>, XML text elements will be coalesced.
+	 * See {@link XMLInputFactory#IS_COALESCING} for more info.
+	 */
+	public static final String XML_coalescing = "XmlParser.coalescing";
+
+	/**
+	 * Replace entity references ({@link Boolean}, default=<jk>true</jk>).
+	 * <p>
+	 * If <jk>true</jk>, entity references will be replace during parsing.
+	 * See {@link XMLInputFactory#IS_REPLACING_ENTITY_REFERENCES} for more info.
+	 */
+	public static final String XML_replaceEntityReferences = "XmlParser.replaceEntityReferences";
+
+	/**
+	 * XML reporter ({@link XMLReporter}, default=<jk>null</jk>).
+	 * <p>
+	 * Associates an {@link XMLReporter} with this parser.
+	 * <p>
+	 * Note:  Reporters are not copied to new parsers during a clone.
+	 */
+	public static final String XML_reporter = "XmlParser.reporter";
+
+	/**
+	 * XML resolver ({@link XMLResolver}, default=<jk>null</jk>).
+	 * <p>
+	 * Associates an {@link XMLResolver} with this parser.
+	 */
+	public static final String XML_resolver = "XmlParser.resolver";
+
+	/**
+	 * XML event allocator. ({@link XMLEventAllocator}, default=<jk>false</jk>).
+	 * <p>
+	 * Associates an {@link XMLEventAllocator} with this parser.
+	 */
+	public static final String XML_eventAllocator = "XmlParser.eventAllocator";
+
+	/**
+	 * Preserve root element during generalized parsing ({@link Boolean}, default=<jk>false</jk>).
+	 * <p>
+	 * If <jk>true</jk>, when parsing into a generic {@link ObjectMap}, the map will
+	 * 	contain a single entry whose key is the root element name.
+	 *
+	 * Example:
+	 *	<table class='styled'>
+	 *		<tr>
+	 *			<td>XML</td>
+	 *			<td>ObjectMap.toString(), preserveRootElement==false</td>
+	 *			<td>ObjectMap.toString(), preserveRootElement==true</td>
+	 *		</tr>
+	 *		<tr>
+	 *			<td><code><xt>&lt;root&gt;&lt;a&gt;</xt>foobar<xt>&lt;/a&gt;&lt;/root&gt;</xt><code></td>
+	 *			<td><code>{ a:<js>'foobar'</js> }</code></td>
+	 *			<td><code>{ root: { a:<js>'foobar'</js> }}</code></td>
+	 *		</tr>
+	 *	</table>
+	 *
+	 */
+	public static final String XML_preserveRootElement = "XmlParser.preserveRootElement";
+
+	private String xsiNs = "http://www.w3.org/2001/XMLSchema-instance";
+	private boolean
+		trimWhitespace = false,
+		validating = false,
+		coalescing = false,
+		replaceEntityReferences = true,
+		preserveRootElement = false;
+	private XMLReporter reporter;
+	private XMLResolver resolver;
+	private XMLEventAllocator eventAllocator;
+
+	/**
+	 * Sets the specified property value.
+	 * @param property The property name.
+	 * @param value The property value.
+	 * @return <jk>true</jk> if property name was valid and property was set.
+	 * @throws LockedException If bean context is locked.
+	 */
+	protected boolean setProperty(String property, Object value) throws LockedException {
+		BeanContext bc = BeanContext.DEFAULT;
+		if (property.equals(XML_trimWhitespace))
+			trimWhitespace = bc.convertToType(value, Boolean.class);
+		else if (property.equals(XML_validating))
+			validating = bc.convertToType(value, Boolean.class);
+		else if (property.equals(XML_coalescing))
+			coalescing = bc.convertToType(value, Boolean.class);
+		else if (property.equals(XML_replaceEntityReferences))
+			replaceEntityReferences = bc.convertToType(value, Boolean.class);
+		else if (property.equals(XML_xsiNs))
+			xsiNs = value.toString();
+		else if (property.equals(XML_reporter) && value instanceof XMLReporter)
+			reporter = (XMLReporter)value;
+		else if (property.equals(XML_resolver) && value instanceof XMLResolver)
+			resolver = (XMLResolver)value;
+		else if (property.equals(XML_eventAllocator) && value instanceof XMLEventAllocator)
+			eventAllocator = (XMLEventAllocator)value;
+		else if (property.equals(XML_preserveRootElement))
+			preserveRootElement = bc.convertToType(value, Boolean.class);
+		else
+			return false;
+		return true;
+	}
+
+	/**
+	 * Returns the current {@link #XML_xsiNs} value.
+	 * @return The current {@link #XML_xsiNs} value.
+	 */
+	public String getXsiNs() {
+		return xsiNs;
+	}
+
+	/**
+	 * Returns the current {@link #XML_trimWhitespace} value.
+	 * @return The current {@link #XML_trimWhitespace} value.
+	 */
+	public boolean isTrimWhitespace() {
+		return trimWhitespace;
+	}
+
+	/**
+	 * Returns the current {@link #XML_preserveRootElement} value.
+	 * @return The current {@link #XML_preserveRootElement} value.
+	 */
+	public boolean isPreserveRootElement() {
+		return preserveRootElement;
+	}
+
+	/**
+	 * Returns the current {@link #XML_validating} value.
+	 * @return The current {@link #XML_validating} value.
+	 */
+	public boolean isValidating() {
+		return validating;
+	}
+
+	/**
+	 * Returns the current {@link #XML_coalescing} value.
+	 * @return The current {@link #XML_coalescing} value.
+	 */
+	public boolean isCoalescing() {
+		return coalescing;
+	}
+
+	/**
+	 * Returns the current {@link #XML_replaceEntityReferences} value.
+	 * @return The current {@link #XML_replaceEntityReferences} value.
+	 */
+	public boolean isReplaceEntityReferences() {
+		return replaceEntityReferences;
+	}
+
+	/**
+	 * Returns the current {@link #XML_reporter} value.
+	 * @return The current {@link #XML_reporter} value.
+	 */
+	public XMLReporter getReporter() {
+		return reporter;
+	}
+
+	/**
+	 * Returns the current {@link #XML_reporter} value.
+	 * @return The current {@link #XML_reporter} value.
+	 */
+	public XMLResolver getResolver() {
+		return resolver;
+	}
+
+	/**
+	 * Returns the current {@link #XML_eventAllocator} value.
+	 * @return The current {@link #XML_eventAllocator} value.
+	 */
+	public XMLEventAllocator getEventAllocator() {
+		return eventAllocator;
+	}
+
+
+	//--------------------------------------------------------------------------------
+	// Overridden methods
+	//--------------------------------------------------------------------------------
+
+	@Override /* Object */
+	public XmlParserProperties clone() {
+		try {
+			return (XmlParserProperties)super.clone();
+		} catch (CloneNotSupportedException e) {
+			throw new RuntimeException(e); // Shouldn't happen.
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaDocSerializer.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaDocSerializer.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaDocSerializer.class
new file mode 100755
index 0000000..4aa659b
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaDocSerializer.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/xml/XmlSchemaDocSerializer.java
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaDocSerializer.java b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaDocSerializer.java
new file mode 100755
index 0000000..0c3b5f5
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaDocSerializer.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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.xml;
+
+import java.io.*;
+
+import com.ibm.juno.core.serializer.*;
+
+/**
+ * Serializes POJO metadata to HTTP responses as XML.
+ *
+ *
+ * <h6 class='topic'>Media types</h6>
+ * <p>
+ * 	Handles <code>Accept</code> types: <code>text/xml+schema</code>
+ * <p>
+ * 	Produces <code>Content-Type</code> types: <code>text/xml</code>
+ *
+ *
+ * <h6 class='topic'>Description</h6>
+ * <p>
+ * 	Same as {@link XmlSchemaSerializer}, except prepends <code><xt>&lt;?xml</xt> <xa>version</xa>=<xs>'1.0'</xs> <xa>encoding</xa>=<xs>'UTF-8'</xs><xt>?&gt;</xt></code> to the response
+ * 	to make it a valid XML document.
+ *
+ *
+ * @author James Bognar (jbognar@us.ibm.com)
+ */
+public class XmlSchemaDocSerializer extends XmlSchemaSerializer {
+
+	//--------------------------------------------------------------------------------
+	// Overridden methods
+	//--------------------------------------------------------------------------------
+
+	@Override /* Serializer */
+	protected void doSerialize(Object o, Writer out, SerializerContext ctx) throws IOException, SerializeException {
+		XmlSerializerContext xctx = (XmlSerializerContext)ctx;
+		XmlSerializerWriter w = xctx.getWriter(out);
+		w.append("<?xml")
+			.attr("version", "1.0")
+			.attr("encoding", "UTF-8")
+			.appendln("?>");
+		super.doSerialize(o, w, ctx);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer$1.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer$1.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer$1.class
new file mode 100755
index 0000000..98bc0e8
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer$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/xml/XmlSchemaSerializer$QueueEntry.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer$QueueEntry.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer$QueueEntry.class
new file mode 100755
index 0000000..7948545
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer$QueueEntry.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/xml/XmlSchemaSerializer$Schema.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer$Schema.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer$Schema.class
new file mode 100755
index 0000000..fa87011
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer$Schema.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/xml/XmlSchemaSerializer$Schemas.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer$Schemas.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer$Schemas.class
new file mode 100755
index 0000000..fba563f
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer$Schemas.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/xml/XmlSchemaSerializer.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer.class
new file mode 100755
index 0000000..1361066
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer.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/xml/XmlSchemaSerializer.java
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer.java b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer.java
new file mode 100755
index 0000000..bc40ae4
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSchemaSerializer.java
@@ -0,0 +1,588 @@
+/*******************************************************************************
+ * 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.xml;
+
+import static com.ibm.juno.core.xml.annotation.XmlFormat.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.text.*;
+import java.util.*;
+import java.util.regex.*;
+
+import javax.xml.*;
+import javax.xml.transform.stream.*;
+import javax.xml.validation.*;
+
+import org.w3c.dom.bootstrap.*;
+import org.w3c.dom.ls.*;
+import org.xml.sax.*;
+
+import com.ibm.juno.core.*;
+import com.ibm.juno.core.annotation.*;
+import com.ibm.juno.core.serializer.*;
+import com.ibm.juno.core.utils.*;
+import com.ibm.juno.core.xml.annotation.*;
+
+/**
+ * Serializes POJO metadata to HTTP responses as XML.
+ *
+ *
+ * <h6 class='topic'>Media types</h6>
+ * <p>
+ * 	Handles <code>Accept</code> types: <code>text/xml+schema</code>
+ * <p>
+ * 	Produces <code>Content-Type</code> types: <code>text/xml</code>
+ *
+ *
+ * <h6 class='topic'>Description</h6>
+ * <p>
+ * 	Produces the XML-schema representation of the XML produced by the {@link XmlSerializer} class with the same properties.
+ *
+ *
+ * <h6 class='topic'>Configurable properties</h6>
+ * <p>
+ * 	This class has the following properties associated with it:
+ * <ul>
+ * 	<li>{@link XmlSerializerProperties}
+ * 	<li>{@link SerializerProperties}
+ * 	<li>{@link BeanContextProperties}
+ * </ul>
+ *
+ * @author James Bognar (jbognar@us.ibm.com)
+ */
+@Produces(value="text/xml+schema",contentType="text/xml")
+public class XmlSchemaSerializer extends XmlSerializer {
+
+	@Override /* XmlSerializer */
+	protected void doSerialize(Object o, Writer out, SerializerContext ctx) throws IOException, SerializeException {
+		XmlSerializerContext xctx = (XmlSerializerContext)ctx;
+
+		if (xctx.isEnableNamespaces() && xctx.isAutoDetectNamespaces())
+			findNsfMappings(o, xctx);
+
+		Namespace xs = xctx.getXsNamespace();
+		Namespace[] allNs = ArrayUtils.append(new Namespace[]{xctx.getDefaultNamespace()}, xctx.getNamespaces());
+
+		Schemas s = new Schemas(xs, xctx.getDefaultNamespace(), allNs, xctx);
+		s.process(o, xctx);
+		s.serializeTo(out);
+	}
+
+	/**
+	 * Returns an XML-Schema validator based on the output returned by {@link #doSerialize(Object, Writer, SerializerContext)};
+	 *
+	 * @param o The object to serialize.
+	 * @param ctx The serializer context object return by {@link #createContext(ObjectMap, Method)}.<br>
+	 * 	Can be <jk>null</jk>.
+	 * @return The new validator.
+	 * @throws SAXException If a problem was detected in the XML-Schema output produced by this serializer.
+	 * @throws SerializeException If a problem occurred trying to convert the output.
+	 */
+	public Validator getValidator(Object o, SerializerContext ctx) throws SerializeException, SAXException {
+		String xmlSchema = serialize(o, ctx);
+
+		// create a SchemaFactory capable of understanding WXS schemas
+		SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+
+		if (xmlSchema.indexOf('\u0000') != -1) {
+
+			// Break it up into a map of namespaceURI->schema document
+			final Map<String,String> schemas = new HashMap<String,String>();
+			String[] ss = xmlSchema.split("\u0000");
+			xmlSchema = ss[0];
+			for (String s : ss) {
+				Matcher m = pTargetNs.matcher(s);
+				if (m.find())
+					schemas.put(m.group(1), s);
+			}
+
+			// Create a custom resolver
+			factory.setResourceResolver(
+				new LSResourceResolver() {
+
+					@Override /* LSResourceResolver */
+					public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
+
+						String schema = schemas.get(namespaceURI);
+						if (schema == null)
+							throw new RuntimeException(MessageFormat.format("No schema found for namespaceURI ''{0}''", namespaceURI));
+
+						try {
+							DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
+							DOMImplementationLS domImplementationLS = (DOMImplementationLS)registry.getDOMImplementation("LS 3.0");
+							LSInput in = domImplementationLS.createLSInput();
+							in.setCharacterStream(new StringReader(schema));
+							in.setSystemId(systemId);
+							return in;
+
+						} catch (Exception e) {
+							throw new RuntimeException(e);
+						}
+					}
+				}
+			);
+		}
+		return factory.newSchema(new StreamSource(new StringReader(xmlSchema))).newValidator();
+	}
+
+	private static Pattern pTargetNs = Pattern.compile("targetNamespace=['\"]([^'\"]+)['\"]");
+
+
+	/* An instance of a global element, global attribute, or XML type to be serialized. */
+	private static class QueueEntry {
+		Namespace ns;
+		String name;
+		ClassMeta<?> cm;
+		QueueEntry(Namespace ns, String name, ClassMeta<?> cm) {
+			this.ns = ns;
+			this.name = name;
+			this.cm = cm;
+		}
+	}
+
+	/* An encapsulation of all schemas present in the metamodel of the serialized object. */
+	private class Schemas extends LinkedHashMap<Namespace,Schema> {
+
+		private static final long serialVersionUID = 1L;
+
+		private Namespace defaultNs;
+		private LinkedList<QueueEntry>
+			elementQueue = new LinkedList<QueueEntry>(),
+			attributeQueue = new LinkedList<QueueEntry>(),
+			typeQueue = new LinkedList<QueueEntry>();
+
+		private Schemas(Namespace xs, Namespace defaultNs, Namespace[] allNs, XmlSerializerContext ctx) throws IOException {
+			this.defaultNs = defaultNs;
+			for (Namespace ns : allNs)
+				put(ns, new Schema(this, xs, ns, defaultNs, allNs, ctx));
+		}
+
+		private Schema getSchema(Namespace ns) {
+			if (ns == null)
+				ns = defaultNs;
+			Schema s = get(ns);
+			if (s == null)
+				throw new RuntimeException("No schema defined for namespace '"+ns+"'");
+			return s;
+		}
+
+		private void process(Object o, SerializerContext ctx) throws IOException {
+			ClassMeta<?> cm = ctx.getBeanContext().getClassMetaForObject(o);
+			Namespace ns = defaultNs;
+			if (cm == null)
+				queueElement(ns, "null", object());
+			else {
+				XmlClassMeta xmlMeta = cm.getXmlMeta();
+				if (xmlMeta.getElementName() != null && xmlMeta.getNamespace() != null)
+					ns = xmlMeta.getNamespace();
+				queueElement(ns, xmlMeta.getElementName(), cm);
+			}
+			processQueue();
+		}
+
+
+		private void processQueue() throws IOException {
+			boolean b;
+			do {
+				b = false;
+				while (! elementQueue.isEmpty()) {
+					QueueEntry q = elementQueue.removeFirst();
+					b |= getSchema(q.ns).processElement(q.name, q.cm);
+				}
+				while (! typeQueue.isEmpty()) {
+					QueueEntry q = typeQueue.removeFirst();
+					b |= getSchema(q.ns).processType(q.name, q.cm);
+				}
+				while (! attributeQueue.isEmpty()) {
+					QueueEntry q = attributeQueue.removeFirst();
+					b |= getSchema(q.ns).processAttribute(q.name, q.cm);
+				}
+			} while (b);
+		}
+
+		private void queueElement(Namespace ns, String name, ClassMeta<?> cm) {
+			elementQueue.add(new QueueEntry(ns, name, cm));
+		}
+
+		private void queueType(Namespace ns, String name, ClassMeta<?> cm) {
+			if (name == null)
+				name = XmlUtils.encodeElementName(cm.toString());
+			typeQueue.add(new QueueEntry(ns, name, cm));
+		}
+
+		private void queueAttribute(Namespace ns, String name, ClassMeta<?> cm) {
+			attributeQueue.add(new QueueEntry(ns, name, cm));
+		}
+
+		private void serializeTo(Writer w) throws IOException {
+			boolean b = false;
+			for (Schema s : values()) {
+				if (b)
+					w.append('\u0000');
+				w.append(s.toString());
+				b = true;
+			}
+		}
+	}
+
+	/* An encapsulation of a single schema. */
+	private class Schema {
+		private StringWriter sw = new StringWriter();
+		private XmlSerializerWriter w;
+		private XmlSerializerContext ctx;
+		private Namespace defaultNs, targetNs;
+		private Schemas schemas;
+		private Set<String>
+			processedTypes = new HashSet<String>(),
+			processedAttributes = new HashSet<String>(),
+			processedElements = new HashSet<String>();
+
+		public Schema(Schemas schemas, Namespace xs, Namespace targetNs, Namespace defaultNs, Namespace[] allNs, XmlSerializerContext ctx) throws IOException {
+			this.schemas = schemas;
+			this.defaultNs = defaultNs;
+			this.targetNs = targetNs;
+			this.ctx = ctx;
+			w = new XmlSerializerWriter(sw, ctx.isUseIndentation(), ctx.getQuoteChar(), null, null, true, null);
+			int i = ctx.getIndent();
+			w.oTag(i, "schema");
+			w.attr("xmlns", xs.getUri());
+			w.attr("targetNamespace", targetNs.getUri());
+			w.attr("elementFormDefault", "qualified");
+			if (targetNs != defaultNs)
+				w.attr("attributeFormDefault", "qualified");
+			for (Namespace ns2 : allNs)
+				w.attr("xmlns", ns2.name, ns2.uri);
+			w.append('>').nl();
+			for (Namespace ns : allNs) {
+				if (ns != targetNs) {
+					w.oTag(i+1, "import")
+						.attr("namespace", ns.getUri())
+						.attr("schemaLocation", ns.getName()+".xsd")
+						.append("/>").nl();
+				}
+			}
+		}
+
+		private boolean processElement(String name, ClassMeta<?> cm) throws IOException {
+			if (processedElements.contains(name))
+				return false;
+			processedElements.add(name);
+
+			ClassMeta<?> ft = cm.getFilteredClassMeta();
+			int i = ctx.getIndent() + 1;
+			if (name == null)
+				name = getElementName(ft);
+			Namespace ns = first(ft.getXmlMeta().getNamespace(), defaultNs);
+			String type = getXmlType(ns, ft);
+
+			w.oTag(i, "element")
+				.attr("name", XmlUtils.encodeElementName(name))
+				.attr("type", type)
+				.append('/').append('>').nl();
+
+			schemas.queueType(ns, null, ft);
+			schemas.processQueue();
+			return true;
+		}
+
+		private boolean processAttribute(String name, ClassMeta<?> cm) throws IOException {
+			if (processedAttributes.contains(name))
+				return false;
+			processedAttributes.add(name);
+
+			int i = ctx.getIndent() + 1;
+			String type = getXmlAttrType(cm);
+
+			w.oTag(i, "attribute")
+				.attr("name", name)
+				.attr("type", type)
+				.append('/').append('>').nl();
+
+			return true;
+		}
+
+		private boolean processType(String name, ClassMeta<?> cm) throws IOException {
+			if (processedTypes.contains(name))
+				return false;
+			processedTypes.add(name);
+
+			int i = ctx.getIndent() + 1;
+
+			cm = cm.getFilteredClassMeta();
+
+			w.oTag(i, "complexType")
+				.attr("name", name);
+
+			// This element can have mixed content if:
+			// 	1) It's a generic Object (so it can theoretically be anything)
+			//		2) The bean has a property defined with @XmlFormat.CONTENT.
+			if ((cm.isBean() && cm.getBeanMeta().getXmlMeta().getXmlContentProperty() != null) || cm.isObject())
+				w.attr("mixed", "true");
+
+			w.cTag().nl();
+
+			if (! (cm.isMap() || cm.isBean() || cm.hasToObjectMapMethod() || cm.isCollection() || cm.isArray() || (cm.isAbstract() && ! cm.isNumber()) || cm.isObject())) {
+				String base = getXmlAttrType(cm);
+				w.sTag(i+1, "simpleContent").nl();
+				w.oTag(i+2, "extension")
+					.attr("base", base);
+				if (ctx.isAddJsonTypeAttrs() || (ctx.isAddJsonStringTypeAttrs() && base.equals("string"))) {
+					w.cTag().nl();
+					w.oTag(i+3, "attribute")
+						.attr("name", "type")
+						.attr("type", "string")
+						.ceTag().nl();
+					w.eTag(i+2, "extension").nl();
+				} else {
+					w.ceTag().nl();
+				}
+				w.eTag(i+1, "simpleContent").nl();
+
+			} else {
+
+				//----- Bean -----
+				if (cm.isBean()) {
+					BeanMeta<?> bm = cm.getBeanMeta();
+
+					boolean hasChildElements = false;
+
+					for (BeanPropertyMeta<?> pMeta : bm.getPropertyMetas())
+						if (pMeta.getXmlMeta().getXmlFormat() != XmlFormat.ATTR && pMeta.getXmlMeta().getXmlFormat() != XmlFormat.CONTENT)
+							hasChildElements = true;
+
+					if (bm.getXmlMeta().getXmlContentProperty() != null) {
+						w.sTag(i+1, "sequence").nl();
+						w.oTag(i+2, "any")
+							.attr("processContents", "skip")
+							.attr("minOccurs", 0)
+							.ceTag().nl();
+						w.eTag(i+1, "sequence").nl();
+
+					} else if (hasChildElements) {
+						w.sTag(i+1, "sequence").nl();
+
+						boolean hasOtherNsElement = false;
+
+						for (BeanPropertyMeta<?> pMeta : bm.getPropertyMetas()) {
+							XmlBeanPropertyMeta<?> xmlMeta = pMeta.getXmlMeta();
+							if (xmlMeta.getXmlFormat() != XmlFormat.ATTR) {
+								boolean isCollapsed = xmlMeta.getXmlFormat() == COLLAPSED;
+								ClassMeta<?> ct2 = pMeta.getClassMeta();
+								String childName = pMeta.getName();
+								if (isCollapsed) {
+									if (xmlMeta.getChildName() != null)
+										childName = xmlMeta.getChildName();
+									ct2 = pMeta.getClassMeta().getElementType();
+								}
+								Namespace cNs = first(xmlMeta.getNamespace(), ct2.getXmlMeta().getNamespace(), cm.getXmlMeta().getNamespace(), defaultNs);
+								if (xmlMeta.getNamespace() == null) {
+									w.oTag(i+2, "element")
+										.attr("name", XmlUtils.encodeElementName(childName), true)
+										.attr("type", getXmlType(cNs, ct2));
+									if (isCollapsed) {
+										w.attr("minOccurs", 0);
+										w.attr("maxOccurs", "unbounded");
+									} else {
+										if (! ctx.isTrimNulls())
+											w.attr("nillable", true);
+										else
+											w.attr("minOccurs", 0);
+									}
+
+									w.ceTag().nl();
+								} else {
+									// Child element is in another namespace.
+									schemas.queueElement(cNs, pMeta.getName(), ct2);
+									hasOtherNsElement = true;
+								}
+
+							}
+						}
+
+						// If this bean has any child elements in another namespace,
+						// we need to add an <any> element.
+						if (hasOtherNsElement)
+							w.oTag(i+2, "any")
+								.attr("minOccurs", 0)
+								.attr("maxOccurs", "unbounded")
+								.ceTag().nl();
+						w.eTag(i+1, "sequence").nl();
+					}
+
+					for (BeanPropertyMeta<?> pMeta : bm.getXmlMeta().getXmlAttrProperties().values()) {
+						Namespace pNs = pMeta.getXmlMeta().getNamespace();
+						if (pNs == null)
+							pNs = defaultNs;
+
+						// If the bean attribute has a different namespace than the bean, then it needs to
+						// be added as a top-level entry in the appropriate schema file.
+						if (pNs != targetNs) {
+							schemas.queueAttribute(pNs, pMeta.getName(), pMeta.getClassMeta());
+							w.oTag(i+1, "attribute")
+							//.attr("name", pMeta.getName(), true)
+							.attr("ref", pNs.getName() + ':' + pMeta.getName())
+							.ceTag().nl();
+						}
+
+						// Otherwise, it's just a plain attribute of this bean.
+						else {
+							w.oTag(i+1, "attribute")
+								.attr("name", pMeta.getName(), true)
+								.attr("type", getXmlAttrType(pMeta.getClassMeta()))
+								.ceTag().nl();
+						}
+					}
+
+				//----- Collection -----
+				} else if (cm.isCollection() || cm.isArray()) {
+					ClassMeta<?> elementType = cm.getElementType();
+					if (elementType.isObject()) {
+						w.sTag(i+1, "sequence").nl();
+						w.oTag(i+2, "any")
+							.attr("processContents", "skip")
+							.attr("maxOccurs", "unbounded")
+							.attr("minOccurs", "0")
+							.ceTag().nl();
+						w.eTag(i+1, "sequence").nl();
+					} else {
+						Namespace cNs = first(elementType.getXmlMeta().getNamespace(), cm.getXmlMeta().getNamespace(), defaultNs);
+						schemas.queueType(cNs, null, elementType);
+						w.sTag(i+1, "sequence").nl();
+						w.oTag(i+2, "choice")
+							.attr("minOccurs", 0)
+							.attr("maxOccurs", "unbounded")
+							.cTag().nl();
+						w.oTag(i+3, "element")
+							.attr("name", XmlUtils.encodeElementName(getElementName(elementType)))
+							.attr("type", getXmlType(cNs, elementType))
+							.ceTag().nl();
+						w.oTag(i+3, "element")
+							.attr("name", "null")
+							.attr("type", "string")
+							.ceTag().nl();
+						w.eTag(i+2, "choice").nl();
+						w.eTag(i+1, "sequence").nl();
+					}
+
+				//----- Map -----
+				} else if (cm.isMap() || cm.hasToObjectMapMethod() || cm.isAbstract() || cm.isObject()) {
+					w.sTag(i+1, "sequence").nl();
+					w.oTag(i+2, "any")
+						.attr("processContents", "skip")
+						.attr("maxOccurs", "unbounded")
+						.attr("minOccurs", "0")
+						.ceTag().nl();
+					w.eTag(i+1, "sequence").nl();
+				}
+
+				if (ctx.isAddClassAttrs()) {
+					w.oTag(i+1, "attribute")
+						.attr("name", "_class")
+						.attr("type", "string")
+						.ceTag().nl();
+				}
+				if (ctx.isAddJsonTypeAttrs()) {
+					w.oTag(i+1, "attribute")
+						.attr("name", "type")
+						.attr("type", "string")
+						.ceTag().nl();
+				}
+			}
+
+			w.eTag(i, "complexType").nl();
+			schemas.processQueue();
+
+			return true;
+		}
+
+		private String getElementName(ClassMeta<?> cm) {
+			cm = cm.getFilteredClassMeta();
+			String name = cm.getXmlMeta().getElementName();
+
+			if (name == null) {
+				if (cm.isBoolean())
+					name = "boolean";
+				else if (cm.isNumber())
+					name = "number";
+				else if (cm.isArray() || cm.isCollection())
+					name = "array";
+				else if (! (cm.isMap() || cm.hasToObjectMapMethod() || cm.isBean() || cm.isCollection() || cm.isArray() || cm.isObject() || cm.isAbstract()))
+					name = "string";
+				else
+					name = "object";
+			}
+			return name;
+		}
+
+		@Override /* Object */
+		public String toString() {
+			try {
+				w.eTag(ctx.getIndent(), "schema").nl();
+			} catch (IOException e) {
+				throw new RuntimeException(e); // Shouldn't happen.
+			}
+			return sw.toString();
+		}
+
+		private String getXmlType(Namespace currentNs, ClassMeta<?> cm) {
+			String name = null;
+			cm = cm.getFilteredClassMeta();
+			if (currentNs == targetNs && ! ctx.isAddJsonTypeAttrs()) {
+				if (cm.isBoolean())
+					name = "boolean";
+				else if (cm.isNumber()) {
+					if (cm.isDecimal())
+						name = "decimal";
+					else
+						name = "integer";
+				}
+				if (name == null && ! ctx.isAddJsonStringTypeAttrs()) {
+					if (! (cm.isMap() || cm.hasToObjectMapMethod() || cm.isBean() || cm.isCollection() || cm.isArray() || cm.isObject() || cm.isAbstract()))
+						name = "string";
+				}
+			}
+			if (name == null) {
+				name = XmlUtils.encodeElementName(cm.toString());
+				schemas.queueType(currentNs, name, cm);
+				return currentNs.getName() + ":" + name;
+			}
+
+			return name;
+		}
+	}
+
+	private <T> T first(T...tt) {
+		for (T t : tt)
+			if (t != null)
+				return t;
+		return null;
+	}
+
+
+	private static String getXmlAttrType(ClassMeta<?> cm) {
+		if (cm.isBoolean())
+			return "boolean";
+		if (cm.isNumber()) {
+			if (cm.isDecimal())
+				return "decimal";
+			return "integer";
+		}
+		return "string";
+	}
+
+	@Override /* Serializer */
+	public XmlSerializerContext createContext(ObjectMap properties, Method javaMethod) {
+		// This serializer must always have namespaces enabled.
+		if (properties == null)
+			properties = new ObjectMap();
+		properties.put(XmlSerializerProperties.XML_enableNamespaces, true);
+		return new XmlSerializerContext(getBeanContext(), sp, xsp, properties, javaMethod);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$Simple.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$Simple.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$Simple.class
new file mode 100755
index 0000000..bc8d4b1
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$Simple.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/xml/XmlSerializer$SimpleSq.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$SimpleSq.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$SimpleSq.class
new file mode 100755
index 0000000..3ddea63
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$SimpleSq.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/xml/XmlSerializer$SimpleXmlJsonSq.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$SimpleXmlJsonSq.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$SimpleXmlJsonSq.class
new file mode 100755
index 0000000..d1b38a7
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$SimpleXmlJsonSq.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/xml/XmlSerializer$Sq.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$Sq.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$Sq.class
new file mode 100755
index 0000000..2db7192
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$Sq.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/xml/XmlSerializer$SqReadable.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$SqReadable.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$SqReadable.class
new file mode 100755
index 0000000..71e44be
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$SqReadable.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/xml/XmlSerializer$XmlJson.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$XmlJson.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$XmlJson.class
new file mode 100755
index 0000000..8d4a34b
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$XmlJson.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/xml/XmlSerializer$XmlJsonSq.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$XmlJsonSq.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$XmlJsonSq.class
new file mode 100755
index 0000000..4264fee
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer$XmlJsonSq.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/xml/XmlSerializer.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer.class
new file mode 100755
index 0000000..221a0e7
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer.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/xml/XmlSerializer.java
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer.java b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer.java
new file mode 100755
index 0000000..8b75856
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializer.java
@@ -0,0 +1,725 @@
+/*******************************************************************************
+ * 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.xml;
+
+import static com.ibm.juno.core.serializer.SerializerProperties.*;
+import static com.ibm.juno.core.xml.XmlSerializerProperties.*;
+import static com.ibm.juno.core.xml.annotation.XmlFormat.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.ibm.juno.core.*;
+import com.ibm.juno.core.annotation.*;
+import com.ibm.juno.core.filter.*;
+import com.ibm.juno.core.json.*;
+import com.ibm.juno.core.serializer.*;
+import com.ibm.juno.core.xml.annotation.*;
+
+/**
+ * Serializes POJO models to XML.
+ *
+ *
+ * <h6 class='topic'>Media types</h6>
+ * <p>
+ * 	Handles <code>Accept</code> types: <code>text/xml</code>
+ * <p>
+ * 	Produces <code>Content-Type</code> types: <code>text/xml</code>
+ *
+ *
+ * <h6 class='topic'>Description</h6>
+ * <p>
+ * 	See the {@link JsonSerializer} class for details on how Java models map to JSON.
+ * <p>
+ * 	For example, the following JSON...
+ * <p class='bcode'>
+ * 	{
+ * 		name:<js>'John Smith'</js>,
+ * 		address: {
+ * 			streetAddress: <js>'21 2nd Street'</js>,
+ * 			city: <js>'New York'</js>,
+ * 			state: <js>'NY'</js>,
+ * 			postalCode: <js>10021</js>
+ * 		},
+ * 		phoneNumbers: [
+ * 			<js>'212 555-1111'</js>,
+ * 			<js>'212 555-2222'</js>
+ * 		],
+ * 		additionalInfo: <jk>null</jk>,
+ * 		remote: <jk>false</jk>,
+ * 		height: <js>62.4</js>,
+ * 		<js>'fico score'</js>:  <js>' &gt; 640'</js>
+ * 	}
+ * <p>
+ * 	...maps to the following XML...
+ * <p class='bcode'>
+ * 	<xt>&lt;object&gt;</xt>
+ * 		<xt>&lt;name</xt> <xa>type</xa>=<xs>'string'</xs><xt>&gt;</xt>John Smith<xt>&lt;/name&gt;</xt>
+ * 		<xt>&lt;address</xt> <xa>type</xa>=<xs>'object'</xs><xt>&gt;</xt>
+ * 			<xt>&lt;streetAddress</xt> <xa>type</xa>=<xs>'string'</xs><xt>&gt;</xt>21 2nd Street<xt>&lt;/streetAddress&gt;</xt>
+ * 			<xt>&lt;city</xt> <xa>type</xa>=<xs>'string'</xs><xt>&gt;</xt>New York<xt>&lt;/city&gt;</xt>
+ * 			<xt>&lt;state</xt> <xa>type</xa>=<xs>'string'</xs><xt>&gt;</xt>NY<xt>&lt;/state&gt;</xt>
+ * 			<xt>&lt;postalCode</xt> <xa>type</xa>=<xs>'number'</xs><xt>&gt;</xt>10021<xt>&lt;/postalCode&gt;</xt>
+ * 		<xt>&lt;/address&gt;</xt>
+ * 		<xt>&lt;phoneNumbers</xt> <xa>type</xa>=<xs>'array'</xs><xt>&gt;</xt>
+ * 			<xt>&lt;string&gt;</xt>212 555-1111<xt>&lt;/string&gt;</xt>
+ * 			<xt>&lt;string&gt;</xt>212 555-2222<xt>&lt;/string&gt;</xt>
+ * 		<xt>&lt;/phoneNumbers&gt;</xt>
+ * 		<xt>&lt;additionalInfo</xt> <xa>type</xa>=<xs>'null'</xs><xt>&gt;&lt;/additionalInfo&gt;</xt>
+ * 		<xt>&lt;remote</xt> <xa>type</xa>=<xs>'boolean'</xs><xt>&gt;</xt>false<xt>&lt;/remote&gt;</xt>
+ * 		<xt>&lt;height</xt> <xa>type</xa>=<xs>'number'</xs><xt>&gt;</xt>62.4<xt>&lt;/height&gt;</xt>
+ * 		<xt>&lt;fico_x0020_score</xt> <xa>type</xa>=<xs>'string'</xs><xt>&gt;</xt> &amp;gt; 640<xt>&lt;/fico_x0020_score&gt;</xt>
+ * 	<xt>&lt;/object&gt;</xt>
+ * <p>
+ * 	This serializer provides several serialization options.  Typically, one of the predefined <jsf>DEFAULT</jsf> serializers will be sufficient.
+ * 	However, custom serializers can be constructed to fine-tune behavior.
+ * <p>
+ * 	If an attribute name contains any non-valid XML element characters, they will be escaped using standard {@code _x####_} notation.
+ *
+ *
+ * <h6 class='topic'>Configurable properties</h6>
+ * <p>
+ * 	This class has the following properties associated with it:
+ * <ul>
+ * 	<li>{@link XmlSerializerProperties}
+ * 	<li>{@link SerializerProperties}
+ * 	<li>{@link BeanContextProperties}
+ * </ul>
+ *
+ *
+ * <h6 class='topic'>Behavior-specific subclasses</h6>
+ * <p>
+ * 	The following direct subclasses are provided for convenience:
+ * <ul>
+ * 	<li>{@link Sq} - Default serializer, single quotes.
+ * 	<li>{@link SqReadable} - Default serializer, single quotes, whitespace added.
+ * 	<li>{@link XmlJson} - Default serializer with JSON attribute tags.
+ * 	<li>{@link XmlJsonSq} - Default serializer with JSON attribute tags, single quotes.
+ * </ul>
+ *
+ *
+ * @author James Bognar (jbognar@us.ibm.com)
+ */
+@SuppressWarnings({ "rawtypes", "unchecked" })
+@Produces("text/xml")
+public class XmlSerializer extends WriterSerializer {
+
+	/** Default serializer, all default settings. */
+	public static final XmlSerializer DEFAULT = new XmlSerializer().lock();
+
+	/** Default serializer, single quotes. */
+	public static final XmlSerializer DEFAULT_SQ = new XmlSerializer.Sq().lock();
+
+	/** Default serializer, single quotes, whitespace added. */
+	public static final XmlSerializer DEFAULT_SQ_READABLE = new XmlSerializer.SqReadable().lock();
+
+	/** Default serializer with JSON attribute tags. */
+	public static final XmlSerializer DEFAULT_XMLJSON = new XmlSerializer.XmlJson().lock();
+
+	/** Default serializer with JSON attribute tags, single quotes. */
+	public static final XmlSerializer DEFAULT_XMLJSON_SQ = new XmlSerializer.XmlJsonSq().lock();
+
+	/** Default serializer without namespaces. */
+	public static final XmlSerializer DEFAULT_SIMPLE = new XmlSerializer.Simple().lock();
+
+	/** Default serializer without namespaces, with single quotes. */
+	public static final XmlSerializer DEFAULT_SIMPLE_SQ = new XmlSerializer.SimpleSq().lock();
+
+	/** Default serializer without namespaces, with JSON attribute tags and single quotes. */
+	public static final XmlSerializer DEFAULT_SIMPLE_XMLJSON_SQ = new XmlSerializer.SimpleXmlJsonSq().lock();
+
+
+	/** Default serializer, single quotes. */
+	public static class Sq extends XmlSerializer {
+		/** Constructor */
+		public Sq() {
+			setProperty(SERIALIZER_quoteChar, '\'');
+		}
+	}
+
+	/** Default serializer, single quotes, whitespace added. */
+	public static class SqReadable extends Sq {
+		/** Constructor */
+		public SqReadable() {
+			setProperty(SERIALIZER_useIndentation, true);
+		}
+	}
+
+	/** Default serializer with JSON attribute tags. */
+	@Produces(value="text/xml+json",contentType="text/xml")
+	public static class XmlJson extends XmlSerializer {
+		/** Constructor */
+		public XmlJson() {
+			setProperty(XML_addJsonTypeAttrs, true);
+		}
+	}
+
+	/** Default serializer with JSON attribute tags, single quotes. */
+	public static class XmlJsonSq extends XmlJson {
+		/** Constructor */
+		public XmlJsonSq() {
+			setProperty(SERIALIZER_quoteChar, '\'');
+		}
+	}
+
+	/** Default serializer without namespaces. */
+	@Produces(value="text/xml+simple",contentType="text/xml")
+	public static class Simple extends XmlSerializer {
+		/** Constructor */
+		public Simple() {
+			setProperty(XML_enableNamespaces, false);
+		}
+	}
+
+	/** Default serializer without namespaces, single quotes. */
+	public static class SimpleSq extends Simple {
+		/** Constructor */
+		public SimpleSq() {
+			setProperty(SERIALIZER_quoteChar, '\'');
+		}
+	}
+
+	/** Default serializer with JSON attribute tags, single quotes. */
+	public static class SimpleXmlJsonSq extends SimpleSq {
+		/** Constructor */
+		public SimpleXmlJsonSq() {
+			setProperty(XML_addJsonTypeAttrs, true);
+		}
+	}
+
+	/** XML serializer properties currently set on this serializer. */
+	protected transient XmlSerializerProperties xsp = new XmlSerializerProperties();
+
+
+	/**
+	 * Recursively searches for the XML namespaces on the specified POJO and adds them to the serializer context object.
+	 *
+	 * @param o The POJO to check.
+	 * @param ctx The context that exists for the duration of a single serialization.
+	 * @throws SerializeException
+	 */
+	protected void findNsfMappings(Object o, XmlSerializerContext ctx) throws SerializeException {
+		BeanContext bc = ctx.getBeanContext();
+		ClassMeta<?> aType = null;						// The actual type
+		aType = ctx.push(null, o, null);
+
+		if (aType != null) {
+			Namespace ns = aType.getXmlMeta().getNamespace();
+			if (ns != null) {
+				if (ns.uri != null)
+					ctx.addNamespace(ns);
+				else
+					ns = null;
+			}
+		}
+
+		// Handle recursion
+		if (aType != null && ! aType.isPrimitive()) {
+
+			BeanMap bm = null;
+			if (aType.isBeanMap()) {
+				bm = (BeanMap)o;
+			} else if (aType.isBean()) {
+				bm = bc.forBean(o);
+			} else if (aType.isDelegate()) {
+				ClassMeta innerType = ((Delegate)o).getClassMeta();
+				Namespace ns = innerType.getXmlMeta().getNamespace();
+				if (ns != null) {
+					if (ns.uri != null)
+						ctx.addNamespace(ns);
+					else
+						ns = null;
+				}
+
+				if (innerType.isBean()) {
+					for (BeanPropertyMeta bpm : (Collection<BeanPropertyMeta>)innerType.getBeanMeta().getPropertyMetas()) {
+						ns = bpm.getXmlMeta().getNamespace();
+						if (ns != null && ns.uri != null)
+							ctx.addNamespace(ns);
+					}
+
+				} else if (innerType.isMap()) {
+					for (Object o2 : ((Map)o).values())
+						findNsfMappings(o2, ctx);
+				} else if (innerType.isCollection()) {
+					for (Object o2 : ((Collection)o))
+						findNsfMappings(o2, ctx);
+				}
+
+			} else if (aType.isMap()) {
+				for (Object o2 : ((Map)o).values())
+					findNsfMappings(o2, ctx);
+			} else if (aType.isCollection()) {
+				for (Object o2 : ((Collection)o))
+					findNsfMappings(o2, ctx);
+			} else if (aType.isArray() && ! aType.getElementType().isPrimitive()) {
+				for (Object o2 : ((Object[])o))
+					findNsfMappings(o2, ctx);
+			}
+			if (bm != null) {
+				for (BeanMapEntry p : (Set<BeanMapEntry>)bm.entrySet()) {
+
+					Namespace ns = p.getMeta().getXmlMeta().getNamespace();
+					if (ns != null && ns.uri != null)
+						ctx.addNamespace(ns);
+
+					try {
+						findNsfMappings(p.getValue(), ctx);
+					} catch (Throwable x) {
+						// Ignore
+					}
+				}
+			}
+		}
+
+		ctx.pop();
+	}
+
+	/**
+	 * Workhorse method.
+	 *
+	 * @param out The writer to send the output to.
+	 * @param o The object to serialize.
+	 * @param eType The expected type if this is a bean property value being serialized.
+	 * @param ctx The serializer context.
+	 * @param elementName The root element name.
+	 * @param elementNamespace The namespace of the element.
+	 * @param addNamespaceUris Flag indicating that namespace URIs need to be added.
+	 * @param format The format to serialize the output to.
+	 * @param pMeta The bean property metadata if this is a bean property being serialized.
+	 * @return The same writer passed in so that calls to the writer can be chained.
+	 * @throws IOException If a problem occurred trying to write to the writer.
+	 * @throws SerializeException If a problem occurred trying to convert the output.
+	 */
+	protected XmlSerializerWriter serializeAnything(XmlSerializerWriter out, Object o, ClassMeta eType,
+			XmlSerializerContext ctx, String elementName, Namespace elementNamespace, boolean addNamespaceUris,
+			XmlFormat format, BeanPropertyMeta<?> pMeta) throws IOException, SerializeException {
+
+		BeanContext bc = ctx.getBeanContext();
+		String ts = null;              // The type string (e.g. <type> or <x x='type'>
+		int indent = ctx.indent;       // Current indentation
+		ClassMeta<?> aType = null;     // The actual type
+		ClassMeta<?> wType = null;     // The wrapped type
+		ClassMeta<?> gType = object(); // The generic type
+
+		aType = ctx.push(elementName, o, eType);
+
+		if (eType == null)
+			eType = object();
+
+		// Handle recursion
+		if (aType == null) {
+			o = null;
+			aType = object();
+		}
+
+		if (o != null) {
+
+			if (aType.isDelegate()) {
+				wType = aType;
+				aType = ((Delegate)o).getClassMeta();
+			}
+
+			gType = aType.getFilteredClassMeta();
+
+			// Filter if necessary
+			PojoFilter filter = aType.getPojoFilter();
+			if (filter != null) {
+				o = filter.filter(o);
+
+				// If the filter's getFilteredClass() method returns Object, we need to figure out
+				// the actual type now.
+				if (gType.isObject())
+					gType = bc.getClassMetaForObject(o);
+			}
+		} else {
+			gType = eType.getFilteredClassMeta();
+		}
+
+		String classAttr = null;
+		if (ctx.isAddClassAttrs()) {
+			if (o != null && ! eType.equals(aType))
+				classAttr = aType.toString();
+			else if (o == null)
+				classAttr = eType.toString();
+		}
+
+		// char '\0' is interpreted as null.
+		if (o != null && gType.isChar() && ((Character)o).charValue() == 0)
+			o = null;
+
+		boolean isCollapsed = false;		// If 'true', this is a collection and we're not rendering the outer element.
+
+		// Get the JSON type string.
+		if (gType.isCharSequence() || gType.isChar())
+			ts = "string";
+		else if (gType.isNumber())
+			ts = "number";
+		else if (gType.isBoolean())
+			ts = "boolean";
+		else if (gType.isMap() || gType.isBean() || gType.hasToObjectMapMethod()) {
+			isCollapsed = gType.getXmlMeta().getFormat() == XmlFormat.COLLAPSED;
+			ts = "object";
+		}
+		else if (gType.isCollection() || gType.isArray()) {
+			isCollapsed = (format == COLLAPSED && ! addNamespaceUris);
+			ts = "array";
+		}
+		else
+			ts = "string";
+
+
+		// Is there a name associated with this bean?
+		if (elementName == null)
+			elementName = gType.getXmlMeta().getElementName();
+		if (elementName == null)
+			elementName = aType.getXmlMeta().getElementName();
+
+		// If the value is null then it's either going to be <null/> or <XmlSerializer nil='true'/>
+		// depending on whether the element has a name.
+		boolean isNullTag = (elementName == null && o == null);
+
+		if (isNullTag)
+			ts = "null";
+
+		if (ctx.isEnableNamespaces()) {
+			if (elementNamespace == null)
+				elementNamespace = gType.getXmlMeta().getNamespace();
+			if (elementNamespace == null)
+				elementNamespace = aType.getXmlMeta().getNamespace();
+			if (elementNamespace != null && elementNamespace.uri == null)
+				elementNamespace = null;
+			if (elementNamespace == null)
+				elementNamespace = ctx.getDefaultNamespace();
+		} else {
+			elementNamespace = null;
+		}
+
+		// Do we need a carriage return after the start tag?
+		boolean cr = o != null && (gType.isMap() || gType.isCollection() || gType.isArray() || gType.isBean() || gType.hasToObjectMapMethod());
+
+		String en = (elementName == null ? ts : elementName);
+		boolean encodeEn = elementName != null;
+		String ns = (elementNamespace == null ? null : elementNamespace.name);
+		String xsi = null, dns = null, elementNs = null;
+		if (ctx.isEnableNamespaces()) {
+			xsi = ctx.getXsiNamespace().name;
+			dns = elementName == null && ctx.getDefaultNamespace() != null ? ctx.getDefaultNamespace().name : null;
+			elementNs = elementName == null ? dns : ns;
+			if (elementName == null)
+				elementNamespace = null;
+		}
+
+		// Render the start tag.
+		if (! isCollapsed) {
+			out.oTag(indent, elementNs, en, encodeEn);
+			if (addNamespaceUris) {
+				out.attr((String)null, "xmlns", ctx.getDefaultNamespace().getUri());
+
+				for (Namespace n : ctx.getNamespaces())
+					out.attr("xmlns", n.getName(), n.getUri());
+
+				Namespace xsiNs = ctx.getXsiNamespace();
+				if (xsiNs != null)
+					out.attr("xmlns", xsiNs.name, xsiNs.uri);
+			}
+			if (elementName != null && ctx.isAddJsonTypeAttrs() && (ctx.isAddJsonStringTypeAttrs() || ! ts.equals("string")))
+				out.attr(dns, "type", ts);
+			if (classAttr != null)
+				out.attr(dns, "_class", classAttr);
+			if (o == null) {
+				if (! isNullTag)
+					out.attr(xsi, "nil", "true");
+				if ((gType.isBoolean() || gType.isNumber()) && ! gType.isNullable())
+					o = gType.getPrimitiveDefault();
+			}
+
+			if (o != null && !(gType.isMap() || gType.isBean() || gType.hasToObjectMapMethod()))
+				out.append('>');
+
+			if (cr && !(gType.isMap() || gType.isBean() || gType.hasToObjectMapMethod()))
+				out.nl();
+		}
+
+		boolean hasChildren = true;
+
+		// Render the tag contents.
+		if (o != null) {
+			if (gType.isUri() || (pMeta != null && pMeta.isUri()))
+				out.appendUri(o);
+			else if (gType.isCharSequence() || gType.isChar())
+				out.encodeText(o);
+			else if (gType.isNumber() || gType.isBoolean())
+				out.append(o);
+			else if (gType.isMap() || (wType != null && wType.isMap())) {
+				if (o instanceof BeanMap)
+					hasChildren = serializeBeanMap(out, (BeanMap)o, elementNamespace, ctx, isCollapsed);
+				else
+					hasChildren = serializeMap(out, (Map)o, gType, ctx);
+			}
+			else if (gType.hasToObjectMapMethod())
+				hasChildren = serializeMap(out, gType.toObjectMap(o), gType, ctx);
+			else if (gType.isBean())
+				hasChildren = serializeBeanMap(out, bc.forBean(o), elementNamespace, ctx, isCollapsed);
+			else if (gType.isCollection() || (wType != null && wType.isCollection())) {
+				if (isCollapsed)
+					ctx.indent--;
+				serializeCollection(out, (Collection)o, gType, ctx, pMeta);
+				if (isCollapsed)
+					ctx.indent++;
+			}
+			else if (gType.isArray()) {
+				if (isCollapsed)
+					ctx.indent--;
+				serializeCollection(out, toList(gType.getInnerClass(), o), gType, ctx, pMeta);
+				if (isCollapsed)
+					ctx.indent++;
+			}
+			else
+				out.encodeText(o);
+		}
+
+		ctx.pop();
+
+		// Render the end tag.
+		if (! isCollapsed) {
+			if (o == null || ! hasChildren)
+				out.append('/').append('>').nl();
+			else
+				out.i(cr ? indent : 0).eTag(elementNs, en, encodeEn).nl();
+		}
+
+		return out;
+	}
+
+	private boolean serializeMap(XmlSerializerWriter out, Map m, ClassMeta<?> type, XmlSerializerContext ctx) throws IOException, SerializeException {
+
+		m = sort(ctx, m);
+
+		ClassMeta<?> keyType = type.getKeyType(), valueType = type.getValueType();
+
+		boolean hasChildren = false;
+		for (Iterator i = m.entrySet().iterator(); i.hasNext();) {
+			Map.Entry e = (Map.Entry)i.next();
+
+			Object k = e.getKey();
+			if (k == null) {
+				k = "\u0000";
+			} else {
+				k = generalize(ctx, k, keyType);
+			}
+
+			Object value = e.getValue();
+
+			if (! hasChildren) {
+				hasChildren = true;
+				out.append('>').nl();
+			}
+			serializeAnything(out, value, valueType, ctx, k.toString(), null, false, NORMAL, null);
+		}
+		return hasChildren;
+	}
+
+	private boolean serializeBeanMap(XmlSerializerWriter out, BeanMap m, Namespace elementNs, XmlSerializerContext ctx, boolean isCollapsed) throws IOException, SerializeException {
+		boolean hasChildren = false;
+		BeanMeta bm = m.getMeta();
+
+		Map<String,BeanPropertyMeta> xmlAttrs = bm.getXmlMeta().getXmlAttrProperties();
+		Object content = null;
+		for (BeanPropertyMeta p : xmlAttrs.values()) {
+
+			String key = p.getName();
+			Object value = null;
+			try {
+				value = p.get(m);
+			} catch (StackOverflowError e) {
+				throw e;
+			} catch (Throwable x) {
+				ctx.addBeanGetterWarning(p, x);
+			}
+
+			if (canIgnoreValue(ctx, p.getClassMeta(), key, value))
+				continue;
+
+			Namespace ns = (ctx.isEnableNamespaces() && p.getXmlMeta().getNamespace() != elementNs ? p.getXmlMeta().getNamespace() : null);
+
+			if (p.isBeanUri() || p.isUri())
+				out.attrUri(ns, key, value);
+			else
+				out.attr(ns, key, value);
+		}
+
+		boolean hasContent = false;
+
+		for (BeanMapEntry p : (Set<BeanMapEntry>)m.entrySet()) {
+			BeanPropertyMeta pMeta = p.getMeta();
+			XmlFormat xf = pMeta.getXmlMeta().getXmlFormat();
+
+			if (xf == CONTENT) {
+				content = p.getValue();
+				hasContent = true;
+			} else if (xf == ATTR) {
+				// Do nothing
+			} else {
+				String key = p.getKey();
+				Object value = null;
+				try {
+					value = p.getValue();
+				} catch (StackOverflowError e) {
+					throw e;
+				} catch (Throwable x) {
+					ctx.addWarning("Could not call getValue() on property ''{0}'', {1}", key, x.getLocalizedMessage());
+				}
+
+				if (canIgnoreValue(ctx, pMeta.getClassMeta(), key, value))
+					continue;
+
+				if (! hasChildren) {
+					hasChildren = true;
+					out.appendIf(! isCollapsed, '>').nl();
+				}
+				serializeAnything(out, value, pMeta.getClassMeta(), ctx, key, pMeta.getXmlMeta().getNamespace(), false, pMeta.getXmlMeta().getXmlFormat(), pMeta);
+			}
+		}
+		if ((! hasContent) || canIgnoreValue(ctx, string(), null, content))
+			return hasChildren;
+		out.append(">").cr(ctx.indent);
+
+		// Serialize XML content.
+		XmlContentHandler h = bm.getXmlMeta().getXmlContentHandler();
+		if (h != null)
+			try {
+				h.serialize(out, m.getBean());
+			} catch (Exception e) {
+				throw new SerializeException(e);
+			}
+		else
+			out.encodeText(content);
+		out.nl();
+		return true;
+	}
+
+	private XmlSerializerWriter serializeCollection(XmlSerializerWriter out, Collection c, ClassMeta<?> type, XmlSerializerContext ctx, BeanPropertyMeta<?> ppMeta) throws IOException, SerializeException {
+
+		c = sort(ctx, c);
+
+		ClassMeta<?> elementType = type.getElementType();
+
+		String eName = null;
+		Namespace eNs = null;
+
+		if (ppMeta != null) {
+			eName = ppMeta.getXmlMeta().getChildName();
+			eNs = ppMeta.getXmlMeta().getNamespace();
+		}
+
+		if (eName == null) {
+			eName = type.getXmlMeta().getChildName();
+			eNs = type.getXmlMeta().getNamespace();
+		}
+
+		if (eName == null && ! elementType.isObject()) {
+			eName = elementType.getXmlMeta().getElementName();
+			eNs = elementType.getXmlMeta().getNamespace();
+		}
+
+		for (Iterator i = c.iterator(); i.hasNext();) {
+			Object value = i.next();
+			serializeAnything(out, value, elementType, ctx, eName, eNs, false, NORMAL, null);
+		}
+		return out;
+	}
+
+	/**
+	 * Returns the schema serializer based on the settings of this serializer.
+	 * @return The schema serializer.
+	 */
+	public XmlSerializer getSchemaSerializer() {
+		XmlSchemaSerializer s = new XmlSchemaSerializer();
+		s.beanContextFactory = this.beanContextFactory;
+		s.sp = this.sp;
+		s.xsp = this.xsp;
+		return s;
+	}
+
+
+	//--------------------------------------------------------------------------------
+	// Overridden methods
+	//--------------------------------------------------------------------------------
+
+	@Override /* Serializer */
+	protected void doSerialize(Object o, Writer out, SerializerContext ctx) throws IOException, SerializeException {
+		XmlSerializerContext xctx = (XmlSerializerContext)ctx;
+		if (xctx.isEnableNamespaces() && xctx.isAutoDetectNamespaces())
+			findNsfMappings(o, xctx);
+		serializeAnything(xctx.getWriter(out), o, null, xctx, null, null, xctx.isEnableNamespaces() && xctx.isAddNamespaceUrlsToRoot(), NORMAL, null);
+	}
+
+	@Override /* Serializer */
+	public XmlSerializerContext createContext(ObjectMap properties, Method javaMethod) {
+		return new XmlSerializerContext(getBeanContext(), sp, xsp, properties, javaMethod);
+	}
+
+	@Override /* CoreApi */
+	public XmlSerializer setProperty(String property, Object value) throws LockedException {
+		checkLock();
+		if (! xsp.setProperty(property, value))
+			super.setProperty(property, value);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public XmlSerializer setProperties(ObjectMap properties) throws LockedException {
+		for (Map.Entry<String,Object> e : properties.entrySet())
+			setProperty(e.getKey(), e.getValue());
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public XmlSerializer addNotBeanClasses(Class<?>...classes) throws LockedException {
+		super.addNotBeanClasses(classes);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public XmlSerializer addFilters(Class<?>...classes) throws LockedException {
+		super.addFilters(classes);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public <T> XmlSerializer addImplClass(Class<T> interfaceClass, Class<? extends T> implClass) throws LockedException {
+		super.addImplClass(interfaceClass, implClass);
+		return this;
+	}
+
+	@Override /* CoreApi */
+	public XmlSerializer setClassLoader(ClassLoader classLoader) throws LockedException {
+		super.setClassLoader(classLoader);
+		return this;
+	}
+
+	@Override /* Lockable */
+	public XmlSerializer lock() {
+		super.lock();
+		return this;
+	}
+
+	@Override /* Lockable */
+	public XmlSerializer clone() {
+		try {
+			XmlSerializer c = (XmlSerializer)super.clone();
+			c.xsp = xsp.clone();
+			return c;
+		} catch (CloneNotSupportedException e) {
+			throw new RuntimeException(e); // Shouldn't happen.
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializerContext.class
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializerContext.class b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializerContext.class
new file mode 100755
index 0000000..16e777a
Binary files /dev/null and b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializerContext.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/xml/XmlSerializerContext.java
----------------------------------------------------------------------
diff --git a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializerContext.java b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializerContext.java
new file mode 100755
index 0000000..0ea37fa
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/xml/XmlSerializerContext.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * 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.xml;
+
+import static com.ibm.juno.core.xml.NamespaceFactory.*;
+import static com.ibm.juno.core.xml.XmlSerializerProperties.*;
+
+import java.io.*;
+import java.lang.reflect.*;
+
+import com.ibm.juno.core.*;
+import com.ibm.juno.core.serializer.*;
+import com.ibm.juno.core.utils.*;
+
+/**
+ * Context object that lives for the duration of a single serialization of the {@link XmlSerializer}.
+ * <p>
+ * 	See {@link SerializerContext} for details.
+ *
+ * @author James Bognar (jbognar@us.ibm.com)
+ */
+@SuppressWarnings("hiding")
+public class XmlSerializerContext extends SerializerContext {
+
+	private final boolean
+		addJsonTypeAttrs,
+		addJsonStringTypeAttrs,
+		autoDetectNamespaces,
+		enableNamespaces,
+		addNamespaceUrlsToRoot;
+
+	private Namespace
+		defaultNamespace,
+		xsiNamespace,
+		xsNamespace;
+
+	private Namespace[] namespaces = new Namespace[0];
+
+	/**
+	 * Constructor.
+	 * @param beanContext The bean context being used by the serializer.
+	 * @param sp Default general serializer properties.
+	 * @param xsp Default XML serializer properties.
+	 * @param op Override properties.
+	 * @param javaMethod Java method that invoked this serializer.
+	 * 	When using the REST API, this is the Java method invoked by the REST call.
+	 * 	Can be used to access annotations defined on the method or class.
+	 */
+	public XmlSerializerContext(BeanContext beanContext, SerializerProperties sp, XmlSerializerProperties xsp, ObjectMap op, Method javaMethod) {
+		super(beanContext, sp, op, javaMethod);
+		if (op == null || op.isEmpty()) {
+			addJsonTypeAttrs = xsp.addJsonTypeAttrs;
+			addJsonStringTypeAttrs = xsp.addJsonStringTypeAttrs;
+			enableNamespaces = xsp.enableNamespaces;
+			autoDetectNamespaces = xsp.autoDetectNamespaces;
+			addNamespaceUrlsToRoot = xsp.addNamespaceUrlsToRoot;
+			addNamespaces(xsp.namespaces);
+			setDefaultNamespace(xsp.defaultNamespace);
+			xsiNamespace = xsp.xsiNamespace;
+			xsNamespace = xsp.xsNamespace;
+		} else {
+			addJsonTypeAttrs = op.getBoolean(XML_addJsonTypeAttrs, xsp.addJsonTypeAttrs);
+			addJsonStringTypeAttrs = op.getBoolean(XML_addJsonStringTypeAttrs, xsp.addJsonStringTypeAttrs);
+			enableNamespaces = op.getBoolean(XML_enableNamespaces, xsp.enableNamespaces);
+			autoDetectNamespaces = op.getBoolean(XML_autoDetectNamespaces, xsp.autoDetectNamespaces);
+			addNamespaceUrlsToRoot = op.getBoolean(XML_addNamespaceUrisToRoot, xsp.addNamespaceUrlsToRoot);
+			namespaces = (op.containsKey(XML_namespaces) ? parseNamespaces(op.get(XML_namespaces)) : xsp.namespaces);
+			setDefaultNamespace(op.containsKey(XML_defaultNamespaceUri) ? op.getString(XML_defaultNamespaceUri) : xsp.defaultNamespace);
+			xsiNamespace = (op.containsKey(XML_xsiNamespace) ? parseNamespace(op.get(XML_xsiNamespace)) : xsp.xsiNamespace);
+			xsNamespace = (op.containsKey(XML_xsNamespace) ? parseNamespace(op.get(XML_xsNamespace)) : xsp.xsNamespace);
+		}
+	}
+
+	private void setDefaultNamespace(String s) {
+		if (s == null)
+			return;
+		if (StringUtils.startsWith(s, '{'))
+			defaultNamespace = parseNamespace(s);
+		else if (! s.startsWith("http://"))
+			defaultNamespace = get(s, "http://unknown");
+		else
+			defaultNamespace = get(null, s);
+	}
+
+	private void addNamespaces(Namespace...namespaces) {
+		for (Namespace ns : namespaces)
+			addNamespace(ns);
+	}
+
+	void addNamespace(Namespace ns) {
+		if (ns == defaultNamespace)
+			return;
+
+		for (Namespace n : namespaces)
+			if (n == ns)
+				return;
+
+		if (defaultNamespace != null && (ns.uri.equals(defaultNamespace.uri) || ns.name.equals(defaultNamespace.name)))
+			defaultNamespace = ns;
+		else
+			namespaces = ArrayUtils.append(namespaces, ns);
+	}
+
+	/**
+	 * Returns the list of namespaces being used in the current XML serialization.
+	 *
+	 * @return The list of namespaces being used in the current XML serialization.
+	 */
+	public Namespace[] getNamespaces() {
+		return namespaces;
+	}
+
+	/**
+	 * Returns the {@link XmlSerializerProperties#XML_addJsonTypeAttrs} setting value in this context.
+	 *
+	 * @return The {@link XmlSerializerProperties#XML_addJsonTypeAttrs} setting value in this context.
+	 */
+	public final boolean isAddJsonTypeAttrs() {
+		return addJsonTypeAttrs;
+	}
+
+	/**
+	 * Returns the {@link XmlSerializerProperties#XML_addJsonStringTypeAttrs} setting value in this context.
+	 *
+	 * @return The {@link XmlSerializerProperties#XML_addJsonStringTypeAttrs} setting value in this context.
+	 */
+	public final boolean isAddJsonStringTypeAttrs() {
+		return addJsonStringTypeAttrs;
+	}
+
+	/**
+	 * Returns the {@link XmlSerializerProperties#XML_autoDetectNamespaces} setting value in this context.
+	 *
+	 * @return The {@link XmlSerializerProperties#XML_autoDetectNamespaces} setting value in this context.
+	 */
+	public final boolean isAutoDetectNamespaces() {
+		return enableNamespaces && autoDetectNamespaces;
+	}
+
+	/**
+	 * Returns the {@link XmlSerializerProperties#XML_enableNamespaces} setting value in this context.
+	 *
+	 * @return The {@link XmlSerializerProperties#XML_enableNamespaces} setting value in this context.
+	 */
+	public final boolean isEnableNamespaces() {
+		return enableNamespaces;
+	}
+
+	/**
+	 * Returns the {@link XmlSerializerProperties#XML_addNamespaceUrisToRoot} setting value in this context.
+	 *
+	 * @return The {@link XmlSerializerProperties#XML_addNamespaceUrisToRoot} setting value in this context.
+	 */
+	public final boolean isAddNamespaceUrlsToRoot() {
+		return addNamespaceUrlsToRoot;
+	}
+
+	/**
+	 * Returns the {@link XmlSerializerProperties#XML_defaultNamespaceUri} setting value in this context.
+	 *
+	 * @return The {@link XmlSerializerProperties#XML_defaultNamespaceUri} setting value in this context.
+	 */
+	public final Namespace getDefaultNamespace() {
+		return defaultNamespace;
+	}
+
+	/**
+	 * Returns the {@link XmlSerializerProperties#XML_xsiNamespace} setting value in this context.
+	 *
+	 * @return The {@link XmlSerializerProperties#XML_xsiNamespace} setting value in this context.
+	 */
+	public final Namespace getXsiNamespace() {
+		return xsiNamespace;
+	}
+
+	/**
+	 * Returns the {@link XmlSerializerProperties#XML_xsNamespace} setting value in this context.
+	 *
+	 * @return The {@link XmlSerializerProperties#XML_xsNamespace} setting value in this context.
+	 */
+	public final Namespace getXsNamespace() {
+		return xsNamespace;
+	}
+
+	/**
+	 * Wraps the specified writer in a {@link XmlSerializerWriter} if it is not already an instance of that class.
+	 *
+	 * @param out The writer being wrapped.
+	 * @return The wrapped writer.
+	 */
+	public XmlSerializerWriter getWriter(Writer out) {
+		if (out instanceof XmlSerializerWriter)
+			return (XmlSerializerWriter)out;
+		return new XmlSerializerWriter(out, isUseIndentation(), getQuoteChar(), getRelativeUriBase(), getAbsolutePathUriBase(), isEnableNamespaces(), getDefaultNamespace());
+	}
+}

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