/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package freemarker.ext.ant;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.w3c.dom.Document;
import org.xml.sax.SAXParseException;

import freemarker.ext.dom.NodeModel;
import freemarker.ext.xml.NodeListModel;
import freemarker.template.Configuration;
import freemarker.template.SimpleHash;
import freemarker.template.SimpleScalar;
import freemarker.template.Template;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateNodeModel;
import freemarker.template._ObjectWrappers;
import freemarker.template.utility.ClassUtil;
import freemarker.template.utility.SecurityUtilities;


/**
 * <p>This is an <a href="http://jakarta.apache.org/ant/" target="_top">Ant</a> task for transforming
 * XML documents using FreeMarker templates. It uses the adapter class
 * {@link NodeListModel}. It will read a set of XML documents, and pass them to
 * the template for processing, building the corresponding output files in the
 * destination directory.</p>
 * <p>It makes the following variables available to the template in the data model:</p>
 * <ul>
 * <li>{@code document}: <em>Deprecated!</em> The DOM tree of the currently processed XML file wrapped
      with the legacy {@link freemarker.ext.xml.NodeListModel}.
      For new projects you should use the {@code .node} instead, which initially
      contains the DOM Document wrapped with {@link freemarker.ext.dom.NodeModel}.</li>
 * <li>{@code properties}: a {@link freemarker.template.SimpleHash} containing
 * properties of the project that executes the task</li>
 * <li>{@code userProperties}: a {@link freemarker.template.SimpleHash} containing
 * user properties of the project that executes the task</li>
 * <li>{@code project}: the DOM tree of the XML file specified by the
 * {@code projectfile}. It will not be available if you didn't specify the
 * {@code projectfile} attribute.</li>
 * <li>further custom models can be instantiated and made available to the 
 * templates using the {@code models} attribute.</li>
 * </ul>
 * <p>It supports the following attributes:</p>
 * <table style="width: auto; border-collapse: collapse" border="1">
 *   <caption style="display: none">FreeMarker XML ant task attributes</caption>
 *   <tr>
 *     <th valign="top">Attribute</th>
 *     <th valign="top">Description</th>
 *     <th valign="top">Required</th>
 *   </tr>
 *   <tr>
 *     <td valign="top">basedir</td>
 *     <td valign="top">location of the XML files. Defaults to the project's
 *       basedir.</td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">destdir</td>
 *     <td valign="top">location to store the generated files.</td>
 *     <td valign="top">Yes</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">includes</td>
 *     <td valign="top">comma-separated list of patterns of files that must be
 *       included; all files are included when omitted.</td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">includesfile</td>
 *     <td valign="top">the name of a file that contains
 *       include patterns.</td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">excludes</td>
 *     <td valign="top">comma-separated list of patterns of files that must be
 *       excluded; no files (except default excludes) are excluded when omitted.</td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">excludesfile</td>
 *     <td valign="top">the name of a file that contains
 *       exclude patterns.</td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">defaultexcludes</td>
 *     <td valign="top">indicates whether default excludes should be used
 *       (<code>yes</code> | <code>no</code>); default excludes are used when omitted.</td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">extension</td>
 *     <td valign="top">extension of generated files. Defaults to .html.</td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">template</td>
 *     <td valign="top">name of the FreeMarker template file that will be
 *       applied by default to XML files</td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">templateDir</td>
 *     <td valign="top">location of the FreeMarker template(s) to be used, defaults
 *                       to the project's baseDir</td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">projectfile</td>
 *     <td valign="top">path to the project file. The poject file must be an XML file.
 *       If omitted, it will not be available to templates </td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">incremental</td>
 *     <td valign="top">indicates whether all files should be regenerated (no), or
 *       only those that are older than the XML file, the template file, or the
 *       project file (yes). Defaults to yes. </td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">encoding</td>
 *     <td valign="top">The encoding of the output files. Defaults to platform
 *       default encoding.</td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">templateEncoding</td>
 *     <td valign="top">The encoding of the template files. Defaults to platform
 *       default encoding.</td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">validation</td>
 *     <td valign="top">Whether to validate the XML input. Defaults to off.</td>
 *     <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">models</td>
 *     <td valign="top">A list of [name=]className pairs separated by spaces,
 *      commas, or semicolons that specifies further models that should be 
 *      available to templates. If name is omitted, the unqualified class name
 *      is used as the name. Every class that is specified must implement the
 *      TemplateModel interface and have a no-args constructor.</td>
 *     <td valign="top">No</td>
 *   </tr>
 * </table>
 * 
 * <p>It supports the following nesed elements:</p>
 * 
 * <table style="width: auto; border-collapse: collapse" border="1">
 *   <caption style="display: none">FreeMarker XML ant task nested elements</caption>
 *   <tr>
 *     <th valign="top">Element</th>
 *     <th valign="top">Description</th>
 *     <th valign="top">Required</th>
 *   </tr>
 *   <tr>
 *     <td valign="top">prepareModel</td>
 *     <td valign="top">
 *      This element executes Jython script before the processing of each XML
 *      files, that you can use to modify the data model.
 *      You either enter the Jython script directly nested into this
 *      element, or specify a Jython script file with the {@code file}
 *      attribute.
 *      The following variables are added to the Jython runtime's local
 *      namespace before the script is invoked:
 *      <ul>
 *        <li>{@code model}: The data model as <code>java.util.HashMap</code>.
 *           You can read and modify the data model with this variable.
 *        <li>{@code doc}: The XML document as <code>org.w3c.dom.Document</code>.
 *        <li>{@code project}: The project document (if used) as
 *           <code>org.w3c.dom.Document</code>.
 *      </ul>
 *      <i>If this element is used, Jython classes (tried with Jython 2.1)
 *      must be available.</i>
 *    </td>
 *    <td valign="top">No</td>
 *   </tr>
 *   <tr>
 *     <td valign="top">prepareEnvironment</td>
 *     <td valign="top">This element executes Jython script before the processing
 *      of each XML files, that you can use to modify the freemarker environment
 *      ({@link freemarker.core.Environment}). The script is executed after the
 *      {@code prepareModel} element. The accessible Jython variables are the
 *      same as with the {@code prepareModel} element, except that there is no
 *      {@code model} variable, but there is {@code env} variable, which is
 *      the FreeMarker environment ({@link freemarker.core.Environment}).
 *      <i>If this element is used, Jython classes (tried with Jython 2.1)
 *      must be available.</i>
 *    </td>
 *    <td valign="top">No</td>
 *   </tr>
 * </table>
 * @deprecated <a href="http://fmpp.sourceforge.net">FMPP</a> is a more complete solution.
 */
@Deprecated
public class FreemarkerXmlTask
extends
    MatchingTask {
    private JythonAntTask prepareModel;
    private JythonAntTask prepareEnvironment;
    private final DocumentBuilderFactory builderFactory;
    private DocumentBuilder builder;
    
    /** the {@link Configuration} used by this task. */
    private Configuration cfg = new Configuration();
    
    /** the destination directory */
    private File destDir;

    /** the base directory */
    private File baseDir;

    //Where the templates live
    
    private File templateDir;
    
    /** the template= attribute */
    private String templateName;

    /** The template in its parsed form */
    private Template parsedTemplate;

    /** last modified of the template sheet */
    private long templateFileLastModified = 0;

    /** the projectFile= attribute */
    private String projectAttribute = null;

    private File projectFile = null;

    /** The DOM tree of the project wrapped into FreeMarker TemplateModel */
    private TemplateModel projectTemplate;
    // The DOM tree wrapped using the freemarker.ext.dom wrapping.
    private TemplateNodeModel projectNode;
    private TemplateModel propertiesTemplate;
    private TemplateModel userPropertiesTemplate;

    /** last modified of the project file if it exists */
    private long projectFileLastModified = 0;

    /** check the last modified date on files. defaults to true */
    private boolean incremental = true;

    /** the default output extension is .html */
    private String extension = ".html";

    private String encoding = SecurityUtilities.getSystemProperty("file.encoding", "utf-8");
    private String templateEncoding = encoding;
    private boolean validation = false;

    private String models = "";
    private final Map modelsMap = new HashMap();
    
    
    
    /**
     * Constructor creates the SAXBuilder.
     */
    public FreemarkerXmlTask() {
        builderFactory = DocumentBuilderFactory.newInstance();
        builderFactory.setNamespaceAware(true);
    }

    /**
     * Set the base directory. Defaults to {@code .}
     */
    public void setBasedir(File dir) {
        baseDir = dir;
    }

    /**
     * Set the destination directory into which the generated
     * files should be copied to
     * @param dir the name of the destination directory
     */
    public void setDestdir(File dir) {
        destDir = dir;
    }

    /**
     * Set the output file extension. {@code .html} by default.
     */
    public void setExtension(String extension) {
        this.extension = extension;
    }

    public void setTemplate(String templateName) {
        this.templateName = templateName;
    }
    
    public void setTemplateDir(File templateDir) throws BuildException {
        this.templateDir = templateDir;
        try {
            cfg.setDirectoryForTemplateLoading(templateDir);
        } catch (Exception e) {
            throw new BuildException(e);
        }
    }

    /**
     * Set the path to the project XML file
     */
    public void setProjectfile(String projectAttribute) {
        this.projectAttribute = projectAttribute;
    }

    /**
     * Turn on/off incremental processing. On by default
     */
    public void setIncremental(String incremental) {
        this.incremental = !(incremental.equalsIgnoreCase("false") || incremental.equalsIgnoreCase("no") || incremental.equalsIgnoreCase("off"));
    }

    /**
     * Set encoding for generated files. Defaults to platform default encoding.
     */
    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public void setTemplateEncoding(String inputEncoding) {
        this.templateEncoding = inputEncoding;
    }
    
    /**
     * Sets whether to validate the XML input.
     */
    public void setValidation(boolean validation) {
        this.validation = validation;
    }

    public void setModels(String models) {
        this.models = models;
    }
    
    @Override
    public void execute() throws BuildException {
        DirectoryScanner scanner;
        String[]         list;

        if (baseDir == null) {
            baseDir = getProject().getBaseDir();
        }
        if (destDir == null ) {
            String msg = "destdir attribute must be set!";
            throw new BuildException(msg, getLocation());
        }
        
        File templateFile = null;

        if (templateDir == null) {
            if (templateName != null) {
                templateFile = new File(templateName);
                if (!templateFile.isAbsolute()) {
                    templateFile = new File(getProject().getBaseDir(), templateName);
                }
                templateDir = templateFile.getParentFile();
                templateName = templateFile.getName();
            } else {
                templateDir = baseDir;
            }
            setTemplateDir(templateDir);
        } else if (templateName != null) {
            if (new File(templateName).isAbsolute()) {
                throw new BuildException("Do not specify an absolute location for the template as well as a templateDir");
            }
            templateFile = new File(templateDir, templateName);
        }
        if (templateFile != null) {
            templateFileLastModified = templateFile.lastModified();
        }

        try {
            if (templateName != null) {
                parsedTemplate = cfg.getTemplate(templateName, templateEncoding);
            }
        } catch (IOException ioe) {
            throw new BuildException(ioe.toString());
        }
        // get the last modification of the template
        log("Transforming into: " + destDir.getAbsolutePath(), Project.MSG_INFO);

        // projectFile relative to baseDir
        if (projectAttribute != null && projectAttribute.length() > 0) {
            projectFile = new File(baseDir, projectAttribute);
            if (projectFile.isFile())
                projectFileLastModified = projectFile.lastModified();
            else {
                log ("Project file is defined, but could not be located: " +
                     projectFile.getAbsolutePath(), Project.MSG_INFO );
                projectFile = null;
            }
        }

        generateModels();
        
        // find the files/directories
        scanner = getDirectoryScanner(baseDir);

        propertiesTemplate = wrapMap(project.getProperties());
        userPropertiesTemplate = wrapMap(project.getUserProperties());

        builderFactory.setValidating(validation);
        try {
            builder = builderFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new BuildException("Could not create document builder", e, getLocation());
        }

        // get a list of files to work on
        list = scanner.getIncludedFiles();
        
        
        for (int i = 0; i < list.length; ++i) {
            process(baseDir, list[i], destDir);
        }
    }
    
    public void addConfiguredJython(JythonAntTask jythonAntTask) {
        this.prepareEnvironment = jythonAntTask;
    }

    public void addConfiguredPrepareModel(JythonAntTask prepareModel) {
        this.prepareModel = prepareModel;
    }

    public void addConfiguredPrepareEnvironment(JythonAntTask prepareEnvironment) {
        this.prepareEnvironment = prepareEnvironment;
    }
    
    /**
     * Process an XML file using FreeMarker
     */
    private void process(File baseDir, String xmlFile, File destDir)
    throws BuildException {
        File outFile = null;
        File inFile = null;
        try {
            // the current input file relative to the baseDir
            inFile = new File(baseDir,xmlFile);
            // the output file relative to basedir
            outFile = new File(destDir,
                               xmlFile.substring(0,
                                                 xmlFile.lastIndexOf('.')) + extension);

            // only process files that have changed
            if (!incremental ||
                (inFile.lastModified() > outFile.lastModified() ||
                 templateFileLastModified > outFile.lastModified() ||
                 projectFileLastModified > outFile.lastModified())) {
                ensureDirectoryFor(outFile);

                //-- command line status
                log("Input:  " + xmlFile, Project.MSG_INFO );
                
                if (projectTemplate == null && projectFile != null) {
                    Document doc = builder.parse(projectFile);
                    projectTemplate = new NodeListModel(builder.parse(projectFile));
                    projectNode = NodeModel.wrap(doc);
                }

                // Build the file DOM
                Document docNode = builder.parse(inFile);
                
                TemplateModel document = new NodeListModel(docNode);
                TemplateNodeModel docNodeModel = NodeModel.wrap(docNode);
                HashMap root = new HashMap();
                root.put("document", document);
                insertDefaults(root);

                // Process the template and write out
                // the result as the outFile.
                try (Writer writer = new BufferedWriter(
                        new OutputStreamWriter(new FileOutputStream(outFile), encoding))) {
                    if (parsedTemplate == null) {
                        throw new BuildException("No template file specified in build script or in XML file");
                    }
                    if (prepareModel != null) {
                        Map vars = new HashMap();
                        vars.put("model", root);
                        vars.put("doc", docNode);
                        if (projectNode != null) {
                            vars.put("project", ((NodeModel) projectNode).getNode());
                        }
                        prepareModel.execute(vars);
                    }
                    freemarker.core.Environment env = parsedTemplate.createProcessingEnvironment(root, writer);
                    env.setCurrentVisitorNode(docNodeModel);
                    if (prepareEnvironment != null) {
                        Map vars = new HashMap();
                        vars.put("env", env);
                        vars.put("doc", docNode);
                        if (projectNode != null) {
                            vars.put("project", ((NodeModel) projectNode).getNode());
                        }
                        prepareEnvironment.execute(vars);
                    }
                    env.process();
                    writer.flush();
                }

                log("Output: " + outFile, Project.MSG_INFO );
                
            }
        } catch (SAXParseException spe) {
            Throwable rootCause = spe;
            if (spe.getException() != null)
                rootCause = spe.getException();
            log("XML parsing error in " + inFile.getAbsolutePath(), Project.MSG_ERR);
            log("Line number " + spe.getLineNumber());
            log("Column number " + spe.getColumnNumber());
            throw new BuildException(rootCause, getLocation());
        } catch (Throwable e) {
            if (outFile != null ) {
                if (!outFile.delete() && outFile.exists()) {
                    log("Failed to delete " + outFile, Project.MSG_WARN);
                }
            }
            e.printStackTrace();
            throw new BuildException(e, getLocation());
        }
    }

    private void generateModels() {
        StringTokenizer modelTokenizer = new StringTokenizer(models, ",; ");
        while (modelTokenizer.hasMoreTokens()) {
            String modelSpec = modelTokenizer.nextToken();
            String name = null;
            String clazz = null;
            
            int sep = modelSpec.indexOf('=');
            if (sep == -1) {
                // No explicit name - use unqualified class name
                clazz = modelSpec;
                int dot = clazz.lastIndexOf('.');
                if (dot == -1) {
                    // clazz in the default package
                    name = clazz;
                } else {
                    name = clazz.substring(dot + 1);
                }
            } else {
                name = modelSpec.substring(0, sep);
                clazz = modelSpec.substring(sep + 1);
            }
            try {
                modelsMap.put(name, ClassUtil.forName(clazz).newInstance());
            } catch (Exception e) {
                throw new BuildException(e);
            }
        }
    }
    
    /**
     * create directories as needed
     */
    private void ensureDirectoryFor( File targetFile ) throws BuildException {
        File directory = new File( targetFile.getParent() );
        if (!directory.exists()) {
            if (!directory.mkdirs()) {
                throw new BuildException("Unable to create directory: "
                                         + directory.getAbsolutePath(), getLocation());
            }
        }
    }

    private static TemplateModel wrapMap(Map table) {
        SimpleHash model = new SimpleHash(_ObjectWrappers.SAFE_OBJECT_WRAPPER);
        for (Iterator it = table.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry entry = (Map.Entry) it.next();
            model.put(String.valueOf(entry.getKey()), new SimpleScalar(String.valueOf(entry.getValue())));
        }
        return model;
    }

    protected void insertDefaults(Map root) {
        root.put("properties", propertiesTemplate);
        root.put("userProperties", userPropertiesTemplate);
        if (projectTemplate != null) {
            root.put("project", projectTemplate);
            root.put("project_node", projectNode);
        }
        if (modelsMap.size() > 0) {
            for (Iterator it = modelsMap.entrySet().iterator(); it.hasNext(); ) {
                Map.Entry entry = (Map.Entry) it.next();
                root.put(entry.getKey(), entry.getValue());
            }
        }
    }
    
}
