/*
 This Java source file was generated by test-to-java.xsl
 and is a derived work from the source document.
 The source document contained the following notice:



 Copyright (c) 2001-2004 World Wide Web Consortium,
 (Massachusetts Institute of Technology, Institut National de
 Recherche en Informatique et en Automatique, Keio University).  All
 Rights Reserved.  This program is distributed under the W3C's Software
 Intellectual Property License.  This program is distributed in the
 hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.

 See W3C License http://www.w3.org/Consortium/Legal/ for more details.


 */

package tests.org.w3c.dom;

import org.w3c.dom.Element;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;

import javax.xml.parsers.DocumentBuilder;

/**
 * The "setAttributeNode(newAttr)" method raises an "INUSE_ATTRIBUTE_ERR
 * DOMException if the "newAttr" is already an attribute of another element.
 *
 * Retrieve the first emp:address and append a newly created element. The
 * "createAttributeNS(namespaceURI,qualifiedName)" and
 * "setAttributeNodeNS(newAttr)" methods are invoked to create and add a new
 * attribute to the newly created Element. The "setAttributeNodeNS(newAttr)"
 * method is once again called to add the new attribute causing an exception to
 * be raised since the attribute is already an attribute of another element.
 *
 * @author NIST
 * @author Mary Brady
 * @see <a
 *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INUSE_ATTRIBUTE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-258A00AF')/constant[@name='INUSE_ATTRIBUTE_ERR'])</a>
 * @see <a
 *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAtNodeNS">http://www.w3.org/TR/DOM-Level-2-Core/core#ID-ElSetAtNodeNS</a>
 * @see <a
 *      href="http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElSetAtNodeNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INUSE_ATTRIBUTE_ERR'])">http://www.w3.org/TR/DOM-Level-2-Core/core#xpointer(id('ID-ElSetAtNodeNS')/raises/exception[@name='DOMException']/descr/p[substring-before(.,':')='INUSE_ATTRIBUTE_ERR'])</a>
 */
public final class SetAttributeNodeNS extends DOMTestCase {

    DOMDocumentBuilderFactory factory;

    DocumentBuilder builder;

    protected void setUp() throws Exception {
        super.setUp();
        try {
            factory = new DOMDocumentBuilderFactory(DOMDocumentBuilderFactory
                    .getConfiguration2());
            builder = factory.getBuilder();
        } catch (Exception e) {
            fail("Unexpected exception" + e.getMessage());
        }
    }

    protected void tearDown() throws Exception {
        factory = null;
        builder = null;
        super.tearDown();
    }

    /**
     * Runs the test case.
     *
     * @throws Throwable
     *             Any uncaught exception causes test to fail
     */
    public void testSetAttributeNode1() throws Throwable {
        String namespaceURI = "http://www.newattr.com";
        String qualifiedName = "emp:newAttr";
        Document doc;
        Element newElement;
        Attr newAttr;
        NodeList elementList;
        Node testAddr;

        doc = (Document) load("staffNS", builder);
        elementList = doc.getElementsByTagName("emp:address");
        testAddr = elementList.item(0);
        assertNotNull("empAddrNotNull", testAddr);
        newElement = doc.createElement("newElement");
        testAddr.appendChild(newElement);
        newAttr = doc.createAttributeNS(namespaceURI, qualifiedName);
        newElement.setAttributeNodeNS(newAttr);

        {
            boolean success = false;
            try {
                ((Element) /* Node */testAddr).setAttributeNodeNS(newAttr);
            } catch (DOMException ex) {
                success = (ex.code == DOMException.INUSE_ATTRIBUTE_ERR);
            }
            assertTrue("throw_INUSE_ATTRIBUTE_ERR", success);
        }
    }

// Assumes validation.
//    public void testSetAttributeNode2() throws Throwable {
//        Document doc;
//        NodeList genderList;
//        Node gender;
//        NodeList genList;
//        Node gen;
//        NodeList gList;
//        Element genElement;
//        Attr newAttr;
//
//        doc = (Document) load("staffNS", builder);
//
//        if (!factory.isExpandEntityReferences()) {
//            genderList = doc.getElementsByTagName("gender");
//            gender = genderList.item(2);
//            genList = gender.getChildNodes();
//            gen = genList.item(0);
//        } else {
//            gen = doc.createEntityReference("ent4");
//        }
//
//        gList = gen.getChildNodes();
//        genElement = (Element) gList.item(0);
//        assertNotNull("notnull", genElement);
//        newAttr = doc.createAttributeNS("www.xyz.com", "emp:local1");
//
//        {
//            boolean success = false;
//            try {
//                genElement.setAttributeNodeNS(newAttr);
//            } catch (DOMException ex) {
//                success = (ex.code == DOMException.NO_MODIFICATION_ALLOWED_ERR);
//            }
//            assertTrue("throw_NO_MODIFICATION_ALLOWED_ERR", success);
//        }
//    }
    public void testSetAttributeNode3() throws Throwable {
        String namespaceURI = "http://www.newattr.com";
        String qualifiedName = "emp:newAttr";
        Document doc;
        NodeList elementList;
        Node testAddr;
        Attr newAttr;
        Attr newAddrAttr;
        doc = (Document) load("staffNS", builder);
        elementList = doc.getElementsByTagName("emp:address");
        testAddr = elementList.item(0);
        assertNotNull("empAddrNotNull", testAddr);
        newAttr = doc.createAttributeNS(namespaceURI, qualifiedName);
        newAddrAttr = ((Element) /* Node */testAddr)
                .setAttributeNodeNS(newAttr);
        assertNull("throw_Null", newAddrAttr);
    }
    public void testSetAttributeNode4() throws Throwable {
        Document doc;
        NodeList elementList;
        Node testAddr;
        Attr newAttr;
        Attr newAddrAttr;
        String newName;
        doc = (Document) load("staffNS", builder);
        elementList = doc.getElementsByTagName("emp:address");
        testAddr = elementList.item(0);
        assertNotNull("empAddrNotNull", testAddr);
        newAttr = doc.createAttributeNS("http://www.nist.gov", "xxx:domestic");
        newAddrAttr = ((Element) /* Node */testAddr)
                .setAttributeNodeNS(newAttr);
        newName = newAddrAttr.getNodeName();
        assertEquals("nodeName", "emp:domestic", newName);
    }
    public void testSetAttributeNode5() throws Throwable {
        String namespaceURI = "http://www.newattr.com";
        String qualifiedName = "emp:newAttr";
        Document doc1;
        Document doc2;
        Attr newAttr;
        NodeList elementList;
        Node testAddr;

        doc1 = (Document) load("staffNS", builder);
        doc2 = (Document) load("staffNS", builder);
        newAttr = doc2.createAttributeNS(namespaceURI, qualifiedName);
        elementList = doc1.getElementsByTagName("emp:address");
        testAddr = elementList.item(0);

        {
            boolean success = false;
            try {
                ((Element) /* Node */testAddr).setAttributeNodeNS(newAttr);
            } catch (DOMException ex) {
                success = (ex.code == DOMException.WRONG_DOCUMENT_ERR);
            }
            assertTrue("throw_WRONG_DOCUMENT_ERR", success);
        }
    }
}
