/*
 * $Header: /home/harald/repos/remotetea.sf.net/remotetea/src/org/acplt/oncrpc/ant/JrpcgenTask.java,v 1.3 2003/08/14 09:47:17 haraldalbrecht Exp $
 *
 * Copyright (c) 2001
 * Daune Consult SPRL
 * Rue du monument, 1
 * 6530 Thirimont (Belgium)
 * All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) 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 Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this program (see the file LICENSE.txt for more
 * details); if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 */

package org.acplt.oncrpc.ant;

import java.io.File;
import java.io.IOException;

import org.acplt.oncrpc.apps.jrpcgen.JrpcgenContext;
import org.acplt.oncrpc.apps.jrpcgen.JrpcgenOptions;
import org.acplt.oncrpc.apps.jrpcgen.jrpcgen;
import org.apache.tools.ant.BuildException;

/**
 * Ant task to run the ONC/RPC '.x' file compiler provided in the Remote Tea
 * library: jrpcgen.
 *
 * <p>The Remote Tea library is a complete open source implementation of
 * the ONC/RPC standard, originally developed by the Chair of Process Control
 * Engineering of University of Aachen, Germany.
 * <p>Remote Tea can be found at
 * <a href="https://sourceforge.net/projects/remotetea/">
 * https://sourceforge.net/projects/remotetea/</a>.
 *
 * <p>The task attributes are:
 * <ul>
 * <li>srcfile   : '.x' file to compile (mandatory)</li>
 * <li>destdir   : directory where generated files need to be placed
 *                 (mandatory). If a 'package' directive is used,
 *                 do <b>not</b> add the package directories to destDir
 *                 (it is done automatically by the task) </li>
 * <li>package   : package name to be used for generated files (optional)</li>
 * <li>createdir : indicates whether jrpcgen must create destdir if it does
 *                 not exist (optional). Defaults to no.</li>
 * <li>verbose   : indicates whether jrpcgen must be verbose (optional).
 *                 Defaults to no.</li>
 * <li>debug     : indicates whether jrpcgen must trace debug information
 *                 (optional). Defaults to no.</li>
 * <li>backup    : indicates whether jrpcgen must backup files (optional).
 *                 Defaults to no.</li>
 * <li>noClient  : indicates whether jrpcgen shall skip the generation of
 *                 the client stub (optional). Defaults to no.</li>
 * <li>noServer  : indicates whether jrpcgen shall skip the generation of 
 *                 the server stub (optional). Defaults to no.</li>
 * <li>noXdr     : indicates whether jrpcgen shall skip the generation of
 *                 the XDR datatype classes (optional). Defaults to no.</li>
 * <li>serverTcpOnly : indicates whether jrpcgen shall generate the server
 *                     stub for the TCP transport, only (optional).
 *                     Defaults to no.</li>
 * <li>serverUdpOnly : indicates whether jrpcgen shall generate the server
 *                     stub for the UDP transport, only (optional).
 *                     Defaults to no.</li>
 * <li>bean      : indicates whether jrpcgen shall generate the XDR datatype
 *                 classes with getters and setters for bean usage (optional).
 *                 Setting this attribute to {@code true} implies setting the
 *                 attribute {@code serializable} to {@code true} as well.
 *                 Defaults to no.</li>
 * <li>serializable : indicates whether jrpcgen shall tag the XDR datatype
 * 					  classes as serializable by adding the private static final
 *                    field {@code serialVersionUID} (optional). Defaults to no.</li>
 * <li>noValueCtor  : indicates whether jrpcgen shall skip the generation of
 *                    value constructors for the XDR datatype classes (optional).
 *                    Defaults to no.</li>
 * <li>noToString   : indicates whether jrpcgen shall skip the generation of
 *                    the {@code toString()} - methods for the XDR datatype
 *                    classes (optional). Defaults to no.</li>
 * <li>noEquals     : indicates whether jrpcgen shall skip the generation of
 *                    the {@code equals()} - and {@code hashCode()} - methods
 *                    for the XDR datatype classes (optional). Defaults to no.</li>
 * <li>noEnum       : indicates whether jrpcgen shall fall back to Java interfaces
 *                    instead of Java enumerations as mapping for enumerations
 *                    specified in an x-file (optional). Defaults to no.</li>
 * <li>initStrings  : indicates whether jrpcgen shall intialize string fields
 *                    with an empty string instead of {@code null} (optional).
 *                    Defaults to no.</li>
 * <li>noClamp      : indicates whether generated client calls shall get the version
 *                    from the client instance instead of getting a hard coded value
 *                    referring to the version number specified in the x-file (optional).
 *                    Defaults to no.</li>
 * <li>withCallInfo : indicates whether the generated server stub methods shall get the
 *                    ONC/RPC call information as first parameter (optional).
 *                    Defaults to no.</li>
 * </ul>
 *
 * @author <a href="mailto:daune.jf@daune-consult.com">Jean-Francois Daune</a>
 * @author Harald Wirths {@literal <hwirths@nde.ag>}
 */
public class JrpcgenTask extends org.apache.tools.ant.Task {

    public void setSrcfile(java.io.File srcFile) {
        this.srcFile = srcFile;
    }

    public void setDestdir(java.io.File destDir) {
        this.destDir = destDir;
    }

    public void setPackage(java.lang.String packageName) {
        this.options.packageName = packageName;
    }

    public void setCreatedir(boolean createDir) {
        this.createDir = createDir;
    }

    public void setDebug(boolean debug) {
        this.options.debug = debug;
    }

    public void setVerbose(boolean verbose) {
        this.options.verbose = verbose;
    }

    public void setBackup(boolean backup) {
        this.options.noBackups = !backup;
    }

    public void setNoClient(boolean noClient) {
    	this.options.noClient = noClient;
    }
    
    public void setNoServer(boolean noServer) {
    	this.options.noServer = noServer;
    }
    
    public void setNoXdr(boolean noXdr) {
    	this.options.noXdr = noXdr;
    }
    
    public void setServerTcpOnly(boolean serverTcpOnly) {
    	this.options.serverTcpOnly = serverTcpOnly;
    }
    
    public void setServerUdpOnly(boolean serverUdpOnly) {
    	this.options.serverUdpOnly = serverUdpOnly;
    }
    
    public void setBean(boolean bean) {
    	if (bean) {
           	this.options.makeSerializable = bean;
    	}
    	
       	this.options.makeBean = bean;
    }
    
    public void setSerializable(boolean serializable) {
    	if (! this.options.makeBean) {
    		this.options.makeSerializable = serializable;
    	}
    }
    
    public void setNoValueCtor(boolean noValueCtor) {
    	this.options.noValueCtor = noValueCtor;
    }
    
    public void setNoToString(boolean noToString) {
    	this.options.noToString = noToString;
    }
    
    public void setNoEquals(boolean noEquals) {
    	this.options.noEquals = noEquals;
    }
    
    public void setNoEnum(boolean noEnum) {
    	this.options.noEnum = noEnum;
    }
    
    public void setInitStrings(boolean initStrings) {
    	this.options.initStrings = initStrings;
    }
    
    public void setNoClamp(boolean noClamp) {
    	this.options.clampProgAndVers = (! noClamp);
    }
    
    public void setWithCallInfo(boolean withCallInfo) {
    	this.options.withCallInfo = withCallInfo;
    }
    
    public void execute() throws BuildException {
        checkAttributes();

        try {
        	log("Compiling " + srcFile.getCanonicalPath());
            // System.out.println("Compiling " + srcFile.getCanonicalPath());
        }
        catch (IOException ex) {
        }

        if(options.packageName != null) {

            try {
                // Add the package name to destination dir
                destDir = new File(
                    destDir.getCanonicalPath() +
                    File.separator +
                    options.packageName.replace('.', File.separatorChar));
            }
            catch (IOException ex) {
                throw new BuildException(ex); // should never occur
            }
        }

        if (createDir) {
            // Create the destination dir if it does not exist
            try {
                if (!destDir.exists()) {
                    boolean dirsCreated = destDir.mkdirs();
                    if (!dirsCreated) {
                        throw new BuildException("Could not create destination dir" );
                    }
                }
            }
            catch (SecurityException ex) {
                throw new BuildException(ex);
            }
        }

        if (options.debug)
            dumpState();

        options.destinationDir = destDir;

        try (JrpcgenContext context = JrpcgenContext.open(options, srcFile, jrpcgen.VERSION)){
        	new jrpcgen(context).doParse().generateJavaFiles();
        }
        catch (Throwable t) {
            throw new BuildException(t);
        }

    }

    private void checkAttributes() throws BuildException {
        if(srcFile == null)
            throw new BuildException("srcfile has not been set");

        if(destDir == null)
            throw new BuildException("destdir has not been set");

        try {
            if(!srcFile.isFile())
                throw new BuildException("problem reading srcdir");

            if(!destDir.isDirectory())
                throw new BuildException("problem accessing srcdir");
        }
        catch(SecurityException ex) {
            throw new BuildException(ex);
        }
    }

    private void dumpState() {
        System.out.println(srcFile);
        System.out.println(destDir);
        System.out.println(createDir);
    	System.out.println(options);
    }

    private java.io.File srcFile;
    private java.io.File destDir;
    private boolean createDir = false;
    private final JrpcgenOptions options = new JrpcgenOptions();
    
}