org.xlrnet.tibaija.Application.java Source code

Java tutorial

Introduction

Here is the source code for org.xlrnet.tibaija.Application.java

Source

/*
 * Copyright (c) 2015 Jakob Hende
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE
 */

package org.xlrnet.tibaija;

import ch.qos.logback.classic.Level;
import org.apache.commons.lang3.StringUtils;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xlrnet.tibaija.exception.TIRuntimeException;
import org.xlrnet.tibaija.graphics.FontConstants;
import org.xlrnet.tibaija.graphics.FontRegistry;
import org.xlrnet.tibaija.graphics.HomeScreen;
import org.xlrnet.tibaija.graphics.NullHomeScreen;
import org.xlrnet.tibaija.io.CalculatorIO;
import org.xlrnet.tibaija.io.ConsoleIO;
import org.xlrnet.tibaija.memory.CalculatorMemory;
import org.xlrnet.tibaija.memory.DefaultCalculatorMemory;
import org.xlrnet.tibaija.processor.ExecutionEnvironment;
import org.xlrnet.tibaija.processor.TI83Plus;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * Main application class for starting the interpreter.
 */
public class Application {

    private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);

    boolean configured = false;

    public static void main(String[] args) {
        new Application().run(args);
    }

    private static VirtualCalculator getDefaultCalculator(CodeProvider codeProvider) throws IOException {
        Reader reader;
        Writer writer;

        if (System.console() != null) {
            Console console = System.console();
            reader = console.reader();
            writer = console.writer();
            LOGGER.debug("Initialised native system console");
        } else {
            reader = new InputStreamReader(System.in);
            writer = new OutputStreamWriter(System.out);
            LOGGER.debug("Initialised system I/O streams");
        }

        CalculatorIO io = new ConsoleIO(reader, writer);
        CalculatorMemory memory = new DefaultCalculatorMemory();
        HomeScreen homeScreen = new NullHomeScreen();
        FontRegistry fontRegistry = new FontRegistry();
        fontRegistry.registerFont(Paths.get("largeFont.json"), FontConstants.FONT_LARGE);
        fontRegistry.registerFont(Paths.get("smallFont.json"), FontConstants.FONT_SMALL);

        ExecutionEnvironment.newEnvironment(memory, io, codeProvider, homeScreen, fontRegistry);
        return new TI83Plus(memory, io, codeProvider);
    }

    public boolean isConfigured() {
        return configured;
    }

    private void configureRootLogger(ApplicationConfiguration config) {
        ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory
                .getLogger(Logger.ROOT_LOGGER_NAME);
        if (config.isShowDebugLog()) {
            rootLogger.setLevel(Level.DEBUG);
        } else {
            rootLogger.setLevel(Level.INFO);
        }
    }

    private void parseArguments(String[] args) {
        ApplicationConfiguration config = new ApplicationConfiguration();
        CmdLineParser parser = new CmdLineParser(config);

        try {
            parser.parseArgument(args);
            if (config.isShowHelp() || config.isInteractive() || config.getStartFile() != null) {
                configured = true;
            }

            configureRootLogger(config);

            if (config.isInteractive()) {
                runInteractiveMode();
            } else if (config.getStartFile() != null) {
                runFileMode(config.getStartFile());
            } else if (config.isShowHelp() || !isConfigured()) {
                printUsage(parser);
            }

        } catch (CmdLineException e) {
            LOGGER.error("Unable to parse command line parameters", e);
        } catch (Exception e) {
            LOGGER.error("Internal error", e);
        }
    }

    private void printUsage(CmdLineParser parser) {
        System.out.println("Tibaija - a TI-Basic interpreter for Java");
        System.out.println();
        System.out.println("Usage: [file] [options]");
        parser.printUsage(System.out);
    }

    private void run(String[] args) {
        parseArguments(args);
    }

    private void runFileMode(File startFile) {
        LOGGER.info("Starting interpreter from file ...");

        try {
            Path filePath = startFile.toPath();
            Path parentDirectory = filePath.toAbsolutePath().getParent();
            FileSystemCodeProvider codeProvider = new FileSystemCodeProvider(parentDirectory);
            String bootFile = codeProvider.registerFile(filePath);
            VirtualCalculator calculator = getDefaultCalculator(codeProvider);

            LOGGER.info("System booted");

            calculator.executeProgram(bootFile);
        } catch (IOException e) {
            LOGGER.error("Program load error", e);
        }

    }

    private void runInteractiveMode() throws IOException {
        LOGGER.info("Starting interpreter in interactive mode ...");

        VirtualCalculator calculator = getDefaultCalculator(new DummyCodeProvider());
        CalculatorIO io = calculator.getIODevice();
        CalculatorMemory memory = calculator.getMemory();

        showWelcome();
        String input;

        while (true) {
            try {
                input = io.readInput();

                if (input == null || StringUtils.equalsIgnoreCase("exit", input)) {
                    break;
                }

                calculator.interpret(input);
                io.printLine(memory.getLastResult());

            } catch (TIRuntimeException ti) {
                io.printLine("ERR: " + ti.getMessage());
            } catch (Exception e) {
                LOGGER.error("An internal error occurred", e);
                break;
            }
        }

        LOGGER.info("Exiting interpreter ...");
        System.exit(0);
    }

    private void showWelcome() {
        LOGGER.info("Started tibaija in interactive mode");
        System.out.println("#############################################################################");
        System.out.println("#################### Tibaija started in interactive mode ####################");
        System.out.println("####################   Type 'exit' to stop interpreter   ####################");
        System.out.println("#############################################################################");
    }
}