/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.xml.client;

import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.xml.client.impl.DOMParseException;
import com.google.gwt.xml.client.impl.XMLParserImplSafari;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * This class poorly tests all the methods in the GWT XML parser.
 */
public class XMLTest extends GWTTestCase {
  private static List<Node> asList(Node[] nodes) {
    return Arrays.asList(nodes);
  }

  private static void assertAttributeMapEquals(NamedNodeMap listA,
      NamedNodeMap listB) {
    // This is only for checking attribute maps.
    assertEquals(listA.getLength(), listB.getLength());
    for (int i = 0, n = listA.getLength(); i < n; ++i) {
      final Node itemA = listA.item(i);
      final Node itemB = listB.getNamedItem(itemA.getNodeName());
      assertNotNull(itemB);
      assertEquals(itemA.getNodeType(), itemB.getNodeType());
      assertEquals(itemA.getNodeValue(), itemB.getNodeValue());
    }
  }

  private static void assertCharacterDataEquals(CharacterData charDataA,
      CharacterData charDataB) {
    assertEquals(charDataA.getData(), charDataB.getData());
  }

  private static void assertDocumentEquals(Document docA, Document docB) {
    assertNodeListEquals(docA.getChildNodes(), docB.getChildNodes());
  }

  private static void assertElementEquals(Element elemA, Element elemB) {
    assertEquals(elemA.getNodeName(), elemB.getNodeName());
    assertAttributeMapEquals(elemA.getAttributes(), elemB.getAttributes());
    assertNodeListEquals(elemA.getChildNodes(), elemB.getChildNodes());
  }

  private static void assertNodeEquals(Node nodeA, Node nodeB) {
    assertNotNull(nodeA);
    assertNotNull(nodeB);
    final int typeA = nodeA.getNodeType();
    final int typeB = nodeB.getNodeType();
    assertEquals(typeA, typeB);
    switch (typeA) {
      case Node.ELEMENT_NODE:
        assertElementEquals((Element) nodeA, (Element) nodeB);
        break;
      case Node.COMMENT_NODE:
      case Node.CDATA_SECTION_NODE:
      case Node.TEXT_NODE:
        assertCharacterDataEquals((CharacterData) nodeA, (CharacterData) nodeB);
        break;
      case Node.PROCESSING_INSTRUCTION_NODE:
        assertProcessingInstructionEquals((ProcessingInstruction) nodeA,
            (ProcessingInstruction) nodeB);
        break;
      default:
        fail("Unexpected node type: " + nodeA.toString());
        break;
    }
  }

  private static void assertNodeListEquals(NodeList listA, NodeList listB) {
    final int sizeA = listA.getLength();
    final int sizeB = listB.getLength();
    assertEquals(sizeA, sizeB);
    for (int i = 0, n = sizeA; i < n; ++i) {
      assertNodeEquals(listA.item(i), listB.item(i));
    }
  }

  private static void assertProcessingInstructionEquals(
      ProcessingInstruction piA, ProcessingInstruction piB) {
    assertEquals(piA.getData(), piB.getData());
  }

  private static Document createTestDocument() {
    Document d = XMLParser.createDocument();
    Element top = d.createElement("doc");
    top.setAttribute("fluffy", "true");
    top.setAttribute("numAttributes", "2");
    d.appendChild(top);
    ProcessingInstruction commentBefore = d.createProcessingInstruction(
        "target", "some data");
    d.insertBefore(commentBefore, top);
    Comment commentAfter = d.createComment("after the element");
    d.insertBefore(commentAfter, null);
    for (int i = 0; i < 3; i++) {
      Element e = d.createElement("e" + i);
      e.setAttribute("id", "e" + i + "Id");
      top.appendChild(e);
    }
    Element deep = d.createElement("deep");
    top.getFirstChild().appendChild(deep);
    deep.setAttribute("depth", "1 foot");
    Element deep2 = d.createElement("deep");
    deep2.setAttribute("depth", "2 feet");
    top.getFirstChild().getFirstChild().appendChild(deep2);

    top.appendChild(d.createTextNode("0123456789"));
    top.appendChild(d.createCDATASection("abcdefghij"));
    return d;
  }

  /**
   * Returns the module name for GWT unit test running.
   */
  public String getModuleName() {
    return "com.google.gwt.xml.XML";
  }

  public void testAttr() {
    Document d = createTestDocument();
    Element de = d.getDocumentElement();
    de.setAttribute("created", "true");
    assertEquals("true", de.getAttribute("created"));
    de.setAttribute("set", "toAValue");
    assertEquals(de.getAttribute("set"), "toAValue");
    assertTrue(de.getAttributeNode("set").getSpecified());
    assertEquals(de.getAttributeNode("unset"), null);
  }

  public void testCreate() {
    Document d = XMLParser.createDocument();
    CDATASection createCDATA;
    if (XMLParser.supportsCDATASection()) {
      createCDATA = d.createCDATASection("sampl<<< >>e data");
    } else {
      createCDATA = d.createCDATASection("sample data");
    }
    Comment createComment = d.createComment("a sample comment");
    DocumentFragment createDocumentFragment = d.createDocumentFragment();
    Element elementWithChildren = d.createElement("elementWithChildren");
    ProcessingInstruction createProcessingInstruction = d.createProcessingInstruction(
        "target", "processing instruction data");
    Text createTextNode = d.createTextNode("sample text node");
    List<Node> canHaveChildren = asList(new Node[] {
        createDocumentFragment, elementWithChildren});
    List<Node> canBeChildren = asList(new Node[] {
        createCDATA, createComment, elementWithChildren,
        createProcessingInstruction, createTextNode});

    for (int i = 0; i < canHaveChildren.size(); i++) {
      Node parent = (Node) canHaveChildren.get(i);
      Node cloneParent = parent.cloneNode(false);
      if (canBeChildren.contains(parent)) {
        d.appendChild(cloneParent);
      }
      for (int j = 0; j < canBeChildren.size(); j++) {
        Node child = (Node) canBeChildren.get(j);
        cloneParent.appendChild(child.cloneNode(false));
      }
      for (int j = 0; j < canBeChildren.size(); j++) {
        Node clonedChild = cloneParent.getChildNodes().item(j);
        Node hopefullySameChild = (Node) canBeChildren.get(j);
        assertEquals(hopefullySameChild.cloneNode(false).toString(),
            clonedChild.toString());
      }
      Node deepClonedNode = parent.cloneNode(true);
      assertEquals(parent.toString(), deepClonedNode.toString());
    }

    // Now check the document.
    XMLParser.removeWhitespace(d);
    if (XMLParser.supportsCDATASection()) {
      assertDocumentEquals(XMLParser.parse("<elementWithChildren>"
          + "<![CDATA[sampl<<< >>e data]]>" + "<!--a sample comment-->"
          + "<elementWithChildren/>" + "<?target processing instruction data?>"
          + "sample text node" + "</elementWithChildren>"), d);
    } else {
      assertDocumentEquals(XMLParser.parse("<elementWithChildren>"
          + "sample data" + "<!--a sample comment-->"
          + "<elementWithChildren/>" + "<?target processing instruction data?>"
          + "sample text node" + "</elementWithChildren>"), d);
    }
  }

  public void testDocument() {
    Document d = createTestDocument();
    NodeList e1Nodes = d.getElementsByTagName("e1");
    assertEquals(e1Nodes.getLength(), 1);
    Node e1Node = e1Nodes.item(0);
    assertEquals(((Element) e1Node).getTagName(), "e1");

    // we didn't define a dtd, so no id for us
    Element e1NodeDirect = d.getElementById("e1Id");
    assertNull(e1NodeDirect);

    Document alienDoc = XMLParser.createDocument();
    Node alienNode11 = alienDoc.importNode(e1Node, true);
    alienDoc.appendChild(alienNode11);
    assertNotSame(e1Node, alienNode11);
    assertEquals(e1Node.toString(), alienNode11.toString());
  }

  public void testElement() {
    Document d = createTestDocument();
    Element top = d.getDocumentElement();
    NodeList el = top.getElementsByTagName("e1");
    assertEquals(el.getLength(), 1);
    NodeList deepNodes = top.getElementsByTagName("deep");
    assertEquals(deepNodes.getLength(), 2);
    Element d1 = (Element) deepNodes.item(0);
    assertTrue(d1.hasAttribute("depth"));
    assertFalse(d1.hasAttribute("height"));
    d1.removeAttribute("depth");
    assertFalse(d1.hasAttribute("depth"));
    Element d2 = (Element) deepNodes.item(1);
    assertTrue(d2.hasAttribute("depth"));
    Attr depthAttr = d2.getAttributeNode("depth");
    assertNotNull(depthAttr);
    d2.removeAttribute("depth");
    assertFalse(d2.hasAttribute("depth"));
  }

  public void testForIssue733() {
    // TODO (knorton):
    // http://code.google.com/p/google-web-toolkit/issues/detail?id=2346
    // Fixing issue #733 has been deferred for Safari2. See the bug URL for more
    // details. This should be enabled as soon as that bug is fixed.
    if (XMLParserImplSafari.isSafari2LevelWebKit()) {
      return;
    }

    final Document document = XMLParser.createDocument();
    final Element element = document.createElement("foo");
    document.appendChild(element);
    element.setAttribute("bar", "<");
    final String xmlAsString = document.toString();
    try {
      XMLParser.parse(xmlAsString);
    } catch (DOMParseException e) {
      fail(xmlAsString + " is invalid XML.");
    }
  }

  public void testNamedNodeMap() {
    Document d = createTestDocument();
    NamedNodeMap m = d.getDocumentElement().getAttributes();
    assertEquals(((Attr) m.getNamedItem("fluffy")).getValue(), "true");
    assertEquals(m.getLength(), 2);
  }

  public void testNavigation() {
    Document d = createTestDocument();
    Element documentElement = d.getDocumentElement();
    assertEquals("getPreviousSibling", documentElement.getPreviousSibling(),
        d.getChildNodes().item(0));
    assertEquals("getNextSibling", documentElement.getNextSibling(),
        d.getChildNodes().item(2));
    assertEquals("getDocumentElement", documentElement, d.getChildNodes().item(
        1));
    assertEquals("getTagName", documentElement.getTagName(), "doc");
    NodeList documentElementChildNodes = documentElement.getChildNodes();
    int deChildNodesLength = documentElementChildNodes.getLength();
    assertEquals("getFirstChild", documentElement.getFirstChild(),
        documentElementChildNodes.item(0));
    assertEquals("getLastChild", documentElement.getLastChild(),
        documentElementChildNodes.item(deChildNodesLength - 1));
    assertEquals("getNextSibling2",
        documentElement.getFirstChild().getNextSibling(),
        documentElementChildNodes.item(1));

    assertEquals("getPreviousSibling2",
        documentElement.getLastChild().getPreviousSibling(),
        documentElementChildNodes.item(deChildNodesLength - 2));
  }

  public void testNode() {
    Document ns = XMLParser.parse("<x:doc xmlns:x=\"http://x\"/>");
    String xUrl = "http://x";
    assertEquals(xUrl, ns.getFirstChild().getNamespaceURI());
    Element top = ns.getDocumentElement();
    Text xxx = ns.createTextNode("xxx");
    top.appendChild(xxx);
    Text yyy = ns.createTextNode("yyy");
    top.appendChild(yyy);
    assertEquals(xxx.getNodeValue(), "xxx");
    assertEquals(xxx.getParentNode(), top);
    xxx.setNodeValue("x");
    assertEquals(xxx.getData(), "x");
    assertEquals(xxx.getOwnerDocument(), ns);
    top.removeChild(xxx);
    assertEquals(top.getChildNodes().getLength(), 1);
    Comment commentNode = ns.createComment("comment ccc");
    top.replaceChild(commentNode, yyy);
    assertEquals(top.getFirstChild(), commentNode);
    assertEquals(top.getChildNodes().getLength(), 1);
  }

  /**
   * This test is failing on one Safari configuration in web mode in the 1.5
   * release branch, but it passes in all other configurations and in the trunk.
   * The files in the xml package are identical between the trunk and the 1.5
   * branch.
   */
  public void disabledTestParse() {
    Document docA = XMLParser.parse("<!--hello-->   <a spam=\"ham\">\n  <?pi hello ?>dfgdfg  <b/>\t</a>");

    Document docB = XMLParser.createDocument();
    docB.appendChild(docB.createComment("hello"));
    final Element eleB = docB.createElement("a");
    docB.appendChild(eleB);
    eleB.setAttribute("spam", "ham");
    eleB.appendChild(docB.createTextNode("\n  "));
    eleB.appendChild(docB.createProcessingInstruction("pi", "hello "));
    eleB.appendChild(docB.createTextNode("dfgdfg  "));
    eleB.appendChild(docB.createElement("b"));
    eleB.appendChild(docB.createTextNode("\t"));

    assertDocumentEquals(docA, docB);

    try {
      XMLParser.parse("<<<");
      fail();
    } catch (DOMParseException e) {
    }
  }

  public void testPrefix() {
    Document d = XMLParser.parse("<?xml version=\"1.0\"?>\r\n"
        + "<!-- both namespace prefixes are available throughout -->\r\n"
        + "<bk:book xmlns:bk=\'urn:loc.gov:books\'\r\n"
        + "         xmlns:isbn=\'urn:ISBN:0-395-36341-6\'>\r\n"
        + "    <bk:title>Cheaper by the Dozen</bk:title>\r\n"
        + "    <isbn:number>1568491379</isbn:number>\r\n" + "</bk:book>");
    assertEquals(d.getDocumentElement().getNodeName(), "bk:book");
    assertEquals(d.getDocumentElement().getPrefix(), "bk");
    assertEquals(d.getElementsByTagName("book").getLength(), 1);
    assertEquals(d.getElementsByTagName("book").item(0), d.getDocumentElement());
  }

  public void testProcessingInstruction() {
    Document d = createTestDocument();
    ProcessingInstruction pi = (ProcessingInstruction) d.getChildNodes().item(0);
    assertEquals(pi.getTarget(), "target");
    assertEquals(pi.getData(), "some data");
    pi.setData("other data");
    assertEquals(pi.getData(), "other data");
  }

  public void testText() {
    Document d = createTestDocument();
    List<Node> textLikeNodes = Arrays.asList(new Node[] {
        d.createTextNode(""), d.createCDATASection(""), d.createComment("")});
    StringBuffer b = new StringBuffer();
    for (char i = 32; i < 30000; i++) {
      b.append(i);
    }
    for (Iterator<Node> iter = textLikeNodes.iterator(); iter.hasNext();) {
      CharacterData textLike = (CharacterData) iter.next();
      textLike.setData(b.toString());
      assertEquals("initialLength type:" + textLike.getNodeType(), 30000 - 32,
          textLike.getLength());
      assertEquals("initialEquals", textLike.getData(), b.toString());
    }
    for (int i = 32; i < 29900; i += 100) {
      for (Iterator<Node> iter = textLikeNodes.iterator(); iter.hasNext();) {
        CharacterData textLike = (CharacterData) iter.next();
        assertEquals("substring type:" + textLike.getNodeType() + " count: "
            + i, b.substring(i, i + 100), textLike.substringData(i, 100));
      }
    }
    for (Iterator<Node> iter = textLikeNodes.iterator(); iter.hasNext();) {
      StringBuffer bTemp = new StringBuffer(b.toString());
      CharacterData textLike = (CharacterData) iter.next();
      textLike.deleteData(100, 100);
      bTemp.delete(100, 200);
      assertEquals("deleteLength type:" + textLike.getNodeType(),
          bTemp.length(), textLike.getData().length());
      assertEquals("deleteEquals type:" + textLike.getNodeType(),
          bTemp.toString(), textLike.getData());
      bTemp.setLength(0);
    }
    for (Iterator<Node> iter = textLikeNodes.iterator(); iter.hasNext();) {
      StringBuffer bTemp = new StringBuffer(b.toString());
      CharacterData textLike = (CharacterData) iter.next();
      textLike.setData(bTemp.toString());
      textLike.replaceData(50, 100, " ");
      bTemp.replace(50, 150, " ");
      assertEquals("replaceLength type:" + textLike.getNodeType(),
          bTemp.length(), textLike.getData().length());
      assertEquals("replaceEquals type:" + textLike.getNodeType(),
          bTemp.toString(), textLike.getData());
      bTemp.setLength(0);
    }
    for (Iterator<Node> iter = textLikeNodes.iterator(); iter.hasNext();) {
      CharacterData textLike = (CharacterData) iter.next();
      textLike.appendData("!!!");
      assertTrue("endswith!!!", textLike.getData().endsWith("!!!"));
      textLike.insertData(0, "!");
      textLike.insertData(1, "@@");
      assertTrue("startsWith !@@", textLike.getData().startsWith("!@@"));
    }
    Text t = (Text) d.getDocumentElement().getChildNodes().item(3);
    Text rightT = t.splitText(5);
    assertEquals("t and leftT parent equality", t.getParentNode(),
        rightT.getParentNode());
    assertEquals("leftT.getPreviousSibling", rightT.getPreviousSibling(), t);
    assertEquals("t.length", t.getData().length(), 5);
    assertEquals("leftT.length", rightT.getData().length(), 5);
    assertEquals("t data", t.getData(), "01234");
    assertEquals("LeftT data", rightT.getData(), "56789");
    CDATASection cd = (CDATASection) d.getDocumentElement().getChildNodes().item(
        5);
    Text rightCD = cd.splitText(5);
    assertEquals("cd and leftCd parent equality", cd.getParentNode(),
        rightCD.getParentNode());
    assertEquals("leftCD.getPreviousSibling", rightCD.getPreviousSibling(), cd);
    assertEquals("cd length", cd.getData().length(), 5);
    assertEquals("leftCD.length", rightCD.getData().length(), 5);
    assertEquals("cd data", cd.getData(), "abcde");
    assertEquals("leftCD data", rightCD.getData(), "fghij");
    d.getDocumentElement().normalize();
    if (XMLParser.supportsCDATASection()) {
      assertEquals("normalized t", d.getDocumentElement().getChildNodes().item(
          3).toString(), "0123456789");
    } else {
      assertEquals("normalized t", d.getDocumentElement().getChildNodes().item(
          3).toString(), "0123456789abcdefghij");
    }
  }
}
