
/**

 * @author Ibermatica

 * 

 * Fecha de Creaci�n: 31/01/2019

 */

package com.ejie.ad74a.util.pid;

//import org.apache.xpath.XPathAPI;
//import it.svario.xpathapi.jaxp.XPathAPI;

import org.w3c.dom.*;

import com.sun.org.apache.xpath.internal.XPathAPI;

import java.util.StringTokenizer;

import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPathException;

/** Representa un elemento de un documento xml. */

public final class XmlElement {

	private Element domElem;

	/**
	 * 
	 * Construye un objeto de la clase.
	 * 
	 * 
	 * 
	 * @param domElem
	 * 
	 *                Elemento Dom subyacente.
	 * 
	 */

	public XmlElement(Element domElem) {

		this.domElem = domElem;

	}

	/**
	 * 
	 * Devuelve el nombre del elemento.
	 * 
	 * 
	 * 
	 * @return El nombre del elemento.
	 * 
	 */

	public String getName() {

		return domElem.getTagName();

	}

	/**
	 * 
	 * Devuelve el valor del elemento.
	 * 
	 * 
	 * 
	 * @return El valor del elemento; null si no existe.
	 * 
	 */

	public String getValue() {

		String val = null;

		Node node;

		node = domElem.getFirstChild();

		if (node != null) {

			val = node.getNodeValue();

		}

		return val;

	}

	/**
	 * 
	 * Devuelve el atributo del elemento con el nombre especificado.
	 * 
	 * 
	 * 
	 * @param atrib
	 * 
	 *              El nombre del atributo.
	 * 
	 * @return El valor del atributo.
	 * 
	 */

	public String getAttribute(final String atrib) {

		return domElem.getAttribute(atrib);

	}

	/**
	 * 
	 * Establece el valor del elemento.
	 * 
	 * 
	 * 
	 * @param val
	 * 
	 *            El nuevo valor del elemento.
	 * 
	 */

	public void setValue(final String val) {

		Node node;

		Document doc;

		node = domElem.getFirstChild();

		if (node != null) {

			node.setNodeValue(val);

		} else {

			doc = domElem.getOwnerDocument();

			node = doc.createTextNode(val);

			domElem.appendChild(node);

		}

	}

	/**
	 * 
	 * Devuelve el padre de este nodo.
	 * 
	 * 
	 * 
	 * @return El elemento buscado; null si no existe.
	 * 
	 */

	public XmlElement getParentElement() {

		XmlElement elem = null;

		Node node;

		node = domElem.getParentNode();

		if (node != null && node instanceof Element) {

			elem = new XmlElement((Element) node);

		}

		return elem;

	}

	/**
	 * 
	 * Devuelve el (primer) elemento hijo con el nombre especificado.
	 * 
	 * 
	 * 
	 * @param name
	 * 
	 *             Nombre del elemento buscado.
	 * 
	 * @return El elemento buscado; null si no existe.
	 * 
	 */

	public XmlElement getChildElement(final String name) {

		XmlElement elem = null;

		NodeList nodes;

		int count, i;

		Node node;

		String nodeName;

		nodes = domElem.getChildNodes();

		count = nodes.getLength();

		for (i = 0; i < count; i++) {

			node = nodes.item(i);

			if (node.getNodeType() == Node.ELEMENT_NODE) {

				nodeName = node.getNodeName();

				if (nodeName.compareTo(name) == 0) {

					elem = new XmlElement((Element) node); // NOPMD by BICHMAOS, se crea dentro el objeto porque no se
															// sabe antes la informaci�n

					break;

				}

			}

		}

		return elem;

	}

	/**
	 * 
	 * Devuelve el (primer) elemento descendiente con el nombre especificado.
	 * 
	 * 
	 * 
	 * @param pathname
	 * 
	 *                 Ruta de acceso y nombre del elemento buscado. <br>
	 * 
	 *                 La ruta de acceso debe ser relativa al elemento padre.
	 * 
	 * @return El elemento buscado; null si no existe.
	 * 
	 */

	public XmlElement getDescendantElement(final String pathname) {

		XmlElement elem = null;

		StringTokenizer strTkr;

		int count, i;

		String name;

		XmlElement parentElem;

		XmlElement childElem;

		strTkr = new StringTokenizer(pathname, "/");

		count = strTkr.countTokens();

		if (count < 1) {

			elem = getChildElement(pathname);

		} else {

			parentElem = this;

			for (i = 0; i < count; i++) {

				name = strTkr.nextToken();

				childElem = parentElem.getChildElement(name);

				if (childElem == null) {

					break;

				} else {

					parentElem = childElem;

					if (i == (count - 1))

						elem = childElem;

				}

			}

		}

		return elem;

	}

	/**
	 * 
	 * Devuelve la colecci�n de elementos hijo del elemento.
	 * 
	 * 
	 * 
	 * @return La colecci�n mencionada.
	 * 
	 */

	public XmlElements getChildElements() {

		return XmlElement.getChildElements(domElem);

	}

	/**
	 * 
	 * Devuelve el texto xml del elemento.
	 * 
	 * 
	 * 
	 * @param omitXmlHdr
	 * 
	 *                   Especifica si omitir la cabecera xml.
	 * 
	 * @return El texto mencionado.
	 * 
	 * @throws Exception
	 * 
	 *                   si se produce alg�n error.
	 * 
	 */

	public String getStringText(final boolean omitXmlHdr) throws Exception {

		return XmlTransformer.transformXmlElementToXmlStringText(this,

				omitXmlHdr);

	}

	/**
	 * 
	 * Devuelve el elemento Dom subyacente.
	 * 
	 * 
	 * 
	 * @return El elemento mencionado.
	 * 
	 */

	public Element getDomElement() {

		return domElem;

	}

	/**
	 * 
	 * Devuelve la colecci�n de elementos hijo del nodo Dom especificado.
	 * 
	 * 
	 * 
	 * @param domNode
	 * 
	 *                El nodo Dom mencionado.
	 * 
	 * @return La colecci�n mencionada.
	 * 
	 */

	private static XmlElements getChildElements(Node domNode) {

		XmlElements elems = null;

		NodeList domNodes;

		int count, count1, i;

		Node[] domNodes1;

		Node domNode1;

		XmlElement[] elems1;

		XmlElement elem1;

		domNodes = domNode.getChildNodes();

		count = domNodes.getLength();

		domNodes1 = new Node[count];

		count1 = 0;

		for (i = 0; i < count; i++) {

			domNode1 = domNodes.item(i);

			if (domNode1.getNodeType() == Node.ELEMENT_NODE) {

				domNodes1[count1] = domNode1;

				count1++;

			}

		}

		elems1 = new XmlElement[count1];

		for (i = 0; i < count1; i++) {

			domNode1 = domNodes1[i];

			elem1 = new XmlElement((Element) domNode1); // NOPMD by BICHMAOS, se crea dentro el objeto porque no se sabe
														// antes la informaci�n

			elems1[i] = elem1;

		}

		elems = new XmlElements(elems1);

		return elems;

	}

	/**
	 * 
	 * M�todo que obtiene un nodo a trav�s de una expresi�n
	 * 
	 * XPath.
	 * 
	 * 
	 * 
	 * @param xpathExpression
	 * 
	 *                        Expresi�n que obtiene el valor deseado.
	 * 
	 * @return El valor del nodo elemento. Si no existe se devuelve nulo
	 * 
	 * @throws Exception
	 * 
	 */

	public XmlElement getXmlElement(String xpathExpression)

			throws Exception {

		Node node;

		XmlElement element = null;

		node = XPathAPI.selectSingleNode((Node) getDomElement(),

				xpathExpression);

		if (node != null) {

			element = new XmlElement((Element) node);

		}

		return element;

	}

	/**
	 * 
	 * M�todo que obtiene un conjunto de nodos a trav�s de una expresi�n XPath.
	 * 
	 * 
	 * 
	 * @param xpathExpression
	 * 
	 *                        Expresi�n que obtiene el valor deseado.
	 * 
	 * @return El valor de los nodos elemento. Si no existe se devuelve nulo
	 * 
	 * @throws Exception
	 * 
	 */

	public XmlElements getXmlElements(String xpathExpression)

			throws Exception {

		NodeList nodeList;

		int counter;

		XmlElements elements = null;

		XmlElement[] elem;

		nodeList = XPathAPI.selectNodeList(getDomElement(), xpathExpression);

		elem = new XmlElement[nodeList.getLength()];

		for (counter = 0; counter < nodeList.getLength(); counter++) {

			elem[counter] = new XmlElement((Element) nodeList.item(counter)); // NOPMD by BICHMAOS, se crea dentro
																				// el objeto porque no se sabe antes
																				// la informaci�n

		}

		elements = new XmlElements(elem);

		return elements;

	}

} // class XmlElement
