/*
 *  @author Ranides Atterwim <ranides@gmail.com>
 *  @copyright Ranides Atterwim
 *  @license WTFPL
 *  @url http://ranides.net/projects/assira
 */

package net.ranides.assira.xml;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import net.ranides.assira.text.TextInputStream;
import net.ranides.assira.text.TextOutputStream;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

/**
 *
 * @author ranides
 */
final public class XMLHelper {

    private XMLHelper() { }

    public static Document asDocumentClone(Node node) {
        try {
            Document docFragment = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
            docFragment.appendChild(docFragment.importNode(node, true));
            return docFragment;
        } catch (ParserConfigurationException cause) {
            throw new XMLInternalError(cause);
        }
    }

    public static Document asDocument(Node node) {
        try {
            Document docFragment = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
            docFragment.appendChild(docFragment.adoptNode(node));
            return docFragment;
        } catch (ParserConfigurationException cause) {
            throw new XMLInternalError(cause);
        }
    }

    public static Map<String, Node> mapNodes(Node group) {
        Map<String, Node> result = new HashMap<>();
        for(Node node : NodeCollection.nodes(group) ) {
            if(Node.ELEMENT_NODE == node.getNodeType()) {
                result.put(node.getNodeName(), node);
            }
        }
        return result;
    }

    public static Map<String, String> mapValues(Node group) {
        Map<String, String> result = new HashMap<>();

        for(Node node : NodeCollection.nodes(group) ) {
            if(Node.ELEMENT_NODE == node.getNodeType()) {
                result.put(node.getNodeName(), node.getTextContent());
            }
        }
        for(Node node : NodeCollection.attributes(group) ) {
            result.put(node.getNodeName(), node.getTextContent());
        }
        return result;
    }

    /**
     * Konwertuje dowolny objekt Javy do XML używając java.beans.XMLEncoder
     * @param obj
     * @return
     */
    public static String asString(Object obj) {
        TextOutputStream output = new TextOutputStream();
        XMLEncoder encoder = new XMLEncoder(output);
        encoder.writeObject(obj);
        encoder.close();
        return output.toString();
    }

    /**
     * Deseralizacja obiektu przy użyciu XMLDecoder.
     * @param string
     * @return
     */
    public static Object asObject(String string) {
        TextInputStream byo = new TextInputStream(string);
        XMLDecoder dec = new XMLDecoder(byo);
        Object obj = dec.readObject();
        dec.close();
        return obj;
    }

    /**
     * Serializuje i deserializuje obiekt w obrębie tego classLoadera.
     * @param obj
     * @return
     */
    public static Object reparse(Object obj) {
        return asObject( asString(obj) );
    }

}
