/*
 * Copyright (c) 2017 XMLmind Software. All rights reserved.
 *
 * Author: Hussein Shafie
 *
 * This file is part of the XMLmind Assembly Processor project.
 * For conditions of distribution and use, see the accompanying legal.txt file.
 */
package com.xmlmind.domutil;

import java.io.IOException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import org.w3c.dom.Document;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import com.xmlmind.util.ThrowableUtil;

/**
 * Utility allowing to save a W3C DOM document to an XML file.
 */
public final class SaveDocument {
    // The fallback implementation class name, XSLTC, for Java 6, 7, 8, 9.
    private static final String FALLBACK_TRANSFORMER_FACTORY =
        "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";

    private SaveDocument() {}

    /**
     * Save specified document to specified UTF-8, unindented, XML file.
     * <p>Does not save the DOCTYPE of the document if any.
     *
     * @param doc document to be saved
     * @param file save file
     * @exception IOException if for any reason, this method fails
     */
    public static void save(Document doc, File file) 
        throws IOException {
        Transformer transform;
        try {
            TransformerFactory factory;
            try {
                factory = 
                    TransformerFactory.newInstance(FALLBACK_TRANSFORMER_FACTORY,
                                                   /*classLoader*/ null);
            } catch (Exception ignored) {
                //ignored.printStackTrace();

                factory = TransformerFactory.newInstance();
            }

            transform = factory.newTransformer(); // Identity transform.

            transform.setOutputProperty(OutputKeys.METHOD, "xml");
            transform.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            transform.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
            transform.setOutputProperty(OutputKeys.INDENT, "no");
        } catch (Exception shouldNotHappen) {
            throw new IOException(ThrowableUtil.reason(shouldNotHappen));
        }

        OutputStreamWriter out = null;
        try {
            out = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");

            transform.transform(new DOMSource(doc, doc.getDocumentURI()), 
                                new StreamResult(out));
        } catch (IOException e) {
            throw e;
        } catch (Exception e) {
            throw new IOException(ThrowableUtil.reason(e));
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }
}
