package org.anarres.gradle.plugin.velocity;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.log.SystemLogChute;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.Task;
import org.gradle.api.file.ConfigurableFileTree;
import org.gradle.api.file.EmptyFileVisitor;
import org.gradle.api.file.FileVisitDetails;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputDirectory;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputDirectory;

/**
 * A bare velocity task.
 *
 * You may use this to do arbitrary velocity processing without
 * necessarily applying the plugin.
 *
 * @author shevek
 */
public class VelocityTask extends DefaultTask {

    @InputDirectory
    public File inputDir;
    @OutputDirectory
    public File outputDir;

    @Input
    public String filter = "**/*.java";
    @Optional
    @InputDirectory
    public File includeDir;
    @Input
    public Map<String, Object> contextValues = new HashMap<String, Object>();

    public VelocityTask() {
        doLast(new Action<Task>() {

            @Override
            public void execute(Task task) {
                DefaultGroovyMethods.deleteDir(outputDir);
                outputDir.mkdirs();

                final VelocityEngine engine = new VelocityEngine();
                engine.setProperty(VelocityEngine.RUNTIME_LOG_LOGSYSTEM_CLASS, SystemLogChute.class.getName());
                engine.setProperty(VelocityEngine.RESOURCE_LOADER, "file");
                engine.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_CACHE, "true");
                if (includeDir != null)
                    engine.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, includeDir.getAbsolutePath());
                else
                    engine.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, inputDir.getAbsolutePath());

                ConfigurableFileTree inputFiles = getProject().fileTree(inputDir);
                inputFiles.include(filter);
                inputFiles.visit(new EmptyFileVisitor() {
                    @Override
                    public void visitFile(FileVisitDetails fvd) {
                        try {
                            File outputFile = fvd.getRelativePath().getFile(outputDir);
                            VelocityContext context = new VelocityContext();
                            for (Map.Entry<String, Object> e : contextValues.entrySet())
                                context.put(e.getKey(), e.getValue());
                            context.put("project", getProject());
                            context.put("package", DefaultGroovyMethods.join(fvd.getRelativePath().getParent().getSegments(), "."));
                            context.put("class", fvd.getRelativePath().getLastName().replaceFirst("\\.java$", ""));
                            FileReader reader = new FileReader(fvd.getFile());
                            try {
                                outputFile.getParentFile().mkdirs();
                                FileWriter writer = new FileWriter(outputFile);
                                try {
                                    engine.evaluate(context, writer, fvd.getRelativePath().toString(), reader);
                                } finally {
                                    writer.close();
                                }
                            } finally {
                                reader.close();
                            }
                        } catch (IOException e) {
                            throw new GradleException("Failed to process " + fvd, e);
                        }
                    }
                });
            }
        });
    }
}

@@ -1634,39 +1634,32 @@
                 
-engine.
 setProperty(Velo
@@ -1646,32 +1646,40 @@
     setProperty(
+engine, 
 VelocityEngine.R
@@ -1747,39 +1747,32 @@
                 
-engine.
 setProperty(Velo
@@ -1759,32 +1759,40 @@
     setProperty(
+engine, 
 VelocityEngine.R
@@ -1824,39 +1824,32 @@
                 
-engine.
 setProperty(Velo
@@ -1836,32 +1836,40 @@
     setProperty(
+engine, 
 VelocityEngine.F
@@ -1956,39 +1956,32 @@
                 
-engine.
 setProperty(Velo
@@ -1968,32 +1968,40 @@
     setProperty(
+engine, 
 VelocityEngine.F
@@ -2098,23 +2098,16 @@
         
-engine.
 setPrope
@@ -2110,16 +2110,24 @@
 roperty(
+engine, 
 Velocity
@@ -2581,32 +2581,201 @@
 ile(outputDir);%0A
+                            if (getLogger().isDebugEnabled())%0A                                getLogger().debug(%22Preprocessing %22 + fvd.getFile() + %22 -%3E %22 + outputFile);%0A
                 
@@ -4205,11 +4205,265 @@
 );%0A    %7D
+%0A%0A    private void setProperty(VelocityEngine engine, String name, Object value) %7B%0A        if (getLogger().isDebugEnabled())%0A            getLogger().debug(%22VelocityEngine property: %22 + name + %22 = %22 + value);%0A        engine.setProperty(name, value);%0A    %7D
 %0A%7D%0A

Make property-setting verbose.