/*
 * Created on Mar 19, 2008 (C) Copyright TANDBERG Television Ltd.
 */

package com.tandbergtv.watchpoint.pmm.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
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 org.apache.log4j.Logger;
import org.w3c.dom.Document;

import com.tandbergtv.watchpoint.pmm.util.ActionException;

/**
 * Utility methods to load / save XML Documents.
 * 
 * @author Vijay Silva
 */
public final class XMLUtility {

	private static final Logger logger = Logger.getLogger(XMLUtility.class);

	/* Cannot instantiate */
	private XMLUtility() {
	}

	/**
	 * Load the XML Document from the specified file path.
	 * 
	 * @param xmlFilePath
	 *            The path to the XML File to load
	 * @return The Document
	 * @throws ActionException
	 *             Exception loading the XML Document
	 */
	public static Document loadXMLDocument(String xmlFilePath) throws ActionException {
		return loadXMLDocument(new File(xmlFilePath));
	}

	/**
	 * Load the XML Document from the specified file.
	 * 
	 * @param xmlFile
	 *            The XML File to load
	 * @return The Document
	 * @throws ActionException
	 *             Exception loading the XML Document
	 */
	public static Document loadXMLDocument(File xmlFile) throws ActionException {
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			/* Ignore the external DTD completely */
			factory.setAttribute("http://apache.org/xml/features/nonvalidating/load-external-dtd", Boolean.FALSE);			
			DocumentBuilder documentBuilder = factory.newDocumentBuilder();
			return documentBuilder.parse(xmlFile);
		} catch (Exception e) {
			String message = "Failed to load the metadata XML document: " + xmlFile;
			throw new ActionException(message, e);
		}
	}

	/*
	 * Save the XML Document to the specified file
	 */
	public static void saveXMLDocument(Document document, File xmlFile) throws ActionException {
		OutputStream outputStream = null;
		try {
			TransformerFactory factory = TransformerFactory.newInstance();
			Transformer transformer = factory.newTransformer();

			/* Setting pretty formatting properties for output XML  */
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

			String xmlEncoding = document.getXmlEncoding();
			if (xmlEncoding != null)
				transformer.setOutputProperty(OutputKeys.ENCODING, xmlEncoding);

			// <!DOCTYPE ADI SYSTEM 'ADI.DTD'>
			transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "ADI.DTD");

			outputStream = new FileOutputStream(xmlFile);
			transformer.transform(new DOMSource(document), new StreamResult(outputStream));
		} catch (Exception e) {
			String message = "Failed to write XML document to file: " + xmlFile;
			throw new ActionException(message, e);
		} finally {
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (Exception ex) {
					logger.warn("Failed to close the file output stream for: " + xmlFile, ex);
				}
			}
		}
	}
}
