at.ac.tuwien.ims.latex2mobiformulaconv.app.Main.java Source code

Java tutorial

Introduction

Here is the source code for at.ac.tuwien.ims.latex2mobiformulaconv.app.Main.java

Source

package at.ac.tuwien.ims.latex2mobiformulaconv.app;

import at.ac.tuwien.ims.latex2mobiformulaconv.converter.Converter;
import at.ac.tuwien.ims.latex2mobiformulaconv.converter.html2mobi.HtmlToMobiConverter;
import at.ac.tuwien.ims.latex2mobiformulaconv.converter.latex2html.LatexToHtmlConverter;
import at.ac.tuwien.ims.latex2mobiformulaconv.utils.WorkingDirectoryResolver;
import org.apache.commons.cli.*;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/*
 * The MIT License (MIT)
 * latex2mobi -- LaTeX Formulas to Mobi Converter
 * Copyright (c) 2014 Michael Au
 * <p/>
 * 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:
 * <p/>
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * <p/>
 * 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.
 * <p/>
 * <p/>
 * For Third Party Software Licenses read LICENSE file in base dir.
 */

/**
 * The main latex2mobi command line application
 *
 * @author Michael Au
 *         Created: 29.04.14 22:55
 */
public class Main {

    public static final String CALIBRE_HTML2MOBI_CONVERTER = "calibre-html2mobi-converter";
    public static final String KINDLEGEN_HTML2MOBI_CONVERTER = "kindlegen-html2mobi-converter";
    private static final String CONFIGURATION_FILENAME = "configuration.properties";
    // Utilities
    private static final Logger logger = Logger.getRootLogger();
    private static PropertiesConfiguration config;
    private static Options options;
    private static ApplicationContext applicationContext;
    // Flag options
    private static boolean replaceWithPictures = false;
    private static boolean debugMarkupOutput = false;
    private static boolean exportMarkup = false;
    private static boolean noMobiConversion = false;
    private static boolean useCalibreInsteadOfKindleGen = false;
    // Value options
    private static String title = null;
    private static String filename = "LaTeX2Mobi";
    // Paths
    private static List<Path> inputPaths = new ArrayList<Path>();
    private static Path workingDirectory;
    private static Path outputPath;

    private Main() {
        // do nothing
    }

    /**
     * Main application method, may exit on error.
     *
     * @param args standard posix command line arguments
     */
    public static void main(String[] args) {
        logger.debug("main() started with args:");
        for (int i = 0; i < args.length; i++) {
            logger.debug("args[" + i + "]" + ": " + args[i]);
        }

        // Initialize application
        applicationContext = new ClassPathXmlApplicationContext("/application-context.xml");
        logger.debug("Application context loaded.");

        setupWorkingDirectory();
        logger.debug("Working directory set up to: " + workingDirectory.toAbsolutePath().toString());

        initializeOptions();

        // Analyse options
        parseCli(args);
        logger.debug("CLI arguments parsed.");

        loadConfiguration();
        logger.debug("Configuration loaded.");

        // Start conversion
        Converter converter;
        if (replaceWithPictures) {
            converter = (Converter) applicationContext.getBean("image-converter");
        } else {
            converter = (Converter) applicationContext.getBean("dom-converter");
        }

        // Decide which HtmlToMobi Converter to use
        HtmlToMobiConverter htmlToMobiConverter;
        if (useCalibreInsteadOfKindleGen) {
            htmlToMobiConverter = (HtmlToMobiConverter) applicationContext.getBean(CALIBRE_HTML2MOBI_CONVERTER);
        } else {
            // default is kindlegen
            htmlToMobiConverter = (HtmlToMobiConverter) applicationContext.getBean(KINDLEGEN_HTML2MOBI_CONVERTER);
        }
        converter.setHtmlToMobiConverter(htmlToMobiConverter);

        converter.setWorkingDirectory(workingDirectory);

        converter.setInputPaths(inputPaths);
        converter.setReplaceWithPictures(replaceWithPictures);
        converter.setOutputPath(outputPath);
        converter.setFilename(filename);
        converter.setTitle(title);
        converter.setDebugMarkupOutput(debugMarkupOutput);
        converter.setExportMarkup(exportMarkup);
        converter.setNoMobiConversion(noMobiConversion);

        try {
            Path resultFile = converter.convert();
            logger.info("Result : " + resultFile.toAbsolutePath().toString());
        } catch (FileNotFoundException e) {
            logger.error(e.getMessage());
        }

        logger.debug("main() exit.");
    }

    private static void parseCli(String[] args) {
        CommandLineParser parser = new PosixParser();
        try {
            CommandLine cmd = parser.parse(options, args);

            // Show usage, ignore other parameters and quit
            if (cmd.hasOption('h')) {
                usage();
                logger.debug("Help called, main() exit.");
                System.exit(0);
            }

            if (cmd.hasOption('d')) {
                // Activate debug markup only - does not affect logging!
                debugMarkupOutput = true;
            }

            if (cmd.hasOption('m')) {
                exportMarkup = true;
            }

            if (cmd.hasOption('t')) {
                title = cmd.getOptionValue('t');
            }

            if (cmd.hasOption('f')) {
                filename = cmd.getOptionValue('f');
            }

            if (cmd.hasOption('n')) {
                exportMarkup = true; // implicit markup export
                noMobiConversion = true;
            }

            if (cmd.hasOption('i')) {
                String[] inputValues = cmd.getOptionValues('i');
                for (String inputValue : inputValues) {
                    inputPaths.add(Paths.get(inputValue));
                }
            } else {
                logger.error("You have to specify an inputPath file or directory!");
                usage();
                System.exit(1);
            }

            if (cmd.hasOption('o')) {
                String outputDirectory = cmd.getOptionValue('o');

                outputPath = Paths.get(outputDirectory).toAbsolutePath();
                logger.debug("Output path: " + outputPath.toAbsolutePath().toString());
                if (!Files.isDirectory(outputPath) && Files.isRegularFile(outputPath)) {
                    logger.error("Given output directory is a file! Exiting...");

                    System.exit(1);
                }

                if (!Files.exists(outputPath)) {
                    Files.createDirectory(outputPath);
                }

                if (!Files.isWritable(outputPath)) {
                    logger.error("Given output directory is not writable! Exiting...");
                    logger.debug(outputPath.toAbsolutePath().toString());
                    System.exit(1);
                }
                logger.debug("Output path: " + outputPath.toAbsolutePath().toString());

            } else {
                // Set default output directory if none is given
                outputPath = workingDirectory;
            }

            // If set, replace LaTeX Formulas with PNG images, created by
            if (cmd.hasOption("r")) {
                logger.debug("Picture Flag set");
                replaceWithPictures = true;
            }

            if (cmd.hasOption("u")) {
                logger.debug("Use calibre instead of kindlegen");
                useCalibreInsteadOfKindleGen = true;
            }

            // Executable configuration
            LatexToHtmlConverter latexToHtmlConverter = (LatexToHtmlConverter) applicationContext
                    .getBean("latex2html-converter");
            if (cmd.hasOption(latexToHtmlConverter.getExecOption().getOpt())) {
                String execValue = cmd.getOptionValue(latexToHtmlConverter.getExecOption().getOpt());
                logger.info("LaTeX to HTML Executable argument was given: " + execValue);
                Path execPath = Paths.get(execValue);
                latexToHtmlConverter.setExecPath(execPath);
            }

            String htmlToMobiConverterBean = KINDLEGEN_HTML2MOBI_CONVERTER;
            if (useCalibreInsteadOfKindleGen) {
                htmlToMobiConverterBean = CALIBRE_HTML2MOBI_CONVERTER;
            }

            HtmlToMobiConverter htmlToMobiConverter = (HtmlToMobiConverter) applicationContext
                    .getBean(htmlToMobiConverterBean);
            Option htmlToMobiOption = htmlToMobiConverter.getExecOption();
            if (cmd.hasOption(htmlToMobiOption.getOpt())) {
                String execValue = cmd.getOptionValue(htmlToMobiOption.getOpt());
                logger.info("HTML to Mobi Executable argument was given: " + execValue);
                try {
                    Path execPath = Paths.get(execValue);
                    htmlToMobiConverter.setExecPath(execPath);
                } catch (InvalidPathException e) {
                    logger.error("Invalid path given for --" + htmlToMobiOption.getLongOpt() + " <"
                            + htmlToMobiOption.getArgName() + ">");
                    logger.error("I will try to use your system's PATH variable...");
                }
            }

        } catch (MissingOptionException m) {

            Iterator<String> missingOptionsIterator = m.getMissingOptions().iterator();
            while (missingOptionsIterator.hasNext()) {
                logger.error("Missing required options: " + missingOptionsIterator.next() + "\n");
            }
            usage();
            System.exit(1);
        } catch (MissingArgumentException a) {
            logger.error("Missing required argument for option: " + a.getOption().getOpt() + "/"
                    + a.getOption().getLongOpt() + "<" + a.getOption().getArgName() + ">");
            usage();
            System.exit(2);
        } catch (ParseException e) {
            logger.error("Error parsing command line arguments, exiting...");
            logger.error(e.getMessage(), e);
            System.exit(3);
        } catch (IOException e) {
            logger.error("Error creating output path at " + outputPath.toAbsolutePath().toString());
            logger.error(e.getMessage(), e);
            logger.error("Exiting...");
            System.exit(4);
        }
    }

    private static void setupWorkingDirectory() {
        workingDirectory = WorkingDirectoryResolver.getWorkingDirectory(Main.class);

        if (workingDirectory == null) {
            logger.error("Exiting...");
            System.exit(1);
        }
    }

    private static void usage() {
        HelpFormatter formatter = new HelpFormatter();

        // Windows cmd.exe does not like my sharp s ().
        // Grrr.... Schei? Encoding.
        String header = "LaTeX Formulas to Mobi Converter\n" + "(c) 2014-2015 by Michael Auss\n\n\n";
        String footer = "\n\n\nThis software is open source, hosted at GitHub:\n"
                + "https://github.com/Sevyls/latex-formulas-mobi-converter";
        formatter.printHelp("latex2mobi", header, options, footer);
    }

    private static void loadConfiguration() {
        Path defaultConfigPath = workingDirectory.resolve(CONFIGURATION_FILENAME);
        logger.debug("Searching for config in default filepath: " + defaultConfigPath.toAbsolutePath().toString());

        try {
            logger.debug("Loading configuration.");

            config = new PropertiesConfiguration(defaultConfigPath.toFile());

        } catch (ConfigurationException e) {
            logger.error(e.getMessage(), e);
            logger.error("Configuration could not be loaded. Exiting...");
            System.exit(-1);
        }

        if (!(defaultConfigPath.toFile().exists() && defaultConfigPath.toFile().isFile())) {
            try {
                logger.info("Creating empty config file in working directory...");
                config.save();
                logger.debug("Saved empty configuration: " + defaultConfigPath.toAbsolutePath().toString());
            } catch (ConfigurationException e) {
                logger.error("Default configuration file could not be saved!");
                logger.error(e.getMessage(), e);
            }
        }
    }

    private static void initializeOptions() {
        options = new Options();

        Option inputOption = new Option("i", "inputPaths", true, "inputPaths file");
        inputOption.setRequired(true);
        inputOption.setArgs(Option.UNLIMITED_VALUES);
        inputOption.setOptionalArg(false);
        inputOption.setValueSeparator(',');
        options.addOption(inputOption);

        options.addOption("f", "filename", true, "output filename");
        options.addOption("o", "output-dir", true, "output directory");
        options.addOption("m", "export-markup", false, "export html markup");
        options.addOption("n", "no-mobi", false, "no Mobi conversion, just markup, NOTE: makes -m implicit!");
        options.addOption("t", "title", true, "Document title");
        options.addOption("h", "help", false, "show this help");
        options.addOption("d", "debugMarkupOutput", false, "show debug output in html markup");
        options.addOption("u", "use-calibre", false, "use calibre ebook-convert instead of kindlegen");

        Option picturesOption = new Option("r", "replace latex formulas with pictures, override html");
        picturesOption.setLongOpt("replace-with-images");
        picturesOption.setArgs(0);
        picturesOption.setRequired(false);
        options.addOption(picturesOption);

        // implementation specific options
        options.addOption(
                ((LatexToHtmlConverter) applicationContext.getBean("latex2html-converter")).getExecOption());
        options.addOption(
                ((HtmlToMobiConverter) applicationContext.getBean(KINDLEGEN_HTML2MOBI_CONVERTER)).getExecOption());
        options.addOption(
                ((HtmlToMobiConverter) applicationContext.getBean(CALIBRE_HTML2MOBI_CONVERTER)).getExecOption());
    }
}