/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2005-2008 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
*/
package org.ow2.jonas.ant;

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

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Java;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;

/**
 * GenIC Task. That's basically an Ant Task wrapper around GenIC.
 *
 * @author Guillaume Sauthier
 */
public class GenICTask extends BootstrapTask {

    /** GenIC class name. */
    private static final String GENIC_CLASS = "org.ow2.jonas.generators.genic.GenIC";

    /** validation of XML files ? */
    private boolean validation = true;

    /** name of javac command. */
    private String javac       = null;

    /** list of javac options. */
    private String javacOpts  = null;

    /** will GenIC keep already generated files ? */
    private boolean keepGen   = false;

    /**
     * specifies which RMIC compiler to user: the built-in one or the external
     * one.
     */
    private boolean noFastRMIC = false;

    /** protocol list. */
    private String protocols = null;

    /** nocompil. */
    private boolean nocompil = false;

    /** Invoke Javac with tools.jar. */
    private boolean invokeCmd = false;

    /** Options for rmic compiler. */
    private String rmicOpts = null;

    /** extra arguments to be passed to GenIC. */
    private String additionalArgs = null;

    /** verbose mode. */
    private boolean verbose = false;

    /** additionnal classpath for libs. */
    private Path libraryClasspath = null;

    /** inner FileSet list. */
    private List<FileSet> filesets = new ArrayList<FileSet>();

    /** debug field. */
    private boolean debug = false;

    /**
     * @return Returns an empty Path for inner element classpath
     */
    @Override
    public Path createClasspath() {
        libraryClasspath = new Path(getProject());
        return libraryClasspath;
    }

    /**
     * @return Returns an empty FileSet
     */
    public FileSet createFileSet() {
        FileSet set = new FileSet();
        set.setProject(getProject());
        filesets.add(set);
        return set;
    }

    /**
     * Set additional arguments for GenIC command line.
     * @param added additional args
     */
    public void setAdditionalargs(final String added) {
        additionalArgs = added;
    }

    /**
     * Set verbose mode on/off.
     * @param v boolean
     */
    public void setVerbose(final boolean v) {
        verbose = v;
    }

    /**
     * Set debug mode on/off. Used only by developers that wants to Debug GenIC
     * @param d boolean
     */
    public void setJvmdebug(final boolean d) {
        debug = d;
    }

    /**
     * Use InvokeCmd option on/off.
     * @param inv boolean
     */
    public void setInvokecmd(final boolean inv) {
        invokeCmd = inv;
    }

    /**
     * Do not compile generated java files.
     * @param noc on/off
     */
    public void setNocompil(final boolean noc) {
        nocompil = noc;
    }

    /**
     * Set the optios to be passed to the RMI compiler.
     * @param opts list of options
     */
    public void setRmicopts(final String opts) {
        rmicOpts = opts;
    }

    /**
     * Validate XML descriptors.
     * @param v on/off
     */
    public void setValidation(final boolean v) {
        validation = v;
    }

    /**
     * Set the javac command line to be used.
     * @param j path to javac executable
     */
    public void setJavac(final String j) {
        javac = j;
    }

    /**
     * Set the options to be given to javac.
     * @param opts options
     */
    public void setJavacopts(final String opts) {
        javacOpts = opts;
    }

    /**
     * Keep already generated files.
     * @param k on/off
     */
    public void setKeepgenerated(final boolean k) {
        keepGen = k;
    }

    /**
     * Specifies which RMIC compiler to use: the built-in fast one or the
     * slower external one.
     * @param value if true, use the external RMIC compiler
     */
    public void setNoFastRMIC(final boolean value) {
        noFastRMIC = value;
    }

    /**
     * Set the set of protocols for the generation.
     * @param p protocol list (comma separated)
     */
    public void setProtocols(final String p) {
        protocols = p;
    }

    /**
     * Execute the WsGen Ant Task.
     * @throws BuildException if something goes wrong
     */
    @Override
    public void execute() throws BuildException {

        // avoid a -n jonas in the GenIC command line
        setServerName(null);

        for (Iterator<FileSet> fsIterator = filesets.iterator(); fsIterator.hasNext();) {
            FileSet set = fsIterator.next();
            DirectoryScanner ds = set.getDirectoryScanner(getProject());
            ds.scan();
            String[] files = ds.getIncludedFiles();
            File srcDirectory = set.getDir(getProject());
            for (int i = 0; i < files.length; i++) {

                Java genic = getBootstraptask(GENIC_CLASS);

                configureGenIC(genic, srcDirectory + File.separator + files[i]);

                // calling GenIC task
                log("Calling  GenIC task for '" + srcDirectory + File.separator + files[i] + "'.", Project.MSG_VERBOSE);

                if (genic.executeJava() != 0) {
                    throw new BuildException("GenIC reported an error.");
                }
            }
        }

    }

    /**
     * @param genicJavaTask GenIC Task to be configured for GenIC
     * @param filename name of the file to pass into GenIC
     * @return a configured Java Task
     * @throws BuildException if something goes wrong
     */
    private Java configureGenIC(final Java genicJavaTask, final String filename) throws BuildException {

        // keepgenerated
        if (keepGen) {
            genicJavaTask.createArg().setValue("-keepgenerated");
        }

        if (noFastRMIC) {
            genicJavaTask.createArg().setValue("-nofastrmic");
        }

        // novalidation
        if (!validation) {
            genicJavaTask.createArg().setValue("-novalidation");
        }

        // classpath
        if (libraryClasspath != null) {
            genicJavaTask.createArg().setValue("-classpath");
            genicJavaTask.createArg().setPath(libraryClasspath);
        }

        // nocompil
        if (nocompil) {
            genicJavaTask.createArg().setValue("-nocompil");
        }

        // invokecmd
        if (invokeCmd) {
            genicJavaTask.createArg().setValue("-invokecmd");
        }

        // javac
        if (javac != null) {
            genicJavaTask.createArg().setValue("-javac");
            genicJavaTask.createArg().setLine(javac);
        }

        // javacopts
        if (javacOpts != null && !javacOpts.equals("")) {
            genicJavaTask.createArg().setValue("-javacopts");
            genicJavaTask.createArg().setLine(javacOpts);
        }

        // rmicopts
        if (rmicOpts != null && !rmicOpts.equals("")) {
            genicJavaTask.createArg().setValue("-rmicopts");
            genicJavaTask.createArg().setValue(rmicOpts);
        }

        // verbose
        if (verbose) {
            genicJavaTask.createArg().setValue("-verbose");
        }

        // debug
        if (debug) {
            this.log("Launching in debug mode on port 12345, waiting for connection ...", Project.MSG_INFO);
            genicJavaTask.createJvmarg().setLine("-Xdebug -Xnoagent -Xrunjdwp:transport="
                                                 + "dt_socket,server=y,address=12345,suspend=y");
        }

        // additionalargs
        if (additionalArgs != null) {
            genicJavaTask.createArg().setLine(additionalArgs);
        }

        // protocols
        if (protocols != null) {
            genicJavaTask.createArg().setValue("-protocols");
            genicJavaTask.createArg().setValue(protocols);
        }

        // input file to process by GenIC
        genicJavaTask.createArg().setValue(filename);

        return genicJavaTask;

    }

}
