Package org.openbel.framework.tools

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

/**
* 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.Runtime.getRuntime;
import static java.lang.System.currentTimeMillis;
import static java.lang.System.err;
import static org.openbel.framework.common.BELUtilities.asPath;
import static org.openbel.framework.common.BELUtilities.timeFormat;
import static org.openbel.framework.common.Strings.DIRECTORY_CREATION_FAILED;
import static org.openbel.framework.common.Strings.SYSTEM_CONFIG_PATH;
import static org.openbel.framework.common.Strings.TIME_HELP;
import static org.openbel.framework.common.Strings.WARNINGS_AS_ERRORS;
import static org.openbel.framework.common.cfg.SystemConfiguration.getSystemConfiguration;
import static org.openbel.framework.common.enums.ExitCode.GENERAL_FAILURE;
import static org.openbel.framework.core.StandardOptions.ARG_SYSCFG;
import static org.openbel.framework.core.StandardOptions.LONG_OPT_DEBUG;
import static org.openbel.framework.core.StandardOptions.LONG_OPT_SYSCFG;
import static org.openbel.framework.core.StandardOptions.LONG_OPT_TIME;
import static org.openbel.framework.core.StandardOptions.LONG_OPT_VERBOSE;
import static org.openbel.framework.core.StandardOptions.SHRT_OPT_SYSCFG;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.LinkedList;
import java.util.List;

import javax.xml.bind.JAXBException;

import org.apache.commons.cli.Option;
import org.openbel.framework.common.BELRuntimeException;
import org.openbel.framework.common.Reportable;
import org.openbel.framework.common.SimpleOutput;
import org.openbel.framework.common.cfg.RuntimeConfiguration;
import org.openbel.framework.common.cfg.SystemConfiguration;
import org.openbel.framework.common.enums.ExitCode;
import org.openbel.framework.core.CommandLineApplication;
import org.openbel.framework.core.XBELConverterService;
import org.openbel.framework.core.XBELConverterServiceImpl;
import org.openbel.framework.core.XBELValidatorService;
import org.openbel.framework.core.XBELValidatorServiceImpl;
import org.xml.sax.SAXException;

/**
* Base class for BEL phase compilers.
*/
public abstract class PhaseApplication extends CommandLineApplication {
    private final static String INDENT = "    ";

    /**
     * The artifact path.
     */
    protected File artifactPath;

    /**
     * The output directory.
     */
    protected File outputDirectory;

    /**
     * Time command-line argument short option, {@value #SHORT_OPT_TIME}.
     *
     * @deprecated In favor of {@link #LONG_OPT_TIME} only
     */
    @Deprecated
    protected final static String SHORT_OPT_TIME = "t";

    /**
     * Pedantic command-line argument long option, {@value #LONG_OPT_PEDANTIC}.
     */
    protected final static String LONG_OPT_PEDANTIC = "pedantic";

    private long starttime;
    private long endtime;

    /**
     * @param args
     * @param configs
     */
    public PhaseApplication(String[] args) {
        super(args);

        final SimpleOutput reportable = new SimpleOutput();
        reportable.setErrorStream(System.err);
        reportable.setOutputStream(System.out);
        setReportable(reportable);

        setOptions(getPhaseConfiguration());

        // Initialize the system configuration either through the
        // command-line or system defaults.
        initializeSystemConfiguration();
        SystemConfiguration syscfg = getSystemConfiguration();
        outputDirectory = syscfg.getWorkingDirectory();
    }

    public void start() {
        starttime = currentTimeMillis();
    }

    public void stop() {
        endtime = currentTimeMillis();

        final StringBuilder bldr = new StringBuilder();
        bldr.append(INDENT);
        bldr.append("=== Phase Complete === ");
        markTime(bldr, starttime, endtime);
        output(bldr.toString());
    }

    /**
     * Fail with a {@link ExitCode#GENERAL_FAILURE general failure}, printing
     * the application's usage.
     */
    public void failUsage() {
        printUsage();
        bail(GENERAL_FAILURE);
    }

    /**
     * Returns a list of phase-agnostic command-line options.
     *
     * @return List of options
     */
    @Override
    public List<Option> getCommandLineOptions() {
        final List<Option> ret = new LinkedList<Option>();

        String help;

        help = TIME_HELP;
        ret.add(new Option(SHORT_OPT_TIME, LONG_OPT_TIME, false, help));

        help = WARNINGS_AS_ERRORS;
        ret.add(new Option(null, LONG_OPT_PEDANTIC, false, help));

        help = SYSTEM_CONFIG_PATH;
        Option o = new Option(SHRT_OPT_SYSCFG, LONG_OPT_SYSCFG, true, help);
        o.setArgName(ARG_SYSCFG);
        ret.add(o);

        return ret;
    }

    /**
     * Returns the phase options.
     *
     * @return {@link RuntimeConfiguration}
     */
    public abstract RuntimeConfiguration getPhaseConfiguration();

    /**
     * Returns {@code true} if the command-line arguments are valid for this
     * phase, {@code false} otherwise.
     *
     * @param args Command-line arguments
     * @return boolean
     */
    public abstract boolean validCommandLine();

    /**
     * Returns {@link #getPhaseConfiguration()}
     * {@link RuntimeConfiguration#isTime()}, a delegate method for convenience.
     *
     * @return boolean
     */
    protected boolean withTime() {
        return getPhaseConfiguration().isTime();
    }

    /**
     * Returns {@link #getPhaseConfiguration()}
     * {@link RuntimeConfiguration#isDebug()}, a delegate method for
     * convenience.
     *
     * @return boolean
     */
    protected boolean withDebug() {
        return getPhaseConfiguration().isDebug();
    }

    /**
     * Returns {@link #getPhaseConfiguration()}
     * {@link RuntimeConfiguration#isVerbose()}, a delegate method for
     * convenience.
     *
     * @return boolean
     */
    protected boolean withVerbose() {
        return getPhaseConfiguration().isVerbose();
    }

    /**
     * Returns {@link #getPhaseConfiguration()}
     * {@link RuntimeConfiguration#isWarningsAsErrors()}, a delegate method for
     * convenience.
     *
     * @return boolean
     */
    protected boolean withPedantic() {
        return getPhaseConfiguration().isWarningsAsErrors();
    }

    /**
     * Sets the phase-agnostic runtime configuration.
     */
    private void setOptions(RuntimeConfiguration rc) {
        if (hasOption(SHORT_OPT_TIME)) {
            rc.setTime(true);
        }
        if (hasOption(LONG_OPT_DEBUG)) {
            rc.setDebug(true);
        }
        if (hasOption(LONG_OPT_VERBOSE)) {
            rc.setVerbose(true);
        }
        if (hasOption(LONG_OPT_PEDANTIC)) {
            rc.setWarningsAsErrors(true);
        }
    }

    /**
     * Sends {@code "=== <header> ==="} to {@link Reportable#output(String...)
     * output}
     *
     * @param header Non-null header
     * @param phase Non-null phase
     * @param stage Non-null stage
     */
    protected void beginStage(final String header, final String stage,
            final String numStages) {
        boolean print = getPhaseConfiguration().isVerbose();
        if (print) {
            StringBuilder bldr = new StringBuilder();
            bldr.append(INDENT);
            bldr.append("Stage ");
            bldr.append(stage);
            bldr.append(" of ");
            bldr.append(numStages);
            bldr.append(": ");
            bldr.append(header);
            reportable.output(bldr.toString());
        }
    }

    /**
     * Prints phase output.
     *
     * @param output Output
     */
    protected void phaseOutput(final String output) {
        output(INDENT.concat(output));
    }

    /**
     * Prints stage output with two levels of indentation.
     *
     * @param output Output
     */
    protected void stageOutput(final String output) {
        boolean print = getPhaseConfiguration().isVerbose();
        if (print) {
            output(INDENT + INDENT + output);
        }
    }

    /**
     * Prints stage error with two levels of indentation and {@code "[ERROR]: "}
     * prefix.
     *
     * @param error Error
     */
    protected void stageError(final String error) {
        error(INDENT + INDENT + "[ERROR]: " + error);
    }

    /**
     * Prints stage warning with two levels of indentation and
     * {@code "[WARNING]: "} prefix.
     *
     * @param warning Warning
     */
    protected void stageWarning(final String warning) {
        warning(INDENT + INDENT + "[WARNING]: " + warning);
    }

    /**
     * Creates the directory artifact, failing if the directory couldn't be
     * created.
     *
     * @param outputDirectory Phase output directory
     * @param artifact Directory artifact to be created
     */
    protected final File createDirectoryArtifact(final File outputDirectory,
            final String artifact) {
        // Construct artifact path based on output directory
        String path = asPath(outputDirectory.getAbsolutePath(), artifact);
        final File ret = new File(path);
        if (!ret.isDirectory()) {
            // Fail if the directory artifact couldn't be created
            if (!ret.mkdir()) {
                error(DIRECTORY_CREATION_FAILED + ret);
                bail(ExitCode.BAD_OUTPUT_DIRECTORY);
            }
        }
        return ret;
    }

    /**
     * Invokes {@link Reportable#error(String...)} with {@code errors}.
     *
     * @param errors Error strings
     * @see org.openbel.framework.common.Reportable#error(java.lang.String[])
     */
    public void error(String... errors) {
        reportable.error(errors);
    }

    /**
     * Invokes {@link Reportable#warning(String...)} with {@code warnings}.
     *
     * @param warnings Warning strings
     * @see org.openbel.framework.common.Reportable#warning(java.lang.String[])
     */
    public void warning(String... warnings) {
        reportable.warning(warnings);
    }

    /**
     * Invokes {@link Reportable#output(String...)} with {@code outputs}.
     *
     * @param outputs Output strings
     * @see org.openbel.framework.common.Reportable#output(java.lang.String[])
     */
    public void output(String... outputs) {
        reportable.output(outputs);
    }

    /**
     * Appends {@code (#.### seconds)} to the builder, if
     * {@link RuntimeConfiguration#isTime() runtime configuration timing} is
     * set.
     *
     * @param b Non-null builder
     * @param t1 Time at {@code t1}
     * @param t2 Time at {@code t2}
     */
    protected void markTime(final StringBuilder b, long t1, long t2) {
        boolean time = getPhaseConfiguration().isTime();
        if (time) {
            String seconds = timeFormat((t2 - t1));
            b.append("(");
            b.append(seconds);
            b.append(" seconds) ");
        }
    }

    /**
     * Marks the end of a stage by appending a newline to the builder.
     *
     * @param b Non-null builder
     */
    protected void markEndStage(final StringBuilder b) {
        b.append("\n");
    }

    /**
     * Reports {@link ExitCode#toString()} to error, and invokes
     * {@link #bail(ExitCode)} with the provided exit code.
     *
     * @param e Exit code
     */
    protected void exit(ExitCode e) {
        reportable.error(e.toString());
        bail(e);
    }

    /**
     * Directs phase application lifecycle.
     *
     * @param phase Phase application
     */
    protected static void harness(PhaseApplication phase) {
        try {
            phase.start();
            phase.stop();
            phase.end();
        } catch (BELRuntimeException bre) {
            err.println(bre.getUserFacingMessage());
            systemExit(bre.getExitCode());
        } catch (OutOfMemoryError oom) {
            err.println();
            oom.printStackTrace();
            long upperlimit = getRuntime().maxMemory();
            double ulMB = upperlimit * 9.53674316e-7;
            final NumberFormat fmt = new DecimalFormat("#0");
            String allocation = fmt.format(ulMB);
            err.println("\n(current allocation is " + allocation + " MB)");
            systemExit(ExitCode.OOM_ERROR);
        }
    }

    protected XBELValidatorService createValidator() {
        try {
            return new XBELValidatorServiceImpl();
        } catch (SAXException e) {
            fatal("SAX exception creating validator service");
        } catch (MalformedURLException e) {
            fatal("Malformed URL exception creating validator service");
        } catch (IOException e) {
            fatal("IO exception creating validator service");
        } catch (URISyntaxException e) {
            fatal("URL syntax exception creating validator service");
        }
        return null;
    }

    protected XBELConverterService createConverter() {
        try {
            return new XBELConverterServiceImpl();
        } catch (SAXException e) {
            fatal("SAX exception creating converter service");
        } catch (MalformedURLException e) {
            fatal("Malformed URL excpetion creating converter service");
        } catch (URISyntaxException e) {
            fatal("URI Syntax excpetion creating converter service");
        } catch (IOException e) {
            fatal("IO exception creating converter service");
        } catch (JAXBException e) {
            fatal("JAXB exception creating converter service");
        }
        return null;
    }
}
TOP

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

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.