Package org.openbel.framework.tools

Source Code of org.openbel.framework.tools.DocumentConverter

/**
* Copyright (C) 2012-2013 Selventa, Inc.
*
* This file is part of the OpenBEL Framework.
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* The OpenBEL Framework 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 the OpenBEL Framework. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms under LGPL v3:
*
* This license does not authorize you and you are prohibited from using the
* name, trademarks, service marks, logos or similar indicia of Selventa, Inc.,
* or, in the discretion of other licensors or authors of the program, the
* name, trademarks, service marks, logos or similar indicia of such authors or
* licensors, in any marketing or advertising materials relating to your
* distribution of the program or any covered product. This restriction does
* not waive or limit your obligation to keep intact all copyright notices set
* forth in the program as delivered to you.
*
* If you distribute the program in whole or in part, or any modified version
* of the program, and you assume contractual liability to the recipient with
* respect to the program or modified version, then you will indemnify the
* authors and licensors of the program for any liabilities that these
* contractual assumptions directly impose on those licensors and authors.
*/
package org.openbel.framework.tools;

import static java.lang.String.format;
import static org.openbel.framework.common.BELUtilities.hasItems;
import static org.openbel.framework.common.Strings.UTF_8;
import static org.openbel.framework.common.enums.ExitCode.GENERAL_FAILURE;
import static org.openbel.framework.core.StandardOptions.LONG_OPT_DEBUG;
import static org.openbel.framework.core.StandardOptions.SHORT_OPT_VERBOSE;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.util.LinkedList;
import java.util.List;

import javax.xml.bind.JAXBException;

import org.apache.commons.cli.Option;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.openbel.bel.model.BELParseErrorException;
import org.openbel.bel.model.BELParseWarningException;
import org.openbel.framework.common.SimpleOutput;
import org.openbel.framework.common.bel.converters.BELDocumentConverter;
import org.openbel.framework.common.bel.parser.BELParseResults;
import org.openbel.framework.common.bel.parser.BELParser;
import org.openbel.framework.common.belscript.BELScriptExporter;
import org.openbel.framework.common.model.Document;
import org.openbel.framework.common.xbel.parser.XBELConverter;
import org.openbel.framework.core.CommandLineApplication;
import org.openbel.framework.core.XBELConverterServiceImpl;
import org.openbel.framework.core.compiler.ValidationError;
import org.xml.sax.SAXException;

public final class DocumentConverter extends CommandLineApplication {

    private static final String DOCUMENT_CONVERTER_NAME = "Document Converter";
    private static final String DOCUMENT_CONVERTER_DESC =
            "Convert between BEL and XBEL formats";

    private static final String LONG_OPT_NO_PRESERVE = "no-preserve";
    private static final String USAGE_OUTPUT_FILE =
            " [{-o | --output-file} <output file name> [-f | --force | --no-preserve] ]";
    private static final String USAGE_TYPE =
            " [{-t | --type} {bel | BEL | xbel | XBEL}]";

    private static final String BEL_EXTENSION = ".bel";
    private static final String XBEL_EXTENSION = ".xbel";

    // Flags specified by command line options
    private boolean verbose, debug;

    /**
     * Static main method to launch the Document Converter tool.
     *
     * @param args {@link String String[]} the command-line arguments
     */
    public static void main(String[] args) {
        DocumentConverter app = new DocumentConverter(args);
        app.run();
    }

    public DocumentConverter(String[] args) {
        super(args, false);

        final SimpleOutput reportable = new SimpleOutput();
        reportable.setErrorStream(System.err);
        // Normal output is written to stderr because the output document
        // may be written to stdout.
        reportable.setOutputStream(System.err);
        setReportable(reportable);
        printApplicationInfo();

        if (hasOption('h')) {
            printHelp(true);
        }
    }

    private void run() {
        verbose = hasOption(SHORT_OPT_VERBOSE);
        debug = hasOption(LONG_OPT_DEBUG);

        final List<String> extraArgs = getExtraneousArguments();

        // Determine the input document file path
        if (extraArgs.size() == 0) {
            // print out the usage if no arguments are given
          printUsage();
          // Another SimpleOutput is used here, and it uses stdout because at this
          // point nothing else will need to be output.
          SimpleOutput so = new SimpleOutput();
          so.setErrorStream(System.out);
          so.error("\n");
            so.error("No documents specified.");
            end();
        } else if (extraArgs.size() > 1) {
            fatal("Only a single document can be specified.");
        }
        final String inputFileName = extraArgs.get(0);

        // Check that the input file exists
        final File inputFile = new File(inputFileName);
        if (!inputFile.exists()) {
            fatal("Input file does not exist - "
                    + inputFile.getAbsolutePath());
        }

        // Determine the format of the input document
        final DocumentFormat format = determineType(inputFile);
        if (format == null) {
            fatal("Could not determine the format of the input file '"
                    + inputFileName + "'.  " +
                    "Please specify '-t BEL' or '-t XBEL'.");
        }

        OutputStream output = null;
        if (hasOption("o")) {
            final String outputFilename = getOptionValue("o");
            final boolean noPreserve =
                    (hasOption("f") || hasOption(LONG_OPT_NO_PRESERVE));
            final File outputFile = new File(outputFilename);

            if (!noPreserve && outputFile.exists()) {
                fatal("File '" + outputFilename + "' exists, specify --"
                        + LONG_OPT_NO_PRESERVE + " to override.");
            } else if (inputFile.equals(outputFile)) {
                fatal("The input file cannot be the same as the output file.");
            } else {
                // Create a file to write the output document
                try {
                    outputFile.createNewFile();
                    output = new FileOutputStream(outputFile);
                } catch (IOException ex) {
                    bailOnException(ex);
                }
            }
        } else {
            output = System.out;
        }

        if (format == DocumentFormat.BEL) {
            convertBelToXbel(inputFile, output);
        } else if (format == DocumentFormat.XBEL) {
            convertXbelToBel(inputFile, output);
        }
    }

    private DocumentFormat determineType(final File inputFile) {
        DocumentFormat format = null;
        if (hasOption("t")) {
            format = DocumentFormat.getFormatByLabel(getOptionValue("t"));
        }
        if (format == null) {
            final int index = inputFile.getName().lastIndexOf(".");
            if (index == -1) {
                return null;
            }

            final String extension = inputFile.getName().substring(index);
            if (extension.equals(BEL_EXTENSION)) {
                format = DocumentFormat.BEL;
            } else if (extension.equals(XBEL_EXTENSION)) {
                format = DocumentFormat.XBEL;
            }
        }
        return format;
    }

    private void convertBelToXbel(final File inputFile,
            final OutputStream output) {
        try {
            final String belText = FileUtils.readFileToString(inputFile, UTF_8);
            final BELParseResults result = BELParser.parse(belText);

            // Report any BEL parser warnings or errors if verbose mode is enabled
            if (verbose) {
                final List<BELParseWarningException> warnings =
                        result.getSyntaxWarnings();
                final List<BELParseErrorException> errors =
                        result.getSyntaxErrors();
                final String inputFilePath = inputFile.getAbsolutePath();

                if (hasItems(warnings)) {
                    final int numWarnings = warnings.size();
                    reportable.output(format("%d BEL parser warning%s:",
                            numWarnings, (numWarnings == 1 ? "" : "s")));
                    int i = 0;
                    for (BELParseWarningException warning : warnings) {
                        final ValidationError err = new ValidationError(
                                inputFilePath,
                                warning.getMessage(),
                                warning.getLine(),
                                warning.getCharacter());
                        reportable.output(format("%5d. %s", ++i,
                                err.getUserFacingMessage()));
                    }
                }
                if (hasItems(errors)) {
                    final int numErrors = errors.size();
                    reportable.output(format("%d BEL parser error%s:",
                            numErrors, (numErrors == 1 ? "" : "s")));
                    int i = 0;
                    for (BELParseErrorException error : errors) {
                        final ValidationError err = new ValidationError(
                                inputFilePath,
                                error.getMessage(),
                                error.getLine(),
                                error.getCharacter());
                        reportable.output(format("%5d. %s", ++i,
                                err.getUserFacingMessage()));
                    }
                }
            }

            final Document bel =
                    new BELDocumentConverter().convert(result.getDocument());

            final org.openbel.framework.common.xbel.converters.DocumentConverter converter =
                    new org.openbel.framework.common.xbel.converters.DocumentConverter();

            new XBELConverter().marshal(converter.convert(bel), output);

        } catch (JAXBException ex) {
            close(output);
            bailOnException(ex);
        } catch (IOException ex) {
            close(output);
            bailOnException(ex);
        } catch (RuntimeException ex) {
            close(output);
            bailOnException(ex);
        }
    }

    private void convertXbelToBel(final File inputFile,
            final OutputStream output) {
        try {
            final boolean useShortForm = false;
            final BELScriptExporter exporter = new BELScriptExporter();
            exporter.setUseShortForm(useShortForm);
            exporter.export(new XBELConverterServiceImpl().toCommon(inputFile),
                    output);

        } catch (SAXException ex) {
            close(output);
            bailOnException(ex);
        } catch (URISyntaxException ex) {
            close(output);
            bailOnException(ex);
        } catch (IOException ex) {
            close(output);
            bailOnException(ex);
        } catch (JAXBException ex) {
            close(output);
            bailOnException(ex);
        } catch (RuntimeException ex) {
            close(output);
            bailOnException(ex);
        }
    }

    private void close(final OutputStream os) {
        if (os != System.out && os != System.err) {
            try {
                os.close();
            } catch (IOException ex) {}
        }
    }

    private void bailOnException(final Exception e) {
        final Throwable cause = ExceptionUtils.getRootCause(e);
        reportable.error("Unable to run " + DOCUMENT_CONVERTER_NAME);
        final String reason =
                (cause == null ? e.getMessage() : cause.getMessage());
        reportable.error("Reason: "
                +
                (reason != null ? reason
                        : "none.  Specify --debug for more information."));
        if (debug) {
            e.printStackTrace(reportable.errorStream());
        }
        bail(GENERAL_FAILURE);
    }

    @Override
    public String getApplicationName() {
        return DOCUMENT_CONVERTER_NAME;
    }

    @Override
    public String getApplicationShortName() {
        return DOCUMENT_CONVERTER_NAME;
    }

    @Override
    public String getApplicationDescription() {
        return DOCUMENT_CONVERTER_DESC;
    }

    @Override
    public String getUsage() {
        final StringBuilder bldr = new StringBuilder();
        bldr.append(" <BEL or XBEL document name>")
                .append(USAGE_OUTPUT_FILE)
                .append(USAGE_TYPE)
                .append(" [-h | --help] [-v | --verbose]");
        return bldr.toString();
    }

    @Override
    public List<Option> getCommandLineOptions() {
        List<Option> options = new LinkedList<Option>();

        // -f/--force/--no-preserve used with -o/--output-file to force the
        // file to be overwritten if it already exists
        final String noPreserveHelp =
                "Optional.  If specified, if a file with the same name as the output file "
                        +
                        "already exists then it will be overwritten.\n"
                        +
                        "The default is always to preserve the existing file and "
                        +
                        "generate a warning.";
        options.add(new Option("f", "force", false,
                "Identical to --no-preserve."));
        options.add(new Option(null, LONG_OPT_NO_PRESERVE, false,
                noPreserveHelp));

        // -o/--output-file used to set the file to write the new BEL or XBEL document
        final String outputFileHelp =
                "Optional.  If present, it indicates the name of the output file "
                        +
                        "to write the converted BEL or XBEL document to.";
        options.add(new Option("o", "output-file", true, outputFileHelp));

        // -t/--type used to specify whether the input file is BEL (or XBEL), and
        // therefore whether the output file will be XBEL (or BEL).
        final String typeHelp =
                "Specifies the format of the input file.  By default, "
                        + getApplicationShortName()
                        +
                        " infers the format of the document by "
                        +
                        "its extension ("
                        + BEL_EXTENSION
                        + " or "
                        + XBEL_EXTENSION
                        + ").\n"
                        +
                        "If BEL then the input document is expected to be in BEL format and the "
                        +
                        "output document will be in XBEL format.  If XBEL then the input document "
                        +
                        "is expected to be in XBEL format and the output document will be in BEL format.";
        options.add(new Option("t", "type", true, typeHelp));

        // The base class CommandLineApplication will add the --debug, -h/--help,
        // and -v/--verbose options.

        return options;
    }

    public static enum DocumentFormat {
        BEL, XBEL;

        public static DocumentFormat getFormatByLabel(final String label) {
            if (label.equals("bel") || label.equals("BEL")) {
                return BEL;
            } else if (label.equals("xbel") || label.equals("XBEL")) {
                return XBEL;
            } else {
                return null;
            }
        }
    }

    /*
     * Override the printUsage() methods to avoid using stdout to
     * output anything other than a converted BEL or XBEL document.
     *
     * @see org.openbel.framework.clf.CommandLineApplication#printUsage()
     */

    @Override
    public void printUsage() {
        super.printUsage(reportable.outputStream());
    }

    @Override
    public void printUsage(final OutputStream os) {
        super.printUsage(reportable.outputStream());
    }
}
TOP

Related Classes of org.openbel.framework.tools.DocumentConverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.