package nthx.ant;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;

import java.io.*;
import java.util.Vector;
import java.util.Date;

/** Ant task to generate main test class, which runs all found tests.
 *  <p>Use:
 *  <pre>
 *   &lt;target name="tests_generated_master" depends="read_params"&gt;
 *       &lt;taskdef name="master_test_gen" classname="nthx.ant.TestDifferentator"/&gt;
 *       &lt;master_test_gen
 *         masterTestFile="src/main/nthx/ilybra/tests/MasterTest.java"
 *         masterTestClass="MasterTest"
 *         masterTestPackage="nthx.ilybra.tests"&gt;
 *               &lt;fileset dir="${src.main.dir}"&gt;
 *                   &lt;include name="**<s>/</s>*Test.java"/&gt;
 *                   &lt;exclude name="**<s>/</s>*MasterTest.java"/&gt;
 *                   &lt;exclude name="**<s>/</s>Log4j*.java"/&gt;
 *               &lt;/fileset&gt;
 *       &lt;/master_test_gen&gt;
 *   &lt;/target&gt;
 *  </pre>
 *  
 *  @version $Id: TestDifferentator.java.html,v 1.3 2003/08/11 21:56:44 nthx Exp $
 *  @author nthx@irc.pl
 */
public class TestDifferentator
       extends Task{

    protected File masterTestFile = null;
    protected String masterTestClass = null;
    protected String masterTestPackage = null;

    protected Vector filesets = new Vector();

    public TestDifferentator() {
    }

    public void addFileset(FileSet set) {
        filesets.addElement(set);
    }

    //-----------main-------------
    public void execute() throws BuildException {
        validateAttributes();

        try {
            // deal with the filesets
            for (int i = 0; i < filesets.size(); i++)
            {
                FileSet fs = (FileSet) filesets.elementAt(i);
                DirectoryScanner ds = fs.getDirectoryScanner(project);

                String[] srcFiles = ds.getIncludedFiles();

                PrintWriter printWriter = null;
                try
                {
                    printWriter = new PrintWriter(new FileWriter(getMasterTestFile()));
                    writeMasterTest(printWriter, srcFiles);

                } catch (IOException e)
                {
                    log(e.getMessage());
                } finally {
                    printWriter.close();
                }
            }
        } finally {
            // clean up again, so this instance can be used a second
            // time
            masterTestFile = null;
        }
    }

    protected void validateAttributes() throws BuildException {
        if (getMasterTestFile()==null)
            throw new BuildException("No input file!");
    }

    private void writeMasterTest(PrintWriter writer, String[] files)
    {
        //package some.package
        writeMasterTestHeaderFirst(writer);

        //new MasterTest {
        writeMasterTestHeaderThird(writer);

        for (int i=0; i<files.length; i++)
            println(writer, "        result.addTest(new TestSuite("
                            + getClass(files[i])
                            + ".class));"
            );

        writeMasterTestFooter(writer);
    }

    private String getClass(String file)
    {
        int dotJavaIndex = file.lastIndexOf('.');
        String className = file.substring(0, dotJavaIndex);
        className = className.replace('/', '.');
        return className;
    }

    private void writeMasterTestHeaderFirst(PrintWriter writer)
    {
        println(writer, "package " + getMasterTestPackage() + ";");
        println(writer, "import junit.framework.Test;");
        println(writer, "import junit.framework.TestCase;");
        println(writer, "import junit.framework.TestSuite;");
    }

    private void writeMasterTestHeaderThird(PrintWriter writer)
    {
        println(writer, "");
        println(writer, "/**");
        println(writer, " *  @author Generated by nthx's ant task: " + (new Date()).toString());
        println(writer, " *  @version $Id: TestDifferentator.java.html,v 1.3 2003/08/11 21:56:44 nthx Exp $");
        println(writer, " */");
        println(writer, "public class " + getMasterTestClass());
        println(writer, "       extends TestCase");
        println(writer, "{");
        println(writer);
        println(writer, "    public "+getMasterTestClass()+"(String arg0)");
        println(writer, "    {");
        println(writer, "        super(arg0);");
        println(writer, "    }");
        println(writer);
        println(writer, "    public static void main(String[] args)");
        println(writer, "    {");
        println(writer, "        junit.textui.TestRunner.run(suite());");
        println(writer, "    }");
        println(writer);
        println(writer, "    public static Test suite()");
        println(writer, "    {");
        println(writer, "        TestSuite result = new TestSuite();");
        println(writer);
    }

    private void writeMasterTestFooter(PrintWriter writer)
    {
        println(writer);
        println(writer, "        return result; ");
        println(writer);
        println(writer, "    }");
        println(writer, "}");
    }

    private void println(PrintWriter writer, String line){
        writer.print(line + "\n");
    }
    private void println(PrintWriter writer){
        println(writer, "");
    }
    //---getters and setters -----------------------
    public Vector getFilesets() {
        return filesets;
    }

    public void setFilesets(Vector filesets) {
        this.filesets = filesets;
    }
    public File getMasterTestFile() {
        return masterTestFile;
    }
    public void setMasterTestFile(File masterTestFile) {
        this.masterTestFile = masterTestFile;
    }
    public String getMasterTestPackage() {
        return masterTestPackage;
    }
    public void setMasterTestPackage(String masterTestPackage) {
        this.masterTestPackage = masterTestPackage;
    }
    public String getMasterTestClass() {
        return masterTestClass;
    }
    public void setMasterTestClass(String masterTestClass) {
        this.masterTestClass = masterTestClass;
    }

}