calculadora.vista.VistaCLI.java Source code

Java tutorial

Introduction

Here is the source code for calculadora.vista.VistaCLI.java

Source

/*
 * Copyright 2013 Antonio Lpez Marn and Antonio Rodrigo Gea Lpez.
 * Calculadora CLI 2.0
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package calculadora.vista;

import calculadora.controlador.ControladorCLI;
import java.util.Scanner;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;

/**
 * Clase VistaCLI que maneja toda la interfaz visual linea de comandos mostrando
 * los mensajes pertinentes, inicio de la calculadora y carga de las opciones de
 * la linea de comandos.
 *
 * Se comunica con el controlador, y la mayoria de sus metodos son publicos para
 * su facil acceso.
 *
 * @author Antonio Lpez Marn
 * @author Antonio Rodrigo Gea Lpez
 * @version 2.0
 */
public class VistaCLI {

    /*
     * ControladorCLI estatico para poder poner el metodo
     * {@link VistaCLI#startCalculadora} estatico 
     * y poder iniciar la calculadora sin crear instancia.
     * 
     */
    private ControladorCLI controlador;
    //Scanner para escribir linea de comandos
    private Scanner sc;
    //Las opciones de la linea de comando
    private static Options opciones;
    //Contador de errores si se abre la linea de comandos
    private static int cont;

    /**
     * Constructor de la clase VistaCLI.
     *
     * Se inicializa el controlador para comunicarse con el.
     */
    public VistaCLI() {
        controlador = new ControladorCLI(this);

        //Cuando la vista se quiere comunicar con el controlador 
        //cargo las opciones para ser procesadas a continuacion.
        loadCommandLine();
    }

    /**
     * Metodo que inicia la calculadora.
     *
     * Es estatico para que la aplicacion pueda iniciar la vista de la
     * calculadora sin tener que crear un objeto, sino que el objeto de la vista
     * se inicializa a si mismo en este metodo.
     *
     * Lo llama la aplicacion y da la orden de comenzar.
     *
     * @see ControladorCLI#openCalculadora(java.lang.String[])
     * @param args los argumentos de entrada de la linea de comandos
     * @exception NumberFormatException Numeros no validos
     * @exception ArithmeticException Operador incorrecto
     * @exception IllegalArgumentException Argumentos incorrectos.
     */
    public void startCalculadora(String[] args) {
        //Llamo al controlador para que ma abra la calculadora.
        try {
            controlador.openCalculadora(args, opciones);
        } catch (NumberFormatException nfe) {
            mostrarError("Tipo de argumentos no validos.");
        } catch (ArithmeticException | IllegalArgumentException ex) {
            mostrarError(ex.getMessage());
        }
    }

    /**
     * Este metodo realiza la primera etapa de deficion de las opciones de la
     * interfaz de linea de comandos.
     *
     * @see Options
     * @see Options#addOptionGroup(org.apache.commons.cli.OptionGroup)
     */
    private void loadCommandLine() {
        opciones = new Options();

        //help
        opciones.addOption(new Option("h", "help", false, "Muestra este mensaje de ayuda."));

        //suma
        opciones.addOption(OptionBuilder.withArgName("num1> <num2").hasArgs(2)
                .withDescription("Calcula la suma dos numeros reales.").create("s"));
        //resta
        opciones.addOption(OptionBuilder.withArgName("num1> <num2").hasArgs(2)
                .withDescription("Calcula la resta dos numeros reales.").create("r"));
        //multiplicacion
        opciones.addOption(OptionBuilder.withArgName("num1> <num2").hasArgs(2)
                .withDescription("Calcula la multiplicacion dos numeros reales.").create("m"));
        //resto
        opciones.addOption(OptionBuilder.withArgName("num1> <num2").hasArgs(2)
                .withDescription("Calcula el resto de dos numeros reales.").create("re"));

        //division
        opciones.addOption(OptionBuilder.withArgName("dividendo> <divisor").hasArgs(2)
                .withDescription("Calcula la division de dos numeros reales.").create("d"));
        //potencia
        opciones.addOption(OptionBuilder.withArgName("base> <exp").hasArgs(2)
                .withDescription("Calcula la potencia " + " de base elevado a expontente.").create("p"));
        //raiz
        opciones.addOption(OptionBuilder.withArgName("radicando> <indice").hasArgs(2)
                .withDescription("Calcula la raiz enesima " + "de dos numeros, radicando e indice.").create("ra"));

        //Operaciones trigonometricas POSIX largo
        //seno
        opciones.addOption(OptionBuilder.withArgName("angulo").hasArgs().withLongOpt("seno")
                .withDescription("Calcula el seno de un angulo.").create());
        //coseno
        opciones.addOption(OptionBuilder.withArgName("angulo").hasArgs().withLongOpt("coseno")
                .withDescription("Calcula el coseno de un angulo.").create());
        //tangente
        opciones.addOption(OptionBuilder.withArgName("angulo").hasArgs().withLongOpt("tangente")
                .withDescription("Calcula la tangente de un angulo.").create());

        //Tablas de verdad POSIX largo
        //and
        opciones.addOption(OptionBuilder.withArgName("boolean> <boolean").hasArgs(2).withLongOpt("and")
                .withDescription("Calcula la tabla de verdad segun AND.").create());
        //or
        opciones.addOption(OptionBuilder.withArgName("boolean> <boolean").hasArgs(2).withLongOpt("or")
                .withDescription("Calcula la tabla de verdad segun OR.").create());
        //xor
        opciones.addOption(OptionBuilder.withArgName("boolean> <boolean").hasArgs(2).withLongOpt("xor")
                .withDescription("Calcula la tabla de verdad segun XOR.").create());
        //not
        opciones.addOption(OptionBuilder.withArgName("!boolean").hasArgs().withLongOpt("not")
                .withDescription("Calcula la tabla de verdad segun NOT.").create());

        //Conversiones con propiedad 
        //Fuera del grupo para poder poner la ayuda con este comando
        opciones.addOption(OptionBuilder.withArgName("property=value").hasArgs(3)
                .withDescription("Conversion entre binario, octal, decimal "
                        + "y hexadecimal, para mas informacion -h o " + "--help seguido de -Dconvert.")
                .withValueSeparator().create("D"));
    }

    /**
     * Este metodo se ejecuta si se decidio abrir la calculadora linea de
     * comandos, que le aade el comando de exit para poder salir de la
     * calculadora.
     *
     * @return las opciones con el exit aadido
     */
    public Options loadExitOption() {
        opciones.addOption(new Option(null, "exit", false, "Salir de la Calculadora linea de comandos."));
        return opciones;
    }

    /**
     * Instancia la clase Scanner cuando se quiere abrir un flujo de entrada
     * de teclado.
     * 
     * Y se inicializa el contador a 0, por si se equivoca el usuario mucho.
     */
    public void loadOutputTeclado() {
        sc = new Scanner(System.in);
        cont = 0; //Inicio el contador
    }

    /**
     * Muestra las lineas para poner los comandos si se decidio este modo de la
     * calculadora "abierto".
     *
     * Lo llama el controlador si hace decidio este modo.
     *
     * @see String#split(java.lang.String)
     * @return args nueva Linea de comandos.
     */
    public String[] mostrarLineaCalculadora() {
        System.out.print("Calculadora > ");
        return sc.nextLine().split(" +");
    }

    /**
     * Metodo de salida del programa que decide que mostrar, ayudas, resultado,
     * algun error, etc...
     *
     * @param resultado resultado numerico o bien ayudas etc...
     */
    public void salidaPrograma(String resultado) {
        //Si el resultado es mostrar la ayuda, la muestro
        if (resultado.equals("AYUDA")) {
            mostrarAyuda();
        } else if (resultado.equals("AYUDAPROPERTY")) {
            //Mensaje de ayuda de este comando
            ayudaConversion();
        } else if (resultado.equals("EXIT")) {
            //Le digo al controlador que debe de cerrar la calculadora
            controlador.setExit(true);
        } else if (resultado.length() == 0) {
            //Si no hay resultado, mostrar mensaje
            mostrarError("Expecifique algun comando de la Calculadora CLI.");
        } else { //Sino, es un resultado de una operacion
            mostrarResultado(resultado);
        }
    }

    /**
     * Muestra la ayuda de la linea de comandos.
     *
     */
    public void mostrarAyuda() {
        String headerandFooter = "Para mas informacion sobre la conversion poner "
                + "-h o --help seguido del comando -Dconvert.\n";
        new HelpFormatter().printHelp(90, "Opciones Calculadora: \n\n", headerandFooter, opciones,
                "\n" + headerandFooter);
    }

    /**
     * Mostrar un pequeo mensaje par aque sepan el comando de la ayuda y la
     * vean cuando quieran.
     *
     */
    private static String miniAyuda() {
        return "Escriba -h o --help para mostrar la ayuda";
    }

    /**
     * Ayuda del comando -D (conversion origen, destino).
     *
     * Muestra la ayuda.
     */
    public void ayudaConversion() {
        System.out
                .println("Comando -D <property=value>:\n\n " + "\t\tComando para conversion entre binario, octal, "
                        + "decimal y hexadecimal,\n\t\tse debe poner una propiedad "
                        + "seguida de su valor, que pueden ser varios. \n\n\t\t"
                        + "Posibles valores de las propiedades: \n\t\t\tbinario -> "
                        + "bin \n\t\t\toctal -> oct \n\t\t\tdecimal -> dec \n\t\t\t"
                        + "hexadecimal -> hex \n\n\t\tLa conversion se "
                        + "expecifica con las propiedades convert.source (origen)"
                        + "\n\t\ty convert.dest (destino) seguidas con su "
                        + "valor y el operando.\n\n\t\tEjemplos: \n\t\t\t"
                        + "-Dconvert.source=dec -Dconvert.dest=hex 5345 \n\t\t\t"
                        + "-Dconvert.source=hex -Dconvert.dest=oct AA \n\t\t\t"
                        + "-Dconvert.source=bin -Dconvert.dest=dec 101010111");
    }

    /**
     * Muestra el resultado de las operaciones.
     *
     * @param resultado el resultado que se debe mostrar.
     */
    public void mostrarResultado(String resultado) {
        System.out.println("El resultado es: " + resultado);
    }

    /**
     * Muestra los posibles errores que puedan haber en el controlador.
     *
     * Todos los errores pasan por este metodo, para controlar las pequeas
     * ayudas, saber cuando ocurrio un error.
     *
     * Si se abrio la linea de comandos de la calculadora y se equivoca mas de
     * dos veces le muestra un mensaje para saber que tambien se puede salir.
     *
     * @param error el error que se debe mostrar.
     */
    public void mostrarError(String error) {
        cont++; //Suma el error
        String ayuda = miniAyuda();

        //Si el contador el mayor de dos, aade a la mini ayuda este mensaje
        if (cont > 2) {
            ayuda += " o -exit para salir.";
            cont = 0; //Restablece a 0 los errores
        }

        System.out.println(error + "\n" + ayuda);
    }

    /**
     * Si se abrio la linea de comandos de la calculadora mostramos una
     * bienvenida.
     *
     */
    final public void mostrarBienvenida() {
        System.out.println("Calculadora Command Line Interface 2.0\n");
    }

    /**
     * Al salir del programa mostrar una despedida, si se decidio abrir el modo
     * de la calculadora.
     *
     * Esta despedida no debe de ser cambiada a no ser que se cree una nueva
     * version de la calculadora.
     */
    final public void mostrarDespedida() {
        sc.close(); //Cierro el scanner
        System.out.println("\nbye bye ^.^ Calculadora Command Line " + "Interface 2.0");
    }
}