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 ([email protected])
+ */
+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 ([email protected])
+ */
+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 ([email protected])
+ */
+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 ([email protected])
+ */
+@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 ([email protected])
+ */
+@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 ([email protected])
+ */
+@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

Reply via email to