package org.codehaus.stax.test.stream;

import java.util.Iterator;

import javax.xml.XMLConstants;
import javax.xml.namespace.*;
import javax.xml.stream.*;

/**
 * Unit test suite that tests handling of the namespace declarations,
 * both in namespace aware and non-namespace modes.
 *
 * @author Tatu Saloranta
 */
public class TestNamespaces
    extends BaseStreamTest
{
    final String VALID_NS_XML
        = "<root xmlns:a='myurl' attr1='value' a:attr1=''>"
        +"<a:branch xmlns='someurl' xmlns:a='whatever' attr='value'>"
        +"<leaf a='xxx' a:a='yyy' />"
        +"</a:branch>"
        +"</root>";

    public void testValidNs()
        throws XMLStreamException
    {
        XMLStreamReader sr = getNsReader(VALID_NS_XML, true);
        assertEquals(START_ELEMENT, sr.next());
        assertEquals(1, sr.getNamespaceCount());
        assertEquals(2, sr.getAttributeCount());
        // element properties:
        assertNoPrefix(sr);
        assertEquals("root", sr.getLocalName());
        assertNoNsURI(sr);
        // ns/attr properties:
        assertEquals("value", sr.getAttributeValue(null, "attr1"));
        assertEquals("", sr.getAttributeValue("myurl", "attr1"));

        checkIllegalAttributeIndexes(sr);

        // Shouldn't be able to use prefix, just URI:
        assertNull(sr.getAttributeValue("xmlns", "a"));
        assertEquals("myurl", sr.getNamespaceURI("a"));
        assertNull(sr.getNamespaceURI("myurl"));
        /* 07-Sep-2007, TSa: This is a tough call, but I do believe
         *   we should expect "no namespace" as the answer (== ""), not
         *   "unbound" (null).
         */
        //assertNull(sr.getNamespaceURI(""));
        assertEquals("", sr.getNamespaceURI(""));

        assertNull(sr.getNamespaceURI("nosuchurl"));

        NamespaceContext nc = sr.getNamespaceContext();
        assertNotNull(nc);
        assertEquals(XMLConstants.XML_NS_URI, nc.getNamespaceURI(XMLConstants.XML_NS_PREFIX));
        assertEquals(XMLConstants.XML_NS_PREFIX, nc.getPrefix(XMLConstants.XML_NS_URI));
        assertEquals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, nc.getNamespaceURI(XMLConstants.XMLNS_ATTRIBUTE));
        assertEquals(XMLConstants.XMLNS_ATTRIBUTE, nc.getPrefix(XMLConstants.XMLNS_ATTRIBUTE_NS_URI));

        assertEquals("myurl", nc.getNamespaceURI("a"));
        assertEquals("a", nc.getPrefix("myurl"));
        Iterator<?> it = nc.getPrefixes("foobar");
        // Hmmmh. Can it be null or not? For now let's allow null too
        if (it == null) {
            ;
        } else {
            assertFalse(it.hasNext());
        }
        it = nc.getPrefixes("myurl");
        assertNotNull(it);
        assertTrue(it.hasNext());
        assertEquals("a", (String) it.next());
        assertFalse(it.hasNext());

        // // Ok, then the second element:

        assertEquals(START_ELEMENT, sr.next());
        assertEquals(2, sr.getNamespaceCount());
        assertEquals(1, sr.getAttributeCount());
        assertEquals("a", sr.getPrefix());
        assertEquals("branch", sr.getLocalName());

        assertEquals("whatever", sr.getNamespaceURI());
        assertEquals("value", sr.getAttributeValue(null, "attr"));
        assertEquals("value", sr.getAttributeValue(0));

        assertEquals("someurl", sr.getNamespaceURI(""));

        // // And finally the third

        assertEquals(START_ELEMENT, sr.next());
        assertEquals(0, sr.getNamespaceCount());
        assertEquals(2, sr.getAttributeCount());
        assertEquals("leaf", sr.getLocalName());
        assertNoPrefix(sr);
        assertEquals("yyy", sr.getAttributeValue("whatever", "a"));
        assertEquals("xxx", sr.getAttributeValue(null, "a"));

        assertEquals(END_ELEMENT, sr.next());
        assertEquals(0, sr.getNamespaceCount());
        assertEquals("leaf", sr.getLocalName());
        assertNoPrefix(sr);

        assertEquals(END_ELEMENT, sr.next());
        assertEquals(2, sr.getNamespaceCount());
        assertEquals("a", sr.getPrefix());
        assertEquals("branch", sr.getLocalName());

        assertEquals(END_ELEMENT, sr.next());
        assertEquals(1, sr.getNamespaceCount());
        assertNoNsURI(sr);
        assertEquals("root", sr.getLocalName());

        assertEquals(END_DOCUMENT, sr.next());
        assertFalse(sr.hasNext());
    }

    final String VALID_NS_XML2
        ="<?xml version='1.0' ?>"
        +"<root xmlns:a='myurl' xmlns=\"http://foo\">text"
        +"<empty attr='&amp;'/><a:empty /></root>";

    /**
     * Another unit test that checks that valid namespace declarations
     * are handled properly.
     */
    public void testMultipleValidNs()
        throws XMLStreamException
    {
        XMLStreamReader sr = getNsReader(VALID_NS_XML2, true);
        assertEquals(START_ELEMENT, sr.next());

        // Let's thoroughly check the root elem
        assertEquals(2, sr.getNamespaceCount());
        assertEquals(0, sr.getAttributeCount());
        assertNoPrefix(sr);
        assertEquals("root", sr.getLocalName());
        assertEquals("http://foo", sr.getNamespaceURI());
        assertEquals("myurl", sr.getNamespaceURI("a"));

        // first empty elem
        while (sr.next() == CHARACTERS) { }
        assertTokenType(START_ELEMENT, sr.getEventType());
        assertEquals(0, sr.getNamespaceCount());
        assertEquals(1, sr.getAttributeCount());
        assertNoPrefix(sr);
        assertEquals("empty", sr.getLocalName());
        assertEquals("http://foo", sr.getNamespaceURI());
        assertEquals("myurl", sr.getNamespaceURI("a"));
        assertNoAttrNamespace(sr.getAttributeNamespace(0));
        assertNoAttrPrefix(sr.getAttributePrefix(0));
        assertEquals("&", sr.getAttributeValue(0));
        assertTokenType(END_ELEMENT, sr.next());

        // second empty elem
        assertTokenType(START_ELEMENT, sr.next());
        assertEquals(0, sr.getNamespaceCount());
        assertEquals(0, sr.getAttributeCount());
        assertEquals("empty", sr.getLocalName());
        assertEquals("a", sr.getPrefix());
        assertEquals("myurl", sr.getNamespaceURI());
        assertEquals("myurl", sr.getNamespaceURI("a"));
        assertEquals("http://foo", sr.getNamespaceURI(""));
        assertTokenType(END_ELEMENT, sr.next());

        // And closing 'root'
        assertTokenType(END_ELEMENT, sr.next());
        assertEquals("root", sr.getLocalName());
        assertEquals("http://foo", sr.getNamespaceURI());

        assertTokenType(END_DOCUMENT, sr.next());
    }

    /**
     * Test proper handling of valid xml content in non-namespace aware mode.
     * Since not all implementations (like the ref. impl.) support non-ns
     * aware mode, this unit test is skipped if not applicable.
     */
    public void testValidNonNs()
        throws XMLStreamException
    {
        XMLStreamReader sr = getNsReader(VALID_NS_XML, false);
        if (sr == null) {
            reportNADueToNS("testValidNonNs");
            return;
        }

        assertEquals(START_ELEMENT, sr.next());
        assertEquals(0, sr.getNamespaceCount());
        assertEquals(3, sr.getAttributeCount());
        // element properties:
        assertNoPrefix(sr);
        assertEquals("root", sr.getLocalName());

        assertNoNsURI(sr);
        // ns/attr properties:

        assertEquals("value", sr.getAttributeValue(null, "attr1"));
        assertEquals(null, sr.getAttributeValue(null, "foobar"));

        checkIllegalAttributeIndexes(sr);

        /* ... not sure if how namespace access should work, ie. is it ok
         * to throw an exception, return null or what
         */

        // // Ok, then the second element:

        assertEquals(START_ELEMENT, sr.next());
        assertEquals(0, sr.getNamespaceCount());
        assertEquals(3, sr.getAttributeCount());
        assertEquals("a:branch", sr.getLocalName());
        assertNoPrefix(sr);

        // // And finally the third

        assertEquals(START_ELEMENT, sr.next());
        assertEquals(0, sr.getNamespaceCount());
        assertEquals(2, sr.getAttributeCount());
        assertEquals("leaf", sr.getLocalName());
        assertNoPrefix(sr);
        assertEquals("xxx", sr.getAttributeValue(null, "a"));
        assertEquals("yyy", sr.getAttributeValue(null, "a:a"));

        // // And then the end elements

        assertEquals(END_ELEMENT, sr.next());
        assertEquals(0, sr.getNamespaceCount());
        assertEquals("leaf", sr.getLocalName());
        assertNoPrefix(sr);

        assertEquals(END_ELEMENT, sr.next());
        assertEquals(0, sr.getNamespaceCount());
        assertEquals("a:branch", sr.getLocalName());
        assertNoPrefix(sr);

        assertEquals(END_ELEMENT, sr.next());
        assertEquals(0, sr.getNamespaceCount());
        assertNoPrefix(sr);
        assertEquals("root", sr.getLocalName());

        assertEquals(END_DOCUMENT, sr.next());
        assertFalse(sr.hasNext());
    }

    public void testInvalidNs()
        throws XMLStreamException
    {
        testPotentiallyInvalid(true, "testInvalidNs");
    }

    public void testInvalidNonNs()
        throws XMLStreamException
    {
        // Some things are ok, some not, when namespace support is not enabled:
        testPotentiallyInvalid(false, "testInvalidNonNs");
    }

    public void testInvalidStandardBindings()
        throws XMLStreamException
    {
        doTestXmlBinding(true, "testInvalidStandardBindings");
        doTestXmlnsBinding(true, "testInvalidStandardBindings");
    }

    public void testInvalidStandardBindingsNonNs()
        throws XMLStreamException
    {
        doTestXmlBinding(false, "testInvalidStandardBindingsNonNs");
        doTestXmlnsBinding(false, "testInvalidStandardBindingsNonNs");
    }

    public void testDefaultNs()
        throws XMLStreamException
    {
        String XML = "<root xmlns='url' />";

        XMLStreamReader sr = getNsReader(XML, true);
        assertEquals(START_ELEMENT, sr.next());
        assertEquals("root", sr.getLocalName());
        assertEquals("url", sr.getNamespaceURI());
        assertNoPrefix(sr);
        NamespaceContext ctxt = sr.getNamespaceContext();
        assertEquals(1, sr.getNamespaceCount());
        assertEquals("url", sr.getNamespaceURI(0));
        assertNoAttrPrefix(sr.getNamespacePrefix(0));

        assertEquals("url", ctxt.getNamespaceURI(""));
        assertEquals("", ctxt.getPrefix("url"));
        assertNull(ctxt.getNamespaceURI("b"));
        assertNull(ctxt.getPrefix("ns:b"));


        XML = "<root xmlns:a='url' />";

        sr = getNsReader(XML, true);
        assertEquals(START_ELEMENT, sr.next());
        assertEquals("root", sr.getLocalName());
        assertNoPrefix(sr);
        assertNoNsURI(sr);
        assertEquals(1, sr.getNamespaceCount());
        assertEquals("url", sr.getNamespaceURI(0));
        assertEquals("a", sr.getNamespacePrefix(0));
    }

    /**
     * Test case that verifies that namespaces properly nest, and
     * inner definitions (ns in child element) can mask outer
     * definitions (ns in parent element)
     */
    public void testMaskingNs()
        throws XMLStreamException
    {
        final String XML =
            "<a:root xmlns:a='ns:a'><a:child xmlns:a='ns:b' /></a:root>";

        XMLStreamReader sr = getNsReader(XML, true);
        assertEquals(START_ELEMENT, sr.next());
        assertEquals("root", sr.getLocalName());
        assertEquals("a", sr.getPrefix());
        assertEquals("ns:a", sr.getNamespaceURI());
        NamespaceContext ctxt = sr.getNamespaceContext();
        assertEquals("ns:a", ctxt.getNamespaceURI("a"));
        assertNull(ctxt.getNamespaceURI("b"));
        assertEquals("a", ctxt.getPrefix("ns:a"));
        assertNull(ctxt.getPrefix("ns:b"));

        assertEquals(START_ELEMENT, sr.next());
        assertEquals("child", sr.getLocalName());
        assertEquals("a", sr.getPrefix());
        assertEquals("ns:b", sr.getNamespaceURI());

        ctxt = sr.getNamespaceContext();
        assertEquals("ns:b", ctxt.getNamespaceURI("a"));
        assertEquals("a", ctxt.getPrefix("ns:b"));
        assertNull(ctxt.getNamespaceURI("b"));

        // This is testing of actual masking, using NamespaceContext
        {
            // Previous binding should be masked by now!
            String prefix = ctxt.getPrefix("ns:a");
            if (prefix != null) {
                fail("Failed: second declaration for prefix 'a' should have masked previous one; and there should not be a prefix for 'ns:a'. Instead, prefix '"+prefix+"' was considered to (still) be bound");
            }
        }
    }

    /**
     * Unit test that verifies that the default namespace masking works
     * as expected.
     */
    public void testMaskingDefaultNs()
        throws XMLStreamException
    {
        final String XML =
            "<root xmlns='someurl'>"
            +"<branch xmlns=''><leaf /><leaf xmlns='anotherurl' />"
            +"</branch></root>"
            ;

        XMLStreamReader sr = getNsReader(XML, true);
        assertEquals(START_ELEMENT, sr.next());
        assertEquals("root", sr.getLocalName());
        assertNoPrefix(sr);
        assertEquals("someurl", sr.getNamespaceURI());
        assertEquals(1, sr.getNamespaceCount());

        assertEquals(START_ELEMENT, sr.next());
        assertEquals("branch", sr.getLocalName());
        assertNoPrefix(sr);
        assertNoNsURI(sr);
        assertEquals(1, sr.getNamespaceCount());

        assertEquals(START_ELEMENT, sr.next());
        assertEquals("leaf", sr.getLocalName());
        assertNoPrefix(sr);
        assertNoNsURI(sr);
        assertEquals(0, sr.getNamespaceCount());
        assertEquals(END_ELEMENT, sr.next()); // leaf
        assertEquals(0, sr.getNamespaceCount());

        assertEquals(START_ELEMENT, sr.next());
        assertEquals("leaf", sr.getLocalName());
        assertNoPrefix(sr);
        assertEquals("anotherurl", sr.getNamespaceURI());
        assertEquals(1, sr.getNamespaceCount());
        assertEquals(END_ELEMENT, sr.next()); // leaf
        assertEquals(1, sr.getNamespaceCount());

        assertEquals(END_ELEMENT, sr.next()); // branch
        assertEquals(1, sr.getNamespaceCount());

        assertEquals(END_ELEMENT, sr.next()); // root
        assertEquals(1, sr.getNamespaceCount());
    }

    /**
     * This specialized test case verifies that there are no
     * unbinding of explict namespace prefixes in xml 1.0
     * documents. While namespaces 1.1 (and hence, xml 1.0)
     * makes such use legal, xml 1.0 does not allow it.
     */
    public void testUnbindingInvalindInXml10()
        throws XMLStreamException
    {
        final String XML =
            "<?xml version='1.0'?><root xmlns:ns='http://ns'><branch xmlns:ns='' /></root>";

        XMLStreamReader sr = getNsReader(XML, true);
        assertEquals(START_ELEMENT, sr.next());
        assertEquals("root", sr.getLocalName());
        assertNoPrefix(sr);        

        try {
            sr.next(); // start_element, usually throws exc her
            sr.next(); // but if not, at least should do it before end element
            fail("Expected an exception when trying to unbind namespace mapping for prefix 'ns': not legal in xml 1.0 documents");
        } catch (XMLStreamException e) {
            // good
        }
        sr.close();
    }

    /**
     * Unit test that verifies that the namespace with prefix 'xml' is
     * always predefined without further work.
     */
    public void testPredefinedXmlNs()
        throws XMLStreamException
    {
        final String XML = "<root xml:lang='fi'><xml:a /></root>";

        XMLStreamReader sr = getNsReader(XML, true);
        assertEquals(START_ELEMENT, sr.next());
        assertEquals("xml", sr.getAttributePrefix(0));
        assertEquals("lang", sr.getAttributeLocalName(0));
        assertEquals(XMLConstants.XML_NS_URI, sr.getAttributeNamespace(0));
        assertEquals(START_ELEMENT, sr.next());
        assertEquals("xml", sr.getPrefix());
        assertEquals("a", sr.getLocalName());
        assertEquals(XMLConstants.XML_NS_URI, sr.getNamespaceURI());
        assertEquals(END_ELEMENT, sr.next());
        assertEquals(END_ELEMENT, sr.next());
    }

    /**
     * This test verifies that "no namespace" is correctly reported. At
     * this point definition of correct handling is not complete, so
     * it'll only test cases for which there is clear consensus.
     */
    public void testNoNamespace()
        throws XMLStreamException
    {
        String XML = "<root xmlns=''>xyz</root>";
        XMLStreamReader sr = getNsReader(XML, true);
        assertEquals(START_ELEMENT, sr.next());
        assertEquals(1, sr.getNamespaceCount());

        /* 21-Jul-2006, TSa:
         * URI returned for namespace declarations (different from URI
         * of the element, or attributes) should be the lexical value,
         * that is, for "no namespace" it should be "", not null.
         */
        assertEquals("", sr.getNamespaceURI(0));

        /* Too bad there's no consensus on what actual element URI
         * should be: both null and "" have their supporters... ;-)
         */
        sr.close();
    }

    /*
    ////////////////////////////////////////
    // Private methods, shared test code
    ////////////////////////////////////////
     */

    private void checkIllegalAttributeIndexes(XMLStreamReader sr)
        throws XMLStreamException
    {
        /* 26-Jan-2008, TSa: Javadocs/stax specs do not actually specify
         *   what should happen if an illegal index is given.
         *   So while it seems logical that we'd throw an exception,
         *   we can not count on that. Let's rather just check that
         *   we either get an exception, or empty (null or "") value;
         *   and if latter, just warn.
         */
        try {
            String str = sr.getAttributeValue(-1);
            if (str != null) {
                if (str.length() > 0) {
                    fail("Did not expect to find a non-empty value when trying to access attribute #-1, got '"+str+"'");
                }
            }
            warn("Did not get an exception when calling sr.getAttributeValue(-1): seems odd, but legal?");
        } catch (Exception e) { }

        int count = sr.getAttributeCount();
        try {
            String str = sr.getAttributeValue(count);
            if (str != null) {
                if (str.length() > 0) {
                    fail("Did not expect to find a non-empty value when trying to access attribute #"+count+" [with element only having "+count+" attribute(s)], got '"+str+"'");
                }
            }
            warn("Did not get an exception when calling sr.getAttributeValue("+count+"): [with element only having "+count+" attribute(s)] seems odd, but legal?");
        } catch (Exception e) { }
    }

    private void testPotentiallyInvalid(boolean nsAware, String method)
        throws XMLStreamException
    {
        // First, check that undeclared namespace prefixes are not kosher
        try {
            XMLStreamReader sr = getNsReader("<ns1:elem />", nsAware);
            if (sr == null) {
                reportNADueToNS(method);
                return;
            }
            
            streamThrough(sr);
            if (nsAware) {
                fail("Was expecting an exception for content that uses undeclared namespace prefix.");
            }
        } catch (Exception e) {
            if (!nsAware) {
                fail("Was not expecting an exception for undeclared namespace when namespaces support not enabled: "+e);
            }
        }

        // Plus, can't redeclare default namespace
        try {
            XMLStreamReader sr = getNsReader("<elem xmlns='aaa' xmlns='bbb' />",
                                             nsAware);
            streamThrough(sr);
            fail("Was expecting an exception for content that has duplicate declaration of the default namespace.");
        } catch (Exception e) {
            ; // both should get here
        }

        // Nor other prefixes
        try {
            XMLStreamReader sr = getNsReader("<elem xmlns:a='aaa' xmlns:a='bbb' />",
                                             nsAware);
            streamThrough(sr);
            fail("Was expecting an exception for content that has duplicate declaration for a prefix.");
        } catch (Exception e) {
            ; // both should get here
        }

        /* And then, two attribute names may be equivalent if prefixes
         * point to same URI; but only in namespace-aware mode
         */
        try {
            XMLStreamReader sr = getNsReader
                ("<elem xmlns:a=\"aaa\" xmlns:b='aaa' a:attr1='1' b:attr1=\"2\" />",
                 nsAware);
            streamThrough(sr);
            if (nsAware) {
                fail("Was expecting an exception for content that has duplicate attribute (even though prefixes differ, they point to the same URI)");
            }
        } catch (Exception e) {
            if (!nsAware) {
                fail("Was NOT expecting an exception since in non-namespace mode attributes 'a:attr1' and 'b:attr1' are not equivalent: "+e);
            }
        }
    }

    private void doTestXmlBinding(boolean nsAware, String method)
        throws XMLStreamException
    {
        // And 'xml' can only be bound to its correct URI
        { // this should be fine
            XMLStreamReader sr = getNsReader("<elem xmlns:xml='"+XMLConstants.XML_NS_URI+"' />", nsAware);
            if (sr == null) {
                reportNADueToNS(method);
                return;
            }
            streamThrough(sr);
        }

        // But not to anything else:
        try {
            XMLStreamReader sr = getNsReader("<elem xmlns:xml='xxx' />", nsAware);
            streamThrough(sr);
            if (nsAware) {
                fail("Was expecting an exception for content that tries to redeclare 'xml' to different URI.");
            }
        } catch (Exception e) {
            if (!nsAware) {
                fail("Was not expecting an exception for redeclaration of 'xml' when namespace support not enabled: "+e);
            }
        }

        // Also, nothing else can bind to that URI, neither explicit prefix
        try {
            XMLStreamReader sr = getNsReader("<elem xmlns:foo='"+XMLConstants.XML_NS_URI+"' />", nsAware);
            streamThrough(sr);
            if (nsAware) {
                fail("Was expecting an exception for content that tries to bind prefix other than 'xml' to URI '"+XMLConstants.XML_NS_URI+"'");
            }
        } catch (Exception e) {
            if (!nsAware) {
                fail("Was not expecting an exception for binding 'xml' URI");
            }
        }

        // Nor default namespace
        try {
            XMLStreamReader sr = getNsReader("<elem xmlns='"+XMLConstants.XML_NS_URI+"' />", nsAware);
            streamThrough(sr);
            if (nsAware) {
                fail("Was expecting an exception for content that tries to bind the default namespace to 'xml' URI '"+XMLConstants.XML_NS_URI+"'");
            }
        } catch (Exception e) {
            if (!nsAware) {
                fail("Was not expecting an exception for binding default namespace to 'xml' URI");
            }
        }
    }

    private void doTestXmlnsBinding(boolean nsAware, String method)
        throws XMLStreamException
    {
        // Illegal to try to (re)declare 'xmlns' in any way
        try {
            XMLStreamReader sr = getNsReader("<elem xmlns:xmlns='yyy' />", nsAware);
            if (sr == null) {
                reportNADueToNS(method);
                return;
            }
            streamThrough(sr);
            if (nsAware) {
                fail("Was expecting an exception for content that tries to redeclare 'xml' or 'xmlns' to different URI.");
            }
        } catch (Exception e) {
            if (!nsAware) {
                fail("Was not expecting an exception for redeclaration of 'xmlns' when namespace support not enabled: "+e);
            }
        }

        // Also, nothing else can bind to that URI, neither explicit prefix
        try {
            XMLStreamReader sr = getNsReader("<elem xmlns:foo='"+XMLConstants.XMLNS_ATTRIBUTE_NS_URI+"' />", nsAware);
            streamThrough(sr);
            if (nsAware) {
                fail("Was expecting an exception for content that tries to bind prefix other than 'xml' to URI '"+XMLConstants.XMLNS_ATTRIBUTE_NS_URI+"'");
            }
        } catch (Exception e) {
            if (!nsAware) {
                fail("Was not expecting an exception for binding 'xml' URI");
            }
        }

        // Nor default namespace
        try {
            XMLStreamReader sr = getNsReader("<elem xmlns='"+XMLConstants.XMLNS_ATTRIBUTE_NS_URI+"' />", nsAware);
            streamThrough(sr);
            if (nsAware) {
                fail("Was expecting an exception for content that tries to bind the default namespace to 'xml' URI '"+XMLConstants.XMLNS_ATTRIBUTE_NS_URI+"'");
            }
        } catch (Exception e) {
            if (!nsAware) {
                fail("Was not expecting an exception for binding default namespace to 'xml' URI");
            }
        }
    }

    /*
    ////////////////////////////////////////
    // Private methods, other
    ////////////////////////////////////////
     */

    /**
     * @return Stream reader constructed if initialization succeeded (all
     *   setting supported by the impl); null if some settings (namespace
     *   awareness) not supported.
     */
    private XMLStreamReader getNsReader(String contents, boolean nsAware)
        throws XMLStreamException
    {
        XMLInputFactory f = getInputFactory();
        if (!setNamespaceAware(f, nsAware)) {
            return null;
        }
        setCoalescing(f, true);
        setValidating(f, false);
        return constructStreamReader(f, contents);
    }
}
