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

package net.ranides.assira.xml;

import java.io.*;
import java.net.URL;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import net.ranides.assira.io.FileHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

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

    private XMLTransform() { }
    
    public static Document parse(URL source) throws TransformerException {
        try {
            return parse(source.openStream());
        } catch(IOException cause) {
            throw new TransformerException(cause);
        }
    }

    public static Document parse(InputSource source) throws TransformerException {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(false);
            return factory.newDocumentBuilder().parse(source);
        } catch (SAXException cause) {
            throw new TransformerException(cause);
        } catch (ParserConfigurationException cause) {
            throw new TransformerException(cause);
        } catch (IOException cause) {
            throw new TransformerException(cause);
        }
    }

    public static Document parse(InputStream stream) throws TransformerException {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(false);
            return factory.newDocumentBuilder().parse(stream);
        } catch (SAXException cause) {
            throw new TransformerException(cause);
        } catch (ParserConfigurationException cause) {
            throw new TransformerException(cause);
        } catch (IOException cause) {
            throw new TransformerException(cause);
        } finally {
            FileHelper.close(stream);
        }
    }

    public static Document parse(File file) throws TransformerException {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(false);
            return factory.newDocumentBuilder().parse(file);
        } catch (SAXException cause) {
            throw new TransformerException(cause);
        } catch (ParserConfigurationException cause) {
            throw new TransformerException(cause);
        } catch (IOException cause) {
            throw new TransformerException(cause);
        }
    }

    public static Document parse(Reader reader) throws TransformerException {
        try {
            return parse(new InputSource(reader) );
        } finally {
            FileHelper.close(reader);
        }
    }

    public static Document parse(String source) throws TransformerException {
        return parse(new StringReader(source) );
    }

    /**
     * Zrzuca źródło dokumentu do strumienia
     * @param stream
     * @param doc
     * @return
     * @throws IllegalArgumentException jeśli konwersja niemożliwa
     */
    public static StreamResult source(StreamResult stream, Node doc) {
        try {
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            transformer.transform(new DOMSource(doc), stream);
            return stream;
        } catch (TransformerException cause) {
            throw new IllegalArgumentException(cause);
        }
    }

    /**
     * Zrzuca źródło dokumentu do strumienia
     * @param stream
     * @param doc
     * @throws IllegalArgumentException jeśli konwersja niemożliwa
     */
    public static void source(OutputStream stream, Node doc) {
        source(new StreamResult(stream), doc);
        FileHelper.close(stream);
    }

    /**
     * Zrzuca źródło dokumentu do strumienia
     * @param writer
     * @param doc
     * @throws IllegalArgumentException jeśli konwersja niemożliwa
     */
    public static void source(Writer writer, Node doc) {
        source(new StreamResult(writer), doc);
        FileHelper.close(writer);
    }

    /**
     * Zrzuca źródło dokumentu do pliku
     * @param file
     * @param doc
     * @throws IllegalArgumentException jeśli konwersja niemożliwa
     */
    public static void source(File file, Node doc) {
        source(new StreamResult(file), doc);
    }

    /**
     * Zwraca źródło dokumentu jako string
     * @param doc
     * @return
     * @throws IllegalArgumentException jeśli konwersja niemożliwa
     */
    public static String source(Node doc) {
        StringWriter writer = new StringWriter();
        source(new StreamResult(writer), doc);
        return writer.toString();
    }
    
}
