/*
 * Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the
 * License at http://www.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.xmlutil;

import org.jdom.JDOMException;
import org.jdom.Element;
import org.jdom.Document;
import org.jdom.output.XMLOutputter;
import org.jdom.input.SAXBuilder;
import org.jdom.input.JDOMFactory;
import org.apache.log4j.Logger;

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.*;

public class DocImporter {

    public DocImporter(final boolean isValidating) {
        m_builder = new SAXBuilder(isValidating);
    }


    public void setJDOMFactory(JDOMFactory f) {
       m_builder.setFactory(f);
    }
    /**
     * This method takes a list of JDOM Elements that refer to some XML document.
     * The exact type of the element does not matter, so long as it has an attriube
     * named 'resource', which gives a path to some XML file.
     *
     * The method inputs each XML document and appends them to a list which is
     * returned to the caller.
     *
     * @param docRefs List of JDOM Elements referring to XML documents.
     * @return List of JDOM Documents.
     *
     * @throws JDOMException on parse error.
     *
     */
    public List getDocuments(List docRefs) throws JDOMException {
        List documents = new ArrayList( docRefs.size() );
        for (Iterator iterator = docRefs.iterator(); iterator.hasNext();) {
            Element fileRef = (Element) iterator.next();
            String resource = fileRef.getAttributeValue("resource");
            Document doc = getDocumentAsResource(resource);
            documents.add(doc);
        }
        return documents;
    }

    /**
     * Imports a document.
     *
     * @param resource The path to the resource. This must be on the classpath.
     *
     */
    public Document getDocumentAsResource(String resource) throws JDOMException {
        s_log.warn("Loading " + resource);
        InputStream is = getClass().getClassLoader().getResourceAsStream(resource);
        if( null == is ) {
            throw new JDOMException("Couldn't find test definition file: " + resource);
        }
        Document doc = importDocument(is, resource);

        return doc;
    }

    public Document getDocumentAsFile(String filename) throws JDOMException {
        FileInputStream is = null;
        try {
            is = new FileInputStream(filename);
            Document doc = importDocument(is, filename);
            return doc;

        } catch (FileNotFoundException e) {
            throw new JDOMException("No such file: " + filename);
        } finally {
            if ( is != null ) {
                try {
                    is.close();
                } catch (IOException e) {
                    s_log.error("Problem closing file: " + filename, e);
                }
            }
        }

    }


    private Document importDocument(InputStream is, String resource) throws JDOMException {
        Document doc;
        try {
            doc = m_builder.build(is);
        } catch(IOException e) {
            throw new JDOMException("Error loading document: " + resource, e);
        }

        logDocument(doc);
        return doc;
    }

    /**
     * Outputs the document to a log, if debugging is enabled.
     *
     * @param doc The document to output
     */
    private void logDocument(Document doc) {
        if ( s_log.isDebugEnabled() ) {
            XMLOutputter xmlOut = new XMLOutputter();
            StringWriter writer = new StringWriter();
            try {
                xmlOut.output(doc, writer);
                s_log.debug(writer.toString());
            } catch (IOException e) {
                s_log.error("Problem outputting document.", e);
            }
        }
    }
    private SAXBuilder m_builder;
    private static Logger s_log = Logger.getLogger(DocImporter.class);
}
