Package org.openbel.framework.tools

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

/**
* 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 java.lang.System.currentTimeMillis;
import static org.openbel.framework.common.BELUtilities.asPath;
import static org.openbel.framework.common.BELUtilities.sizedArrayList;
import static org.openbel.framework.common.PathConstants.PROTO_NETWORK_FILENAME;
import static org.openbel.framework.common.Strings.NOT_A_PHASE1_DIR;
import static org.openbel.framework.common.Strings.NO_PROTO_NETWORKS;
import static org.openbel.framework.common.Strings.PHASE2_STAGE1_HDR;
import static org.openbel.framework.common.Strings.PHASE2_STAGE2_HDR;
import static org.openbel.framework.common.Strings.PHASE2_STAGE3_HDR;
import static org.openbel.framework.common.Strings.PHASE2_STAGE4_HDR;
import static org.openbel.framework.common.cfg.SystemConfiguration.getSystemConfiguration;
import static org.openbel.framework.tools.PhaseTwoOptions.phaseTwoOptions;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.xml.stream.XMLStreamException;

import org.apache.commons.cli.Option;
import org.openbel.framework.common.cfg.SystemConfiguration;
import org.openbel.framework.common.index.ResourceIndex;
import org.openbel.framework.common.model.EquivalenceDataIndex;
import org.openbel.framework.common.protonetwork.model.ProtoNetwork;
import org.openbel.framework.common.protonetwork.model.ProtoNetworkError;
import org.openbel.framework.common.util.BELPathFilters.ProtonetworkFilter;
import org.openbel.framework.compiler.DefaultPhaseTwo;
import org.openbel.framework.compiler.PhaseTwoImpl;
import org.openbel.framework.core.df.cache.CacheableResourceService;
import org.openbel.framework.core.df.cache.DefaultCacheableResourceService;
import org.openbel.framework.core.df.cache.ResolvedResource;
import org.openbel.framework.core.df.cache.ResourceType;
import org.openbel.framework.core.equivalence.EquivalenceIndexerService;
import org.openbel.framework.core.equivalence.EquivalenceIndexerServiceImpl;
import org.openbel.framework.core.equivalence.EquivalenceMapResolutionFailure;
import org.openbel.framework.core.protocol.ResourceDownloadError;
import org.openbel.framework.core.protonetwork.BinaryProtoNetworkDescriptor;
import org.openbel.framework.core.protonetwork.ProtoNetworkDescriptor;
import org.openbel.framework.core.protonetwork.ProtoNetworkService;
import org.openbel.framework.core.protonetwork.ProtoNetworkServiceImpl;
import org.openbel.framework.core.protonetwork.TextProtoNetworkExternalizer;

/**
* BEL phase two compiler.
*/
public final class PhaseTwoApplication extends PhaseApplication {
    private final DefaultPhaseTwo p2;
    private final CacheableResourceService cache;
    private final SystemConfiguration syscfg;

    /** Phase two artifact directory. */
    public final static String DIR_ARTIFACT = "phaseII";

    private final static String NUM_PHASES = "4";

    /**
     * Phase two application constructor.
     *
     * @param args Command-line arguments
     */
    public PhaseTwoApplication(String[] args) {
        super(args);

        syscfg = getSystemConfiguration();
        cache = new DefaultCacheableResourceService();

        final ProtoNetworkService protonetService =
                new ProtoNetworkServiceImpl();
        final EquivalenceIndexerService indexer =
                new EquivalenceIndexerServiceImpl();
        final PhaseTwoImpl phaseTwo =
                new PhaseTwoImpl(cache, indexer, protonetService);
        phaseTwo.setReportable(getReportable());

        p2 = phaseTwo;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void start() {
        super.start();

        // load the resource index for phase II use.
        String resIdxURL = syscfg.getResourceIndexURL();
        try {
            final ResolvedResource resolvedResource = cache.resolveResource(
                    ResourceType.RESOURCE_INDEX, resIdxURL);
            ResourceIndex.INSTANCE.loadIndex(resolvedResource
                    .getCacheResourceCopy());
        } catch (ResourceDownloadError e) {
            stageError(e.getUserFacingMessage());
            ResourceIndex.INSTANCE.loadIndex();
        } catch (FileNotFoundException e) {
            defaultIndex();
        } catch (XMLStreamException e) {
            defaultIndex();
        }

        processOutputDirectory();
    }

    private void defaultIndex() {
        stageError("Could not read resource index file.  Equivalencing will be "
                + "disabled.");
        ResourceIndex.INSTANCE.loadIndex();
    }

    /**
     * Processes the output directory.
     */
    private void processOutputDirectory() {
        final String root = outputDirectory.getAbsolutePath();
        final String leaf = PhaseOneApplication.DIR_ARTIFACT;
        final String path = asPath(root, leaf);
        final File phaseIPath = new File(path);

        // Fail if the working path doesn't contain a phase I artifact
        if (!phaseIPath.isDirectory()) {
            error(NOT_A_PHASE1_DIR + ": " + phaseIPath);
            failUsage();
        }

        // Fail if the working path doesn't contain any proto-networks
        final File[] networks = phaseIPath.listFiles(new ProtonetworkFilter());
        if (networks.length == 0) {
            error(NO_PROTO_NETWORKS + " found in " + phaseIPath);
            failUsage();
        }

        // Create the directory artifact or fail
        artifactPath = createDirectoryArtifact(outputDirectory, DIR_ARTIFACT);

        processDirectories(networks);
    }

    /**
     * Starts phase two compilation of proto-networks.
     *
     * @param networks
     */
    private void processDirectories(final File[] networks) {
        phaseOutput(format("=== %s ===", getApplicationName()));

        ProtoNetwork network = stage1(networks);
        Set<EquivalenceDataIndex> eqs = stage2();

        if (!eqs.isEmpty()) {
            network = stage3(network, eqs);
        }
        stage4(network);
    }

    /**
     * Stage one merger of networks, returning the merged proto-network.
     *
     * @param networks Proto-networks
     * @return {@link ProtoNetwork}
     */
    private ProtoNetwork stage1(final File[] networks) {
        beginStage(PHASE2_STAGE1_HDR, "1", NUM_PHASES);
        final int netct = networks.length;

        final StringBuilder bldr = new StringBuilder();
        bldr.append("Merging ");
        bldr.append(netct);
        bldr.append(" network");
        if (netct > 1) {
            bldr.append("s");
        }
        stageOutput(bldr.toString());

        long t1 = currentTimeMillis();
        Collection<ProtoNetworkDescriptor> nds = sizedArrayList(netct);
        for (final File network : networks) {
            final String root = network.getAbsolutePath();
            final String netPath = asPath(root, PROTO_NETWORK_FILENAME);
            final File networkBin = new File(netPath);
            nds.add(new BinaryProtoNetworkDescriptor(networkBin));
        }

        ProtoNetwork ret = p2.stage1Merger(nds);

        new File(artifactPath.getAbsolutePath() + "/merged").mkdirs();

        p2.stage4WriteEquivalentProtoNetwork(ret,
                artifactPath.getAbsolutePath() + "/merged");

        if (withDebug()) {
            try {
                TextProtoNetworkExternalizer textExternalizer =
                        new TextProtoNetworkExternalizer();
                textExternalizer.writeProtoNetwork(ret,
                        artifactPath.getAbsolutePath() + "/merged");
            } catch (ProtoNetworkError e) {
                error("Could not write out equivalenced proto network.");
            }
        }

        long t2 = currentTimeMillis();

        bldr.setLength(0);
        markTime(bldr, t1, t2);
        markEndStage(bldr);
        stageOutput(bldr.toString());
        return ret;
    }

    /**
     * Stage two equivalence loading, returning a set of data indices.
     *
     * @param equivalenceFile Equivalence file
     * @return Set of equivalence data indices
     */
    private Set<EquivalenceDataIndex> stage2() {
        beginStage(PHASE2_STAGE2_HDR, "2", NUM_PHASES);

        Set<EquivalenceDataIndex> ret = new HashSet<EquivalenceDataIndex>();

        final StringBuilder bldr = new StringBuilder();
        bldr.append("Loading namespace equivalences from resource index");
        stageOutput(bldr.toString());

        long t1 = currentTimeMillis();
        try {
            ret.addAll(p2.stage2LoadNamespaceEquivalences());
        } catch (EquivalenceMapResolutionFailure e) {
            warning(e.getUserFacingMessage());
            // continue with an empty equivalence data index set
        }

        for (final EquivalenceDataIndex edi : ret) {
            final String nsLocation = edi.getNamespaceResourceLocation();
            bldr.setLength(0);
            bldr.append("Equivalence for ");
            bldr.append(nsLocation);
            stageOutput(bldr.toString());
        }
        long t2 = currentTimeMillis();
        bldr.setLength(0);
        markTime(bldr, t1, t2);
        markEndStage(bldr);
        stageOutput(bldr.toString());
        return ret;
    }

    /**
     * Stage three equivalencing, returning the equivalenced proto-network.
     * If parameter equivalencing yields a {@code 0} count then term and
     * statement equivalencing is not run.
     *
     * @param network Merged proto-network
     * @param equivalences Equivalence data indices
     * @return {@link ProtoNetwork}
     */
    private ProtoNetwork stage3(final ProtoNetwork network,
            Set<EquivalenceDataIndex> equivalences) {
        beginStage(PHASE2_STAGE3_HDR, "3", NUM_PHASES);
        final StringBuilder bldr = new StringBuilder();
        long t1 = currentTimeMillis();

        int pct = stage3Parameter(network, equivalences, bldr);
        stage3Term(network, pct);
        stage3Statement(network, pct);

        long t2 = currentTimeMillis();

        final int paramct =
                network.getParameterTable().getTableParameters().size();
        final int termct = network.getTermTable().getTermValues().size();
        final int stmtct = network.getStatementTable().getStatements().size();

        bldr.setLength(0);
        bldr.append(stmtct);
        bldr.append(" statements, ");
        bldr.append(termct);
        bldr.append(" terms, ");
        bldr.append(paramct);
        bldr.append(" parameters");
        stageOutput(bldr.toString());

        bldr.setLength(0);
        markTime(bldr, t1, t2);
        markEndStage(bldr);
        stageOutput(bldr.toString());
        return network;
    }

    /**
     * Stage three parameter equivalencing.
     *
     * @param network the {@link ProtoNetwork network} to equivalence
     * @param equivalences the {@link Set set} of {@link EquivalenceDataIndex}
     * @param bldr the {@link StringBuilder}
     * @return the {@code int} count of parameter equivalences
     */
    private int stage3Parameter(final ProtoNetwork network,
            Set<EquivalenceDataIndex> equivalences, final StringBuilder bldr) {
        bldr.append("Equivalencing parameters");
        stageOutput(bldr.toString());
        ProtoNetwork ret = network;
        int ct = 0;
        try {
            ct = p2.stage3EquivalenceParameters(ret, equivalences);
            stageOutput("(" + ct + " equivalences)");
        } catch (IOException ioex) {
            final String err = ioex.getMessage();
            fatal(err);
        }

        return ct;
    }

    /**
     * Stage three term equivalencing.
     *
     * @param network the {@link ProtoNetwork network} to equivalence
     * @param pct the parameter equivalencing count to control output
     */
    private void stage3Term(final ProtoNetwork network, int pct) {
        stageOutput("Equivalencing terms");
        int tct = p2.stage3EquivalenceTerms(network);
        stageOutput("(" + tct + " equivalences)");
    }

    /**
     * Stage three statement equivalencing.
     *
     * @param network the {@link ProtoNetwork network} to equivalence
     * @param pct the parameter equivalencing count to control output
     */
    private void stage3Statement(final ProtoNetwork network, int pct) {
        stageOutput("Equivalencing statements");
        int sct = p2.stage3EquivalenceStatements(network);
        stageOutput("(" + sct + " equivalences)");
    }

    /**
     * Stage four saving
     *
     * @param eqNetwork
     * @return
     */
    private ProtoNetworkDescriptor stage4(final ProtoNetwork eqNetwork) {
        beginStage(PHASE2_STAGE4_HDR, "4", NUM_PHASES);
        final StringBuilder bldr = new StringBuilder();
        bldr.append("Saving network");
        stageOutput(bldr.toString());

        long t1 = currentTimeMillis();
        ProtoNetworkDescriptor ret =
                p2.stage4WriteEquivalentProtoNetwork(eqNetwork,
                        artifactPath.getAbsolutePath());

        if (withDebug()) {
            try {
                TextProtoNetworkExternalizer textExternalizer =
                        new TextProtoNetworkExternalizer();
                textExternalizer.writeProtoNetwork(eqNetwork,
                        artifactPath.getAbsolutePath());
            } catch (ProtoNetworkError e) {
                error("Could not write out equivalenced proto network.");
            }
        }

        bldr.setLength(0);
        long t2 = currentTimeMillis();
        markTime(bldr, t1, t2);
        markEndStage(bldr);
        stageOutput(bldr.toString());
        return ret;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public PhaseTwoOptions getPhaseConfiguration() {
        return phaseTwoOptions();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean validCommandLine() {
        // We only need output from phase one. Any command-line is valid.
        return true;
    }

    /**
     * Returns {@code "Phase II: Merging proto-networks"}.
     *
     * @return String
     */
    @Override
    public String getApplicationName() {
        return "Phase II: Merging proto-networks";
    }

    /**
     * Returns {@code "Phase II"}.
     *
     * @return String
     */
    @Override
    public String getApplicationShortName() {
        return "Phase II";
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public List<Option> getCommandLineOptions() {
        return super.getCommandLineOptions();
    }

    /**
     * Returns the application's description.
     *
     * @return String
     */
    @Override
    public String getApplicationDescription() {
        final StringBuilder bldr = new StringBuilder();
        bldr.append("Merges proto-networks into a composite network and ");
        bldr.append("equivalences term references across namespaces.");
        return bldr.toString();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getUsage() {
        StringBuilder bldr = new StringBuilder();
        bldr.append("[OPTION]...");
        return bldr.toString();
    }

    /**
     * Invokes {@link #harness(PhaseApplication)} for
     * {@link PhaseTwoApplication}.
     *
     * @param args Command-line arguments
     */
    public static void main(String[] args) {
        harness(new PhaseTwoApplication(args));
    }

    /**
     * {@inheritDoc}
     */
    public static String getRequiredArguments() {
        // Nothing is required
        return "";
    }
}
TOP

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

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.