/*=========================================================================
 * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
 * This product is protected by U.S. and international copyright
 * and intellectual property laws. Pivotal products are covered by
 * more patents listed at http://www.pivotal.io/patents.
 *=========================================================================
 */
package com.gemstone.gemfire.management.internal.configuration.utils;

import static org.junit.Assert.*;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.distributed.internal.SharedConfiguration;
import com.gemstone.gemfire.internal.cache.extension.Extension;
import com.gemstone.gemfire.internal.cache.xmlcache.CacheXml;
import com.gemstone.gemfire.management.internal.configuration.domain.XmlEntity;
import com.gemstone.gemfire.management.internal.configuration.utils.XmlUtils.XPathContext;
import com.gemstone.gemfire.test.junit.categories.IntegrationTest;

/**
 * Unit tests for {@link XmlUtils#addNewNode(Document, XmlEntity)} and
 * {@link XmlUtils#deleteNode(Document, XmlEntity)}. Simulates the
 * {@link SharedConfiguration} method of extracting {@link XmlEntity} from the
 * new config and applying it to the current shared config.
 * 
 * @author jbarrett@pivotal.io
 *
 * @since 8.1
 */
@Category(IntegrationTest.class)
public class XmlUtilsAddNewNodeJUnitTest {

  private static final String TEST_PREFIX = "test";
  private static final String TEST_NAMESPACE = "urn:java:com/gemstone/gemfire/management/internal/configuration/utils/XmlUtilsAddNewNodeJUnitTest";
  private static final XPathContext xPathContext = new XPathContext();

  private static Cache cache;

  private Document config;

  @BeforeClass
  public static void beforeClass() {
    cache = new CacheFactory().set("mcast-port", "0").create();
    xPathContext.addNamespace(CacheXml.PREFIX, CacheXml.NAMESPACE);
    xPathContext.addNamespace(TEST_PREFIX, TEST_NAMESPACE);
  }

  @Before
  public void before() throws SAXException, ParserConfigurationException, IOException {
    config = XmlUtils.createDocumentFromReader(new InputStreamReader(this.getClass().getResourceAsStream("XmlUtilsAddNewNodeJUnitTest.xml")));
  }

  @AfterClass
  public static void afterClass() {
    cache.close();
    cache = null;
  }

  /**
   * Tests {@link XmlUtils#addNewNode(Document, XmlEntity)} with
   * {@link CacheXml} element with a <code>name</code> attribute,
   * <code>region</code>. It should be added after other <code>region</code>
   * elements.
   * 
   * @throws Exception
   * @throws XPathExpressionException 
   * @since 8.1
   */
  @Test
  public void testAddNewNodeNewNamed() throws Exception {
    final String xPath = "/cache:cache/cache:region[@name='r3']";
    NodeList nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(0, nodes.getLength());

    final Document changes = XmlUtils.createDocumentFromReader(new InputStreamReader(this.getClass().getResourceAsStream(
        "XmlUtilsAddNewNodeJUnitTest.testAddNewNodeNewNamed.xml")));
    nodes = XmlUtils.query(changes, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    Element element = (Element) nodes.item(0);
    assertEquals(CacheXml.NAMESPACE, element.getNamespaceURI());

    final XmlEntity xmlEntity = XmlEntity.builder().withType("region").withAttribute("name", "r3").withConfig(changes).build();
    XmlUtils.addNewNode(config, xmlEntity);

    nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    element = (Element) nodes.item(0);
    assertEquals(CacheXml.NAMESPACE, element.getNamespaceURI());

    final List<Node> childNodes = getElementNodes(config.getFirstChild().getChildNodes());

    assertEquals("r2", childNodes.get(4).getAttributes().getNamedItem("name").getNodeValue());
    assertEquals("r3", childNodes.get(5).getAttributes().getNamedItem("name").getNodeValue());
    assertEquals("test:cache", childNodes.get(6).getNodeName());
  }
  
  /**
   * Return just the nodes from a nodelist that are of type
   * element.
   */
  private List<Node> getElementNodes(NodeList nodes) {
    ArrayList<Node> result = new ArrayList<Node>();
    for(int i = 0; i < nodes.getLength(); i++) {
      Node node = nodes.item(i);
      if(node.getNodeType() == Node.ELEMENT_NODE) {
        result.add(node);
      }
    }
    
    return result;
  }

  /**
   * Tests {@link XmlUtils#addNewNode(Document, XmlEntity)} with
   * {@link CacheXml} element that does not have a name or id attribute,
   * <code>jndi-bindings</code>. It should be added between <code>pdx</code> and
   * <code>region</code> elements.
   * 
   * @throws Exception
   * @since 8.1
   */
  @Test
  public void testAddNewNodeNewUnnamed() throws Exception {
    final String xPath = "/cache:cache/cache:jndi-bindings";
    NodeList nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(0, nodes.getLength());

    final Document changes = XmlUtils.createDocumentFromReader(new InputStreamReader(this.getClass().getResourceAsStream(
        "XmlUtilsAddNewNodeJUnitTest.testAddNewNodeNewUnnamed.xml")));
    nodes = XmlUtils.query(changes, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    Element element = (Element) nodes.item(0);
    assertEquals(CacheXml.NAMESPACE, element.getNamespaceURI());

    final XmlEntity xmlEntity = XmlEntity.builder().withType("jndi-bindings").withConfig(changes).build();
    XmlUtils.addNewNode(config, xmlEntity);

    nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    element = (Element) nodes.item(0);
    assertEquals(CacheXml.NAMESPACE, element.getNamespaceURI());

    final List<Node> childElements = getElementNodes(config.getFirstChild().getChildNodes());
    assertEquals("pdx", childElements.get(2).getNodeName());
    assertEquals("jndi-bindings", childElements.get(3).getNodeName());
    assertEquals("region", childElements.get(4).getNodeName());
  }

  /**
   * Tests {@link XmlUtils#addNewNode(Document, XmlEntity)} with an
   * {@link Extension} that does not have a name or id attribute. It should be
   * added to the end of the config xml. Attempts a name collision with
   * test:region, it should not collide with the similarly named cache:region
   * element.
   * 
   * @throws Exception
   * @since 8.1
   */
  @Test
  public void testAddNewNodeNewUnnamedExtension() throws Exception {
    final String xPath = "/cache:cache/test:region";
    NodeList nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(0, nodes.getLength());

    final Document changes = XmlUtils.createDocumentFromReader(new InputStreamReader(this.getClass().getResourceAsStream(
        "XmlUtilsAddNewNodeJUnitTest.testAddNewNodeNewUnnamedExtension.xml")));
    nodes = XmlUtils.query(changes, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    Element element = (Element) nodes.item(0);
    assertEquals(TEST_NAMESPACE, element.getNamespaceURI());
    assertEquals("test:region", element.getNodeName());
    
    final XmlEntity xmlEntity = XmlEntity.builder().withType("region").withNamespace(TEST_PREFIX, TEST_NAMESPACE).withConfig(changes).build();
    XmlUtils.addNewNode(config, xmlEntity);

    nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    element = (Element) nodes.item(0);
    assertEquals(TEST_NAMESPACE, element.getNamespaceURI());
    assertEquals("test:region", element.getNodeName());

    final List<Node> childElements = getElementNodes(config.getFirstChild().getChildNodes());
    
    
    assertEquals("test:cache", childElements.get(5).getNodeName());
    assertEquals("test:region", childElements.get(6).getNodeName());
    assertEquals(7, childElements.size());
  }

  /**
   * Tests {@link XmlUtils#addNewNode(Document, XmlEntity)} with
   * {@link CacheXml} element with a <code>name</code> attribute,
   * <code>region</code>. It should replace existing <code>region</code> element
   * with same <code>name</code>.
   * 
   * @throws Exception
   * @since 8.1
   */
  @Test
  public void testAddNewNodeReplaceNamed() throws Exception {
    final String xPath = "/cache:cache/cache:region[@name='r1']";
    NodeList nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    Element element = (Element) nodes.item(0);
    assertEquals(1, getElementNodes(element.getChildNodes()).size());
    assertEquals(CacheXml.NAMESPACE, element.getNamespaceURI());

    final Document changes = XmlUtils.createDocumentFromReader(new InputStreamReader(this.getClass().getResourceAsStream(
        "XmlUtilsAddNewNodeJUnitTest.testAddNewNodeReplaceNamed.xml")));
    nodes = XmlUtils.query(changes, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    element = (Element) nodes.item(0);
    assertEquals(0, element.getChildNodes().getLength());
    assertEquals(CacheXml.NAMESPACE, element.getNamespaceURI());

    final XmlEntity xmlEntity = XmlEntity.builder().withType("region").withAttribute("name", "r1").withConfig(changes).build();
    XmlUtils.addNewNode(config, xmlEntity);

    nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    element = (Element) nodes.item(0);
    assertEquals(0, element.getChildNodes().getLength());
    assertEquals(CacheXml.NAMESPACE, element.getNamespaceURI());
  }

  /**
   * Tests {@link XmlUtils#addNewNode(Document, XmlEntity)} with
   * {@link CacheXml} element that does not have a name or id attribute,
   * <code>pdx</code>. It should replace <code>pdx</code> element.
   * 
   * @throws Exception
   * @since 8.1
   */
  @Test
  public void testAddNewNodeReplaceUnnamed() throws Exception {
    final String xPath = "/cache:cache/cache:pdx";
    NodeList nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    Element element = (Element) nodes.item(0);
    assertEquals("foo", XmlUtils.getAttribute(element, "disk-store-name"));
    assertEquals(CacheXml.NAMESPACE, element.getNamespaceURI());

    final Document changes = XmlUtils.createDocumentFromReader(new InputStreamReader(this.getClass().getResourceAsStream(
        "XmlUtilsAddNewNodeJUnitTest.testAddNewNodeReplaceUnnamed.xml")));
    nodes = XmlUtils.query(changes, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    element = (Element) nodes.item(0);
    assertEquals("bar", XmlUtils.getAttribute(element, "disk-store-name"));
    assertEquals(CacheXml.NAMESPACE, element.getNamespaceURI());

    final XmlEntity xmlEntity = XmlEntity.builder().withType("pdx").withConfig(changes).build();
    XmlUtils.addNewNode(config, xmlEntity);

    nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    element = (Element) nodes.item(0);
    assertEquals("bar", XmlUtils.getAttribute(element, "disk-store-name"));
    assertEquals(CacheXml.NAMESPACE, element.getNamespaceURI());
  }

  /**
   * Tests {@link XmlUtils#addNewNode(Document, XmlEntity)} with an
   * {@link Extension} that does not have a name or id attribute,
   * <code>test:cache</code>. It should replace the existing
   * <code>test:cache</code> element.
   * 
   * @throws Exception
   * @since 8.1
   */
  @Test
  public void testAddNewNodeReplaceUnnamedExtension() throws Exception {
    final String xPath = "/cache:cache/test:cache";
    NodeList nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    Element element = (Element) nodes.item(0);
    assertEquals("1", XmlUtils.getAttribute(element, "value"));
    assertEquals(TEST_NAMESPACE, element.getNamespaceURI());

    final org.w3c.dom.Document changes = XmlUtils.createDocumentFromReader(new InputStreamReader(this.getClass().getResourceAsStream(
        "XmlUtilsAddNewNodeJUnitTest.testAddNewNodeReplaceUnnamedExtension.xml")));
    nodes = XmlUtils.query(changes, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    element = (Element) nodes.item(0);
    assertEquals("2", XmlUtils.getAttribute(element, "value"));
    assertEquals(TEST_NAMESPACE, element.getNamespaceURI());

    final XmlEntity xmlEntity = XmlEntity.builder().withType("cache").withNamespace(TEST_PREFIX, TEST_NAMESPACE).withConfig(changes).build();
    XmlUtils.addNewNode(config, xmlEntity);

    nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    element = (Element) nodes.item(0);
    assertEquals("2", XmlUtils.getAttribute(element, "value"));
    assertEquals(TEST_NAMESPACE, element.getNamespaceURI());
  }

  /**
   * Tests {@link XmlUtils#deleteNode(Document, XmlEntity)} with
   * {@link CacheXml} element with a <code>name</code> attribute,
   * <code>region</code>. It should remove existing <code>region</code> element
   * with same <code>name</code>.
   * 
   * @throws Exception
   * @since 8.1
   */
  @Test
  public void testDeleteNodeNamed() throws Exception {
    final String xPath = "/cache:cache/cache:region[@name='r1']";
    NodeList nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    Element element = (Element) nodes.item(0);
    assertEquals(1, getElementNodes(element.getChildNodes()).size());
    assertEquals(CacheXml.NAMESPACE, element.getNamespaceURI());

    final Document changes = XmlUtils.createDocumentFromReader(new InputStreamReader(this.getClass().getResourceAsStream(
        "XmlUtilsAddNewNodeJUnitTest.testDeleteNodeNamed.xml")));
    nodes = XmlUtils.query(changes, xPath, xPathContext);
    assertEquals(0, nodes.getLength());

    final XmlEntity xmlEntity = XmlEntity.builder().withType("region").withAttribute("name", "r1").withConfig(changes).build();
    XmlUtils.deleteNode(config, xmlEntity);

    nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(0, nodes.getLength());
  }

  /**
   * Tests {@link XmlUtils#addNewNode(Document, XmlEntity)} with
   * {@link CacheXml} element that does not have a name or id attribute,
   * <code>pdx</code>. It should remove the existing <code>pdx</code> element.
   * 
   * @throws Exception
   * @since 8.1
   */
  @Test
  public void testDeleteNodeUnnamed() throws Exception {
    final String xPath = "/cache:cache/cache:pdx";
    NodeList nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    Element element = (Element) nodes.item(0);
    assertEquals("foo", XmlUtils.getAttribute(element, "disk-store-name"));
    assertEquals(CacheXml.NAMESPACE, element.getNamespaceURI());

    final Document changes = XmlUtils.createDocumentFromReader(new InputStreamReader(this.getClass().getResourceAsStream(
        "XmlUtilsAddNewNodeJUnitTest.testDeleteNodeUnnamed.xml")));
    nodes = XmlUtils.query(changes, xPath, xPathContext);
    assertEquals(0, nodes.getLength());

    final XmlEntity xmlEntity = XmlEntity.builder().withType("pdx").withConfig(changes).build();
    XmlUtils.deleteNode(config, xmlEntity);

    nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(0, nodes.getLength());
  }

  /**
   * Tests {@link XmlUtils#addNewNode(Document, XmlEntity)} with an
   * {@link Extension} that does not have a name or id attribute,
   * <code>test:cache</code>. It should remove the existing
   * <code>test:cache</code> element.
   * 
   * @throws Exception
   * @since 8.1
   */
  @Test
  public void testDeleteNodeUnnamedExtension() throws Exception {
    final String xPath = "/cache:cache/test:cache";
    NodeList nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(1, nodes.getLength());
    Element element = (Element) nodes.item(0);
    assertEquals("1", XmlUtils.getAttribute(element, "value"));
    assertEquals(TEST_NAMESPACE, element.getNamespaceURI());

    final Document changes = XmlUtils.createDocumentFromReader(new InputStreamReader(this.getClass().getResourceAsStream(
        "XmlUtilsAddNewNodeJUnitTest.testDeleteNodeUnnamedExtension.xml")));
    nodes = XmlUtils.query(changes, xPath, xPathContext);
    assertEquals(0, nodes.getLength());

    final XmlEntity xmlEntity = XmlEntity.builder().withType("cache").withNamespace(TEST_PREFIX, TEST_NAMESPACE).withConfig(changes).build();
    XmlUtils.deleteNode(config, xmlEntity);

    nodes = XmlUtils.query(config, xPath, xPathContext);
    assertEquals(0, nodes.getLength());
  }

}
