/**
 * JaDOrT: JASMINe Deployment Orchestration Tool
 * Copyright (C) 2008-2009 Bull S.A.S.
 * Copyright (C) 2008-2009 France Telecom R&D
 * Contact: jasmine@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: JadortConsole.java 5038 2009-08-21 19:07:11Z alitokmen $
 * --------------------------------------------------------------------------
 */
package org.ow2.jasmine.jadort.client.console;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.ow2.easybeans.component.smartclient.spi.SmartContextFactory;
import org.ow2.jasmine.jadort.api.IJadortService;
import org.ow2.jasmine.jadort.api.entities.deployment.ApplicationBean;
import org.ow2.jasmine.jadort.api.entities.deployment.OperationStateBean;
import org.ow2.jasmine.jadort.api.entities.deployment.ServerProgressBean;
import org.ow2.jasmine.jadort.api.entities.deployment.VMImageBean;
import org.ow2.jasmine.jadort.api.entities.deployment.WorkerProgressBean;
import org.ow2.jasmine.jadort.api.entities.topology.GroupBean;
import org.ow2.jasmine.jadort.api.entities.topology.ServerBean;
import org.ow2.jasmine.jadort.api.entities.topology.WorkerBean;

/**
 * A command line client for JaDOrT
 * 
 * @author Remy Bresson
 */
public class JadortConsole {

    /**
     * List of user commands
     */
    private final static String UC_CREATE_NEW_OPERATION = "createNewOperation";

    private final static String UC_GET_OPERATION_LIST = "getOperationsList";

    private final static String UC_DELETE_OPERATION = "deleteOperation";

    private final static String UC_LOAD_TOPOLOGY = "loadTopology";

    private final static String UC_GET_GROUPS = "getGroups";

    private final static String UC_GET_VM_IMAGES = "getVMImages";

    private final static String UC_SELECT_GROUP = "selectGroup";

    private final static String UC_SELECT_OPERATION_TYPE = "selectOperationType";

    private final static String UC_SELECT_VM_IMAGE = "selectVMImage";

    private final static String UC_SELECT_VM_IMAGE_FOR_SERVER = "selectVMImageForServer";

    private final static String UC_SELECT_SERVERS = "selectServers";

    private final static String UC_GET_CURRENT_STEP = "getCurrentStep";

    private final static String UC_CAN_GO_NEXT = "canGoToNextStep";

    private final static String UC_NEXT = "next";

    private final static String UC_CAN_GO_PREVIOUS = "canGoToPreviousStep";

    private final static String UC_PREVIOUS = "previous";

    private final static String UC_GET_SERVER_PROGRESS_LIST = "getServerProgressList";

    private final static String UC_GET_WORKER_PROGRESS_LIST = "getWorkerProgressList";

    private final static String UC_GET_SELECTED_GROUP = "getSelectedGroup";

    private final static String UC_GET_ACTIVE_SESSIONS = "getActiveSessions";

    private final static String UC_RESTART_SERVER = "restartServer";

    private final static String UC_IGNORE_SERVER = "ignoreServer";

    private final static String UC_CHECK_SERVER = "checkServer";

    private final static String UC_RESTART_WORKER = "restartWorker";

    private final static String UC_IGNORE_WORKER = "ignoreWorker";

    private final static String UC_CHECK_WORKER = "checkWorker";

    private final static String UC_CREATE_APPLICATION = "selectApplication";

    /**
     * List of the methods name on the 'JadortConsoleInterface' class.
     */
    private final static String CI_CREATE_NEW_OPERATION = "createNewOperation";

    private final static String CI_GET_OPERATION_LIST = "getOperationsList";

    private final static String CI_DELETE_OPERATION = "deleteOperation";

    private final static String CI_LOAD_TOPOLOGY = "loadTopology";

    private final static String CI_GET_GROUPS = "getGroups";

    private final static String CI_GET_VM_IMAGES = "getVMImages";

    private final static String CI_SELECT_GROUP = "selectGroup";

    private final static String CI_SELECT_OPERATION_TYPE = "selectOperationType";

    private final static String CI_SELECT_VM_IMAGE = "selectVMImage";

    private final static String CI_SELECT_VM_IMAGE_FOR_SERVER = "selectVMImage";

    private final static String CI_SELECT_SERVERS = "selectServers";

    private final static String CI_GET_CURRENT_STEP = "getCurrentStep";

    private final static String CI_CAN_GO_NEXT = "canGoToNextStep";

    private final static String CI_NEXT = "next";

    private final static String CI_CAN_GO_PREVIOUS = "canGoToPreviousStep";

    private final static String CI_PREVIOUS = "previous";

    private final static String CI_GET_SERVER_PROGRESS_LIST = "getServerProgressList";

    private final static String CI_GET_WORKER_PROGRESS_LIST = "getWorkerProgressList";

    private final static String CI_GET_SELECTED_GROUP = "getSelectedGroup";

    private final static String CI_GET_ACTIVE_SESSIONS = "getActiveSessions";

    private final static String CI_RESTART_SERVER = "restartServer";

    private final static String CI_IGNORE_SERVER = "ignoreServer";

    private final static String CI_CHECK_SERVER = "checkServer";

    private final static String CI_RESTART_WORKER = "restartWorker";

    private final static String CI_IGNORE_WORKER = "ignoreWorker";

    private final static String CI_CHECK_WORKER = "checkWorker";

    private final static String CI_CREATE_APPLICATION = "selectApplication";

    /**
     * List of all the methods to call on JadortConsoleInterface with the
     * arguments type
     */
    private static Map<String, Class<?>[]> methods;
    static {
        JadortConsole.methods = new HashMap<String, Class<?>[]>();
        JadortConsole.methods.put(JadortConsole.CI_CREATE_NEW_OPERATION, new Class[] {String.class});
        JadortConsole.methods.put(JadortConsole.CI_GET_OPERATION_LIST, new Class[] {});
        JadortConsole.methods.put(JadortConsole.CI_DELETE_OPERATION, new Class[] {OperationStateBean.class});
        JadortConsole.methods.put(JadortConsole.CI_LOAD_TOPOLOGY, new Class[] {File.class});
        JadortConsole.methods.put(JadortConsole.CI_GET_GROUPS, new Class[] {});
        JadortConsole.methods.put(JadortConsole.CI_GET_VM_IMAGES, new Class[] {});
        JadortConsole.methods.put(JadortConsole.CI_SELECT_GROUP, new Class[] {GroupBean.class});
        JadortConsole.methods.put(JadortConsole.CI_SELECT_OPERATION_TYPE, new Class[] {IJadortService.OperationType.class});
        JadortConsole.methods.put(JadortConsole.CI_SELECT_VM_IMAGE, new Class[] {VMImageBean.class});
        JadortConsole.methods.put(JadortConsole.CI_SELECT_VM_IMAGE_FOR_SERVER,
            new Class[] {VMImageBean.class, ServerBean.class});
        JadortConsole.methods.put(JadortConsole.CI_SELECT_SERVERS, new Class[] {List.class});
        JadortConsole.methods.put(JadortConsole.CI_GET_CURRENT_STEP, new Class[] {});
        JadortConsole.methods.put(JadortConsole.CI_CAN_GO_NEXT, new Class[] {});
        JadortConsole.methods.put(JadortConsole.CI_NEXT, new Class[] {});
        JadortConsole.methods.put(JadortConsole.CI_CAN_GO_PREVIOUS, new Class[] {});
        JadortConsole.methods.put(JadortConsole.CI_PREVIOUS, new Class[] {});
        JadortConsole.methods.put(JadortConsole.CI_GET_SERVER_PROGRESS_LIST, new Class[] {});
        JadortConsole.methods.put(JadortConsole.CI_GET_WORKER_PROGRESS_LIST, new Class[] {});
        JadortConsole.methods.put(JadortConsole.CI_GET_SELECTED_GROUP, new Class[] {});
        JadortConsole.methods.put(JadortConsole.CI_GET_ACTIVE_SESSIONS, new Class[] {});
        JadortConsole.methods.put(JadortConsole.CI_RESTART_SERVER, new Class[] {ServerBean.class});
        JadortConsole.methods.put(JadortConsole.CI_IGNORE_SERVER, new Class[] {ServerBean.class});
        JadortConsole.methods.put(JadortConsole.CI_CHECK_SERVER, new Class[] {ServerBean.class});
        JadortConsole.methods.put(JadortConsole.CI_RESTART_WORKER, new Class[] {WorkerBean.class});
        JadortConsole.methods.put(JadortConsole.CI_IGNORE_WORKER, new Class[] {WorkerBean.class});
        JadortConsole.methods.put(JadortConsole.CI_CHECK_WORKER, new Class[] {WorkerBean.class});
        JadortConsole.methods.put(JadortConsole.CI_CREATE_APPLICATION, new Class[] {URL.class});
    }

    /**
     * List of the command on the command line (user command) with associated
     * method(s) to call on JadortConsoleInterface
     */
    private static Map<String, Method> commands;
    static {
        JadortConsole.commands = new HashMap<String, Method>();
        try {
            String key = JadortConsole.CI_CREATE_NEW_OPERATION;
            JadortConsole.commands.put(JadortConsole.UC_CREATE_NEW_OPERATION, JadortCommand.class.getMethod(key,
                JadortConsole.methods.get(key)));

            key = JadortConsole.CI_GET_OPERATION_LIST;
            JadortConsole.commands.put(JadortConsole.UC_GET_OPERATION_LIST, JadortCommand.class.getMethod(key));

            key = JadortConsole.CI_DELETE_OPERATION;
            JadortConsole.commands.put(JadortConsole.UC_DELETE_OPERATION, JadortCommand.class.getMethod(key,
                JadortConsole.methods.get(key)));

            key = JadortConsole.CI_LOAD_TOPOLOGY;
            JadortConsole.commands.put(JadortConsole.UC_LOAD_TOPOLOGY, JadortCommand.class.getMethod(key, JadortConsole.methods
                .get(key)));

            key = JadortConsole.CI_GET_GROUPS;
            JadortConsole.commands.put(JadortConsole.UC_GET_GROUPS, JadortCommand.class.getMethod(key));

            key = JadortConsole.CI_GET_VM_IMAGES;
            JadortConsole.commands.put(JadortConsole.UC_GET_VM_IMAGES, JadortCommand.class.getMethod(key));

            key = JadortConsole.CI_SELECT_GROUP;
            JadortConsole.commands.put(JadortConsole.UC_SELECT_GROUP, JadortCommand.class.getMethod(key, JadortConsole.methods
                .get(key)));

            key = JadortConsole.CI_SELECT_OPERATION_TYPE;
            JadortConsole.commands.put(JadortConsole.UC_SELECT_OPERATION_TYPE, JadortCommand.class.getMethod(key,
                JadortConsole.methods.get(key)));

            key = JadortConsole.CI_SELECT_VM_IMAGE;
            JadortConsole.commands.put(JadortConsole.UC_SELECT_VM_IMAGE, JadortCommand.class.getMethod(key,
                JadortConsole.methods.get(key)));

            key = JadortConsole.CI_SELECT_VM_IMAGE_FOR_SERVER;
            JadortConsole.commands.put(JadortConsole.UC_SELECT_VM_IMAGE_FOR_SERVER, JadortCommand.class.getMethod(key,
                JadortConsole.methods.get(key)));

            key = JadortConsole.CI_SELECT_SERVERS;
            JadortConsole.commands.put(JadortConsole.UC_SELECT_SERVERS, JadortCommand.class.getMethod(key,
                JadortConsole.methods.get(key)));

            key = JadortConsole.CI_GET_SELECTED_GROUP;
            JadortConsole.commands.put(JadortConsole.UC_GET_SELECTED_GROUP, JadortCommand.class.getMethod(key));

            key = JadortConsole.CI_GET_ACTIVE_SESSIONS;
            JadortConsole.commands.put(JadortConsole.UC_GET_ACTIVE_SESSIONS, JadortCommand.class.getMethod(key));

            key = JadortConsole.CI_CREATE_APPLICATION;
            JadortConsole.commands.put(JadortConsole.UC_CREATE_APPLICATION, JadortCommand.class.getMethod(key,
                JadortConsole.methods.get(key)));

            key = JadortConsole.CI_GET_CURRENT_STEP;
            JadortConsole.commands.put(JadortConsole.UC_GET_CURRENT_STEP, JadortCommand.class.getMethod(key));

            key = JadortConsole.CI_CAN_GO_NEXT;
            JadortConsole.commands.put(JadortConsole.UC_CAN_GO_NEXT, JadortCommand.class.getMethod(key));

            key = JadortConsole.CI_NEXT;
            JadortConsole.commands.put(JadortConsole.UC_NEXT, JadortCommand.class.getMethod(key));

            key = JadortConsole.CI_CAN_GO_PREVIOUS;
            JadortConsole.commands.put(JadortConsole.UC_CAN_GO_PREVIOUS, JadortCommand.class.getMethod(key));

            key = JadortConsole.CI_PREVIOUS;
            JadortConsole.commands.put(JadortConsole.UC_PREVIOUS, JadortCommand.class.getMethod(key));

            key = JadortConsole.CI_GET_SERVER_PROGRESS_LIST;
            JadortConsole.commands.put(JadortConsole.UC_GET_SERVER_PROGRESS_LIST, JadortCommand.class.getMethod(key));

            key = JadortConsole.CI_GET_WORKER_PROGRESS_LIST;
            JadortConsole.commands.put(JadortConsole.UC_GET_WORKER_PROGRESS_LIST, JadortCommand.class.getMethod(key));

            key = JadortConsole.CI_RESTART_SERVER;
            JadortConsole.commands.put(JadortConsole.UC_RESTART_SERVER, JadortCommand.class.getMethod(key,
                JadortConsole.methods.get(key)));

            key = JadortConsole.CI_RESTART_WORKER;
            JadortConsole.commands.put(JadortConsole.UC_RESTART_WORKER, JadortCommand.class.getMethod(key,
                JadortConsole.methods.get(key)));

            key = JadortConsole.CI_IGNORE_SERVER;
            JadortConsole.commands.put(JadortConsole.UC_IGNORE_SERVER, JadortCommand.class.getMethod(key, JadortConsole.methods
                .get(key)));

            key = JadortConsole.CI_IGNORE_WORKER;
            JadortConsole.commands.put(JadortConsole.UC_IGNORE_WORKER, JadortCommand.class.getMethod(key, JadortConsole.methods
                .get(key)));

            key = JadortConsole.CI_CHECK_SERVER;
            JadortConsole.commands.put(JadortConsole.UC_CHECK_SERVER, JadortCommand.class.getMethod(key, JadortConsole.methods
                .get(key)));

            key = JadortConsole.CI_CHECK_WORKER;
            JadortConsole.commands.put(JadortConsole.UC_CHECK_WORKER, JadortCommand.class.getMethod(key, JadortConsole.methods
                .get(key)));

        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * List of the methods who need operation id as argument
     */
    private static Map<Method, Boolean> methodsNeedOperationNumber;
    static {
        JadortConsole.methodsNeedOperationNumber = new HashMap<Method, Boolean>();
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_LOAD_TOPOLOGY), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_GET_CURRENT_STEP), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_CAN_GO_NEXT), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_NEXT), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_CAN_GO_PREVIOUS), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_PREVIOUS), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_GET_GROUPS), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_GET_VM_IMAGES), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_SELECT_VM_IMAGE), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_SELECT_VM_IMAGE_FOR_SERVER),
            true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_SELECT_GROUP), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_SELECT_OPERATION_TYPE), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_SELECT_SERVERS), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_GET_SERVER_PROGRESS_LIST),
            true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_GET_WORKER_PROGRESS_LIST),
            true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_GET_SELECTED_GROUP), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_GET_ACTIVE_SESSIONS), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_RESTART_SERVER), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_IGNORE_SERVER), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_RESTART_WORKER), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_IGNORE_WORKER), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_CHECK_SERVER), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_CHECK_WORKER), true);
        JadortConsole.methodsNeedOperationNumber.put(JadortConsole.commands.get(JadortConsole.CI_CREATE_APPLICATION), true);
    }

    /**
     * Associate method name on the JaDOrT engine with method name to handle
     * output on the client
     */
    public static Map<String, Method> output;

    static {
        try {
            JadortConsole.output = new HashMap<String, Method>();
            JadortConsole.output.put("getCurrentStep", JadortConsole.class.getMethod("handleStep",
                OperationStateBean.Step.class));
            JadortConsole.output.put("canGoToNextStep", JadortConsole.class.getMethod("handleBoolean", Boolean.class));
            JadortConsole.output.put("next", null);
            JadortConsole.output.put("canGoToPreviousStep", JadortConsole.class.getMethod("handleBoolean", Boolean.class));
            JadortConsole.output.put("previous", null);
            JadortConsole.output.put("loadTopology", null);
            JadortConsole.output.put("getGroups", JadortConsole.class.getMethod("handleGroupsList", List.class));
            JadortConsole.output.put("getVMImages", JadortConsole.class.getMethod("handleVMImagesList", List.class));
            JadortConsole.output.put("selectServers", null);
            JadortConsole.output.put("getServerProgressList", JadortConsole.class.getMethod("handleServerProgressList",
                List.class));
            JadortConsole.output.put("getWorkerProgressList", JadortConsole.class.getMethod("handleWorkerProgressList",
                List.class));
            JadortConsole.output.put("getSelectedGroup", JadortConsole.class.getMethod("handleGroup", GroupBean.class));
            JadortConsole.output.put("getActiveSessions", JadortConsole.class.getMethod("handleInteger", Integer.class));
            JadortConsole.output.put("restart", null);
            JadortConsole.output.put("ignoreServer", null);
            JadortConsole.output.put("checkServer", JadortConsole.class.getMethod("handleBoolean", Boolean.class));
            JadortConsole.output.put("selectApplication", null);
            JadortConsole.output.put("getOperationsList", JadortConsole.class.getMethod("handleOperationsList", List.class));
            JadortConsole.output.put("selectOperation", null);
            JadortConsole.output.put("createNewOperation", JadortConsole.class.getMethod("handleCreateOperation",
                OperationStateBean.class));
            JadortConsole.output.put("deleteOperation", null);
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * The main
     * 
     * @param args command line arguments
     */
    public static void main(final String[] args) {
        try {
            IJadortService iJadort = JadortConsole.initEJBConnection();
            JadortCommand JadortConsoleInterface = new JadortCommand(iJadort);

            CommandArgs commandArgs = JadortConsole.parseForCmd(args, JadortConsoleInterface);
            Method command = commandArgs.getCommand();
            List<Object> arguments = JadortConsole.parseForArgs(commandArgs, JadortConsoleInterface);

            Object resultat = JadortConsole.callRemoteMehod(arguments, command, JadortConsoleInterface);
            Method handler = JadortConsole.output.get(command.getName());
            if (handler != null) {
                Object res = handler.invoke(null, resultat);

                JadortConsole.returnValueToConsole(res);
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();

            System.exit(-1);
        }
    }

    /**
     * Manage the return value to the console
     * 
     * @param res Object returned by the method who handle the display of JaDOrT
     *        service return
     */
    private static void returnValueToConsole(final Object res) {
        int ret = 0;

        if (res != null) {
            if (res instanceof Integer) {
                ret = (Integer) res;
            } else if (res instanceof Boolean) {
                {
                    Boolean bRes = (Boolean) res;
                    if (bRes) {
                        ret = 1;
                    } else {
                        ret = 0;
                    }
                }
            } else if (res instanceof OperationStateBean) {
                ret = ((OperationStateBean) res).getId();
            }
        }

        System.exit(ret);
    }

    /**
     * Invoke the appropriate method on the Command interface
     * 
     * @param arguments arguments list to pass to the method
     * @param cmd the method to call
     * @param iCommand the instance of CommandInterface
     * @return The object returned by the invoked method
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    private static Object callRemoteMehod(final List<Object> arguments, final Method cmd, final JadortCommand iCommand)
        throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {

        return cmd.invoke(iCommand, arguments.toArray());
    }

    /**
     * Init the connection with the JaDOrT service
     * 
     * @return A interface of JaDOrT service ready to be used
     * @throws NamingException
     */
    private static IJadortService initEJBConnection() throws NamingException {
        Hashtable<String, Object> env = new Hashtable<String, Object>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, SmartContextFactory.class.getName());
        Context context = new InitialContext(env);
        return (IJadortService) context.lookup(IJadortService.EJB_JNDI_NAME);
    }

    /**
     * Select the operation w'e want to work with on the JaDOrT service
     * 
     * @param opID Id of the operation to select
     * @param JadortConsoleInterface a instance of CommandInterface
     * @throws Exception
     */
    private static void setSelectedOperation(final Integer opID, final JadortCommand JadortConsoleInterface) throws Exception {
        OperationStateBean op = JadortConsole.getOperationByID(opID, JadortConsoleInterface);
        if (op != null) {
            JadortConsoleInterface.selectOperation(op);
        } else {
            JadortConsole.usage("Unable to find the operation with " + opID + " as id");
        }
    }

    /**
     * Parse the command line for 'command' and operation id. <br />
     * Return a object with the extracted command and the argument in string
     * format. <br
     * />
     * Select the operation on JaDOrT service if needed
     * 
     * @param args the command line arguments
     * @param JadortConsoleInterface a instance of CommandInterface
     * @return A object who contain the command and the argument in String
     *         format
     */
    private static CommandArgs parseForCmd(final String[] args, final JadortCommand JadortConsoleInterface) throws Exception {
        CommandArgs ret = new CommandArgs();

        Method command = null;

        int nbNonArgs = 1;

        /* ------------------------- */
        /* Extract command */
        if (args.length < nbNonArgs) {
            JadortConsole.usage("No command provided!");
        }

        String userCommand = args[0];
        command = JadortConsole.commands.get(userCommand);

        if (command == null) {
            JadortConsole.usage("Unknown command.");
        }

        ret.setCommand(command);
        /* ------------------------- */

        /* ------------------------- */
        /* Manage operation id */
        if (JadortConsole.methodsNeedOperationNumber.get(command) != null) {
            nbNonArgs++;
            if (args.length < nbNonArgs) {
                JadortConsole.usage("No operation Id provided. This field is mandatory.");
            }

            /* Select operation to work with on the server */
            try {
                Integer operationId = new Integer(args[1]);
                JadortConsole.setSelectedOperation(operationId, JadortConsoleInterface);
            } catch (NumberFormatException e) {
                JadortConsole.usage("Unable to parse " + args[1] + " as operation Id. It must be a Integer");
            }
        }
        /* ------------------------- */

        /* ------------------------- */
        /* Set arguments */
        List<String> argsTmp = new ArrayList<String>();
        for (int i = nbNonArgs; i < args.length; i++) {
            argsTmp.add(args[i]);
        }

        ret.setArgs(argsTmp);
        /* ------------------------- */

        return ret;
    }

    /**
     * Parse the arguments in String format, and return a array with the
     * arguments to use with JaDOrT service. <br />
     * It cast String into the real type of JaDOrT service arguments.
     * 
     * @param cmdArgs A object who contains command and argument in String
     *        format
     * @param JadortConsoleInterface a instance of CommandInterface
     * @return An array of object who represents the arguments to use with
     *         JaDOrT service.
     */
    private static List<Object> parseForArgs(final CommandArgs cmdArgs, final JadortCommand JadortConsoleInterface)
        throws Exception {
        List<Object> ret = new ArrayList<Object>();

        Class<?>[] signature = JadortConsole.methods.get(cmdArgs.getCommand().getName());

        if (signature.length != cmdArgs.getArgs().size()
            && !cmdArgs.getCommand().getName().equals(JadortConsole.UC_SELECT_SERVERS)) {
            JadortConsole.usage("To much arguments on the command line");
        }

        try {
            if (signature.length > 0) {
                for (int i = 0; i < signature.length; i++) {
                    if (signature[i] != String.class) {
                        if (signature[i] == OperationStateBean.class) {
                            Integer idOp = new Integer(cmdArgs.getArgs().get(i));
                            OperationStateBean op = JadortConsole.getOperationByID(idOp, JadortConsoleInterface);
                            if (op != null) {
                                ret.add(op);
                            } else {
                                JadortConsole.usage("Unable to find the operation with " + idOp + " as id");
                            }
                        } else if (signature[i] == URL.class) {
                            URL url;
                            try {
                                url = new URL(cmdArgs.getArgs().get(i));
                            } catch (MalformedURLException e) {
                                // urlOrFile is not a URL, it is a file
                                //
                                // Use File.oURI().toURL() and not File.toURL()
                                // since
                                // File.toURL() doesn't properly escape the URL.
                                url = new File(cmdArgs.getArgs().get(i)).toURI().toURL();
                            }
                            ret.add(url);
                        } else if (signature[i] == File.class) {
                            ret.add(new File(cmdArgs.getArgs().get(i)));
                        } else if (signature[i] == ServerBean.class) {
                            ServerBean server = JadortConsole.getServerByName(cmdArgs.getArgs().get(i), JadortConsoleInterface);
                            if (server != null) {
                                ret.add(server);
                            } else {
                                JadortConsole.usage("Unable to find the server with " + cmdArgs.getArgs().get(i) + " as name");
                            }
                        } else if (signature[i] == WorkerBean.class) {
                            WorkerBean worker = JadortConsole.getWorkerByName(cmdArgs.getArgs().get(i), JadortConsoleInterface);
                            if (worker != null) {
                                ret.add(worker);
                            } else {
                                JadortConsole.usage("Unable to find the worker with " + cmdArgs.getArgs().get(i) + " as name");
                            }
                        } else if (signature[i] == GroupBean.class) {
                            GroupBean group = JadortConsole.getGroupByName(cmdArgs.getArgs().get(i), JadortConsoleInterface);
                            if (group != null) {
                                ret.add(group);
                            } else {
                                JadortConsole.usage("Unable to find the group with " + cmdArgs.getArgs().get(i) + " as name");
                            }
                        } else if (signature[i] == VMImageBean.class) {
                            VMImageBean vmImage = JadortConsole.getVMImageByName(cmdArgs.getArgs().get(i),
                                JadortConsoleInterface);
                            if (vmImage != null) {
                                ret.add(vmImage);
                            } else {
                                JadortConsole
                                    .usage("Unable to find the VM image with " + cmdArgs.getArgs().get(i) + " as name");
                            }
                        } else if (signature[i] == List.class) {
                            if (cmdArgs.getCommand().getName().equals(JadortConsole.UC_SELECT_SERVERS)) {
                                List<ServerBean> servers = new ArrayList<ServerBean>();
                                for (; i < cmdArgs.getArgs().size(); i++) {
                                    ServerBean server = JadortConsole.getServerByName(cmdArgs.getArgs().get(i),
                                        JadortConsoleInterface);
                                    servers.add(server);
                                }
                                ret.add(servers);
                            }
                        } else if (signature[i] == IJadortService.OperationType.class) {
                            IJadortService.OperationType opType = IJadortService.OperationType
                                .valueOf(cmdArgs.getArgs().get(i));
                            ret.add(opType);
                        } else {
                            throw new IllegalArgumentException("Devolopment error : type " + signature[i] + " unparsed");
                        }
                    } else {
                        ret.add(cmdArgs.getArgs().get(i));
                    }
                }
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            JadortConsole.usage("Not enough arguments provided on the command line");
        }

        return ret;
    }

    /**
     * Get the operation list
     * 
     * @param JadortConsoleInterface a instance of CommandInterface
     * @return List of operation on the JaDOrT service
     * @throws Exception
     */
    private static List<OperationStateBean> getOperations(final JadortCommand JadortConsoleInterface) throws Exception {
        return JadortConsoleInterface.getOperationsList();
    }

    /**
     * Get the servers list.
     * 
     * @param JadortConsoleInterface a instance of CommandInterface
     * @return The servers list
     * @throws Exception
     */
    private static List<ServerBean> getServers(final JadortCommand JadortConsoleInterface) throws Exception {
        return JadortConsoleInterface.getSelectedGroup().getServers();
    }

    /**
     * Get the servers list.
     * 
     * @param JadortConsoleInterface a instance of CommandInterface
     * @return The servers list
     * @throws Exception
     */
    private static List<WorkerBean> getWorkers(final JadortCommand JadortConsoleInterface) throws Exception {
        return JadortConsoleInterface.getSelectedGroup().getWorkers();
    }

    /**
     * Get a operation by its id
     * 
     * @param id The id of the operation to get
     * @param JadortConsoleInterface a instance of CmmandInterface
     * @return The operation with the id or null if doesn't exist
     * @throws Exception
     */
    private static OperationStateBean getOperationByID(final Integer id, final JadortCommand JadortConsoleInterface)
        throws Exception {
        List<OperationStateBean> operations = JadortConsole.getOperations(JadortConsoleInterface);

        if (operations != null) {
            for (OperationStateBean op : operations) {
                if (op.getId().compareTo(id) == 0) {
                    return op;
                }
            }
            return null;
        } else {
            return null;
        }
    }

    /**
     * Get a group by is name
     * 
     * @param name The name of the group you are looking for.
     * @param JadortConsoleInterface a instance of CommandInterface
     * @return The group with the good name or null if it doesn't exist
     * @throws Exception
     */
    public static GroupBean getGroupByName(final String name, final JadortCommand JadortConsoleInterface) throws Exception {
        List<GroupBean> groups = JadortConsole.getGroups(JadortConsoleInterface);
        for (GroupBean g : groups) {
            if (g.getName().compareTo(name) == 0) {
                return g;
            }
        }

        return null;
    }

    /**
     * Get a VM Image by its name
     * 
     * @param name The name of the VM Image you are looking for.
     * @param JadortConsoleInterface a instance of CommandInterface
     * @return The VMImageBean with the good UUID or null if it doesn't exist
     * @throws Exception
     */
    public static VMImageBean getVMImageByName(final String name, final JadortCommand JadortConsoleInterface) throws Exception {
        List<VMImageBean> vmImages = JadortConsole.getVMImages(JadortConsoleInterface);
        for (VMImageBean vm : vmImages) {
            if (vm.getName().compareTo(name) == 0) {
                return vm;
            }
        }

        return null;
    }

    /**
     * Get a server by its name
     * 
     * @param name The name of the server you are looking for.
     * @param JadortConsoleInterface a instance of CommandInterface
     * @return The server with the good name or null if it doesn't exist
     * @throws Exception
     */
    public static ServerBean getServerByName(final String name, final JadortCommand JadortConsoleInterface) throws Exception {
        List<ServerBean> servers = JadortConsole.getServers(JadortConsoleInterface);
        for (ServerBean s : servers) {
            if (s.getName().compareTo(name) == 0) {
                return s;
            }
        }

        return null;
    }

    /**
     * Get a worker by its name
     * 
     * @param name The name of the worker you are looking for.
     * @param JadortConsoleInterface a instance of CommandInterface
     * @return The worker with the good name or null if it doesn't exist
     * @throws Exception
     */
    public static WorkerBean getWorkerByName(final String name, final JadortCommand JadortConsoleInterface) throws Exception {
        List<WorkerBean> workers = JadortConsole.getWorkers(JadortConsoleInterface);
        for (WorkerBean w : workers) {
            if (w.getName().compareTo(name) == 0) {
                return w;
            }
        }

        return null;

    }

    /**
     * Return the list of the groups.
     * 
     * @param JadortConsoleInterface a instance of CommandInterface
     * @return list of the groups
     * @throws Exception
     */
    public static List<GroupBean> getGroups(final JadortCommand JadortConsoleInterface) throws Exception {
        return JadortConsoleInterface.getGroups();
    }

    /**
     * Return the list of the VM Images.
     * 
     * @param JadortConsoleInterface a instance of CommandInterface
     * @return list of the VM images
     * @throws Exception
     */
    public static List<VMImageBean> getVMImages(final JadortCommand JadortConsoleInterface) throws Exception {
        return JadortConsoleInterface.getVMImages();
    }

    /**
     * Represents a command and a list of String as arguments.
     */
    private static class CommandArgs {

        /**
         * The command
         */
        private Method command;

        /**
         * List of arguments
         */
        private List<String> args;

        /**
         * Default constructor
         */
        public CommandArgs() {
            this.args = new ArrayList<String>();
        }

        /**
         * Return the command
         * 
         * @return the command
         */
        public Method getCommand() {
            return this.command;
        }

        /**
         * Set the command
         * 
         * @param command the command to set
         */
        public void setCommand(final Method command) {
            this.command = command;
        }

        /**
         * Get the arguments
         * 
         * @return the arguments
         */
        public List<String> getArgs() {
            return this.args;
        }

        /**
         * Set the arguments
         * 
         * @param args The arguments list to set
         */
        public void setArgs(final List<String> args) {
            this.args = args;
        }
    }

    /**
     * Manage display of a created operation.
     * 
     * @param op The operation to display
     */
    public static OperationStateBean handleCreateOperation(final OperationStateBean op) {
        System.out.println("New operation created with id = " + op.getId());

        return op;
    }

    /**
     * Display a list of operation
     * 
     * @param operations List of operations
     */
    public static void handleOperationsList(final List<OperationStateBean> operations) {
        System.out.println("\nList of existing opeations : ");

        System.out.println("\tID \t name \t date");

        for (OperationStateBean op : operations) {
            System.out.print("\t " + op.getId());
            System.out.print("\t " + op.getName());
            System.out.println("\t " + op.getDate());
        }
    }

    /**
     * Manage display of a groups list
     * 
     * @param groups The group list to display
     */
    public static void handleGroupsList(final List<GroupBean> groups) {
        System.out.println("Group list : ");
        System.out.println("--------------------------------");

        for (GroupBean g : groups) {
            JadortConsole.printGroup(g);
            System.out.println("--------------------------------\n");
        }
    }

    /**
     * Display the selected group
     * 
     * @param group The selected group.
     */
    public static void handleGroup(final GroupBean group) {
        System.out.println("\nSelected group : ");
        JadortConsole.printGroup(group);
    }

    /**
     * Manage display of a VM Image list
     * 
     * @param vmImages The group list to display
     */
    public static void handleVMImagesList(final List<VMImageBean> vmImages) {
        System.out.println("VM Image list : ");
        System.out.println("--------------------------------");

        for (VMImageBean vmImage : vmImages) {
            JadortConsole.printVMImage(vmImage);
            System.out.println("--------------------------------\n");
        }
    }

    /**
     * Display the selected VMImage
     * 
     * @param group The selected VM Image.
     */
    public static void handleVMImage(final VMImageBean vmImage) {
        System.out.println("\nSelected VM Image : ");
        JadortConsole.printVMImage(vmImage);
    }

    /**
     * Display a group
     * 
     * @param group The group to display
     */
    private static void printGroup(final GroupBean group) {
        if (group == null) {
            System.out.println("No group");
        } else {
            System.out.println("ID : " + group.getId());
            System.out.println("Name : " + group.getName());
            System.out.println("\n");
            System.out.println("Servers on this group :");
            System.out.println("\tID \tName \tCapacity");
            for (ServerBean s : group.getServers()) {
                System.out.print("\t" + s.getId());
                System.out.print("\t" + s.getName());
                System.out.println("\t" + s.getCapacity());
            }

            System.out.println("\n");
            System.out.println("Applications on this group :");
            System.out.println("\tID \tName \tVersion \tState \tPolicy");
            for (ApplicationBean a : group.getApplications()) {
                System.out.print("\t" + a.getId());
                System.out.print("\t" + a.getName());
                System.out.print("\t" + a.getVersion());
                System.out.print("\t" + a.getState());
                System.out.println("\t" + a.getPolicy());
            }
        }
    }

    /**
     * Display a VM Image
     * 
     * @param vmImage The VM Image to display
     */
    private static void printVMImage(final VMImageBean vmImage) {
        if (vmImage == null) {
            System.out.println("No VM Image");
        } else {
            System.out.println("ID : " + vmImage.getId());
            System.out.println("UUID : " + vmImage.getUuid());
            System.out.println("Name : " + vmImage.getName());
        }
    }

    /**
     * display a list of serverProgress
     * 
     * @param serverProgresss The list of serverProgress to display.
     */
    public static void handleServerProgressList(final List<ServerProgressBean> serverProgresss) {
        System.out.println("\nList of serverProgresss : ");
        System.out.println("--------------------------------");
        System.out.println("\tID \t server name \t state \t progress \t log \t old application \t new application");

        for (ServerProgressBean dep : serverProgresss) {
            System.out.print("\t " + dep.getId());
            System.out.print("\t " + dep.getServer().getName());
            System.out.print("\t " + dep.getState());
            System.out.print("\t " + dep.getProgress());
        }
    }

    /**
     * display a list of workerProgress
     * 
     * @param workerProgresss The list of serverProgress to display.
     */
    public static void handleWorkerProgressList(final List<WorkerProgressBean> workerProgresss) {
        System.out.println("\nList of workerProgresss : ");
        System.out.println("--------------------------------");

        System.out.println("\tID \t worker name \t state \t progress \t log");

        for (WorkerProgressBean dep : workerProgresss) {
            System.out.print("\t " + dep.getId());
            System.out.print("\t " + dep.getWorker().getName());
            System.out.print("\t " + dep.getState());
            System.out.print("\t " + dep.getProgress());
        }
    }

    /**
     * Display a boolean
     * 
     * @param bool The boolean to display
     * @return 0 if false, 1 if true
     */
    public static Integer handleBoolean(final Boolean bool) {
        System.out.println("Value : " + bool);

        if (bool) {
            return 1;
        } else {
            return 0;
        }
    }

    /**
     * Display an integer
     * 
     * @param integer The integer to display
     * @return integer
     */
    public static Integer handleInteger(final Integer integer) {
        System.out.println("Value : " + integer);

        return integer;
    }

    /**
     * Display a step of operation
     * 
     * @param step The step to display
     */
    public static void handleStep(final OperationStateBean.Step step) {
        System.out.println("The current step is : " + step);
    }

    /**
     * Print the usage of the program
     * 
     * @param info Additional information to print
     */
    private static void usage(final String info) {
        StringBuilder message = new StringBuilder();
        message.append("Invalid syntax\n");
        message.append(info + "\n");
        message.append("Usage : cmd [operationId] [args,...]\n");
        message.append("List of commands : \n");
        message.append("\t- " + JadortConsole.UC_CREATE_NEW_OPERATION + " {new operation name}" + "\n");
        message.append("\t- " + JadortConsole.UC_GET_OPERATION_LIST + "\n");
        message.append("\t- " + JadortConsole.UC_DELETE_OPERATION + " {operation id}" + "\n");
        message.append("\t- " + JadortConsole.UC_LOAD_TOPOLOGY + " {operation id} {file path}" + "\n");
        message.append("\t- " + JadortConsole.UC_GET_GROUPS + " {operation id}" + "\n");
        message.append("\t- " + JadortConsole.UC_GET_VM_IMAGES + " {operation id}" + "\n");
        message.append("\t- " + JadortConsole.UC_SELECT_GROUP + " {operation id} {group name}" + "\n");
        message.append("\t- " + JadortConsole.UC_SELECT_OPERATION_TYPE + " {operation id} {operation type}" + "\n");
        message.append("\t- " + JadortConsole.UC_SELECT_VM_IMAGE + " {operation id} {vm image name} " + "\n");
        message.append("\t- " + JadortConsole.UC_SELECT_VM_IMAGE_FOR_SERVER + " {operation id} {vm image name} {server name} "
            + "\n");
        message.append("\t- " + JadortConsole.UC_SELECT_SERVERS + " {operation id} {server1 name} {server2 name} ..." + "\n");
        message.append("\t- " + JadortConsole.UC_GET_CURRENT_STEP + " {operation id}" + "\n");
        message.append("\t- " + JadortConsole.UC_CAN_GO_NEXT + " {operation id}" + "\n");
        message.append("\t- " + JadortConsole.UC_NEXT + " {operation id}" + "\n");
        message.append("\t- " + JadortConsole.UC_CAN_GO_PREVIOUS + " {operation id}" + "\n");
        message.append("\t- " + JadortConsole.UC_PREVIOUS + " {operation id}" + "\n");
        message.append("\t- " + JadortConsole.UC_GET_SERVER_PROGRESS_LIST + " {operation id}" + "\n");
        message.append("\t- " + JadortConsole.UC_GET_WORKER_PROGRESS_LIST + " {operation id}" + "\n");
        message.append("\t- " + JadortConsole.UC_GET_SELECTED_GROUP + " {operation id}" + "\n");
        message.append("\t- " + JadortConsole.UC_RESTART_SERVER + " {operation id} {server name}" + "\n");
        message.append("\t- " + JadortConsole.UC_IGNORE_SERVER + " {operation id} {server name}" + "\n");
        message.append("\t- " + JadortConsole.UC_CHECK_SERVER + " {operation id} {server name}" + "\n");
        message.append("\t- " + JadortConsole.UC_RESTART_WORKER + " {operation id} {worker name}" + "\n");
        message.append("\t- " + JadortConsole.UC_IGNORE_WORKER + " {operation id} {worker name}" + "\n");
        message.append("\t- " + JadortConsole.UC_CHECK_WORKER + " {operation id} {worker name}" + "\n");
        message.append("\t- " + JadortConsole.UC_CREATE_APPLICATION + " {operation id} {archive path}" + "\n");

        throw new IllegalArgumentException(message.toString());
    }

}
