/*
 * This file (ReadFromXML.java) is part of DebGen-LabelPrintLib  developed by ASTRID Research.
 * All rights reserved. Reproduction, modification, use or disclosure
 * to third parties without express authority is forbidden.
 *
 *  Copyright ASTRID Research, Hungary, 2010.
 *
 *  ASTRID Research
 *  Headquaters: Csapó utca 42. Debrecen H-4029 HUNGARY
 *  Phone: +36-52-533-173        Fax: +36-52-533-174
 *  Web: http://www.astrid.hu    E-mail: info@astrid.hu
 *
 * Project name: DEBGEN-Biobank-Project.
 * File last modified at 2010.01.08 14:25
 */
package hu.astrid.debgen.labelprint.util;

import hu.astrid.debgen.labelprint.exception.LabelPrintException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.InputStream;
import java.net.URI;
import java.util.List;
import java.util.Vector;

/**
 * @author inagy
 */
public abstract class ReadFromXML {

    /**
     * Get Document from file
     * @param file  XML file.
     */
    public static final Document readFromXml(File file) {
        return readFromXml(file.toURI());
    }

    /**
     * Get Document from URI
     * @param uri  XML uri.
     */
    public static final Document readFromXml(URI uri) {
        Document doc = null;
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            doc = dbf.newDocumentBuilder().parse(new InputSource(uri.toURL().openStream()));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return doc;
    }

    /**
     * Get node value
     *
     * @param node  Root node.
     * @param chain Nodes chain to requested value
     * @return requested node value
     */
    public static String getNodeValue(Node node, String... chain) {
        Node n = getNode(node, chain);

        try {
            return n.getFirstChild().getNodeValue();

        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    /**
     * Get attribute value
     *
     * @param node  Root node.
     * @param attributeName The name of the requested attribute
     * @param chain Nodes chain to requested value
     * @return requested node value
     */
    public static int getAttributeValue(Node node, String attributeName, String... chain) {
        Node n = node;
        if (chain.length > 0) {
            n = getNode(node, chain);
        }
        try {
            return Integer.parseInt(n.getAttributes().getNamedItem(attributeName).getNodeValue());
        } catch (Exception ex) {
            ex.printStackTrace();
            return 1;
        }
    }

    /**
     * Get node
     *
     * @param node  Root node.
     * @param chain Nodes chain to requested node
     * @return requested node
     */
    public static Node getNode(Node node, String... chain) {
        List<Node> list = getNodes(node, chain);
        return (list == null || list.isEmpty() ? null : list.get(0));
    }

    /**
     * Get node list
     *
     * @param node  Root node.
     * @param chain Nodes chain to requested node
     * @return requested nodes
     */
    public static List<Node> getNodes(Node node, String... chain) {
        List<Node> result = new Vector<Node>();
        Node step = node;
        boolean last = false;

        for (int k = 0; k < chain.length; k++) {
            if (k == (chain.length - 1)) {
                last = true;
            }
            String s = chain[k];
            NodeList nl = step.getChildNodes();
            for (int i = 0; i < nl.getLength(); i++) {
                Node n = nl.item(i);
                if (n.getNodeName().equals(s)) {
                    if (!last) {
                        step = n;
                        break;
                    } else {
                        result.add(n);
                    }
                }
            }

        }
        return result;
    }

    /**
     * Get resource.
     * @param resourceName Name of resource.
     */
    public static String readResource(String resourceName) throws LabelPrintException {
        StringBuilder buffer = new StringBuilder();
        InputStream in = null;
        int i;
        try {

            in = ReadFromXML.class.getResourceAsStream(resourceName);

            //TODO: buffert kene hasznalni (byte[])
            while ((i = in.read()) >= 0) {
                buffer.append((char) i);
            }

            return buffer.toString();
        } catch (Exception ex) {
            throw new LabelPrintException(ex);
        } finally {
            try {
                in.close();
            } catch (Exception ex) {
                //IGNORED
            }
        }
    }
}
