ca.uqac.info.trace.generation.TraceGenerator.java Source code

Java tutorial

Introduction

Here is the source code for ca.uqac.info.trace.generation.TraceGenerator.java

Source

/******************************************************************************
  Event trace generator
  Copyright (C) 2012 Sylvain Halle
    
  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.
    
  This program 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 General Public License for more details.
    
  You should have received a copy of the GNU Lesser General Public License along
  with this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 ******************************************************************************/
package ca.uqac.info.trace.generation;

import java.util.Random;

import ca.uqac.info.trace.EventTrace;
import ca.uqac.info.trace.conversion.Translator;
import ca.uqac.info.trace.conversion.XmlTranslator;
import org.apache.commons.cli.*;

/**
 * The TraceGenerator defines the basic methods one can use to produce
 * event traces of various kinds. It also provides functionality to
 * read command-line arguments, produce an output trace and initialize
 * a random number generator.
 * @author Sylvain Hall
 *
 */
public abstract class TraceGenerator {

    /**
     * Intervals for all the aforementioned parameters
     */
    protected int m_minMessages = 1;
    protected int m_maxMessages = 10;

    /**
     * The seed used to initialize the generator
     */
    protected long m_seed = 0;

    /**
     * The random number generator
     */
    protected Random m_random;

    /**
     * Whether to use the system clock as the seed
     */
    protected boolean m_clockAsSeed = false;

    /**
     * Generator's level of verbosity; defaults to 0 (that is,
     * don't display any message apart from the output trace)
     */
    protected int m_verboseLevel = 0;

    /**
     * Generate an event trace. There are no basic assumptions on that
     * trace: it may be the same on every call to generate, or different.
     * It is up to each trace generator to determine the appropriate
     * behaviour for this method.
     * @return The EventTrace produced by the generator
     */
    public abstract EventTrace generate();

    /**
     * Initializes the generator, taking its input parameters from the
     * parsed command line
     * @param c_line An instance of the parsed CommandLine, which can
     * be queried for values gathered from the user 
     */
    public void initialize(CommandLine c_line) {
        if (c_line.hasOption("t"))
            m_clockAsSeed = true;
        if (c_line.hasOption("s"))
            setSeed(new Integer(c_line.getOptionValue("s")).intValue());
        if (c_line.hasOption("n")) {
            m_minMessages = new Integer(c_line.getOptionValue("n")).intValue();
            if (m_minMessages > m_maxMessages)
                m_maxMessages = m_minMessages + 1;
        }
        if (c_line.hasOption("N")) {
            m_maxMessages = new Integer(c_line.getOptionValue("N")).intValue();
            if (m_maxMessages < m_minMessages)
                m_minMessages = Math.max(0, m_maxMessages - 1);
        }
        if (c_line.hasOption("verbose"))
            m_verboseLevel = Integer.parseInt(c_line.getOptionValue("verbose"));
    }

    /**
     * Sets the seed used by the internal random number generator.
     * Starting from the same seed and the same input parameters, successive
     * calls to generate will always generate the same sequence of
     * output traces.
     * @param s
     */
    public void setSeed(long s) {
        m_seed = s;
        m_random.setSeed(s);
    }

    /**
     * Returns an identifying string used by the command-line application
     * to designate the trace generator
     * @return The name
     */
    public abstract String getAppName();

    /**
     * Creates the proper command line options to gather parameters
     * relevant to the configuration of the trace generator. This
     * method must be implemented by all trace generators, in order
     * for them to declare their command line switches.
     * @return The Options object containing the options required by
     * this generator
     */
    @SuppressWarnings("static-access")
    public Options getCommandLineOptions() {
        Options options = new Options();
        Option opt;
        options.addOption("t", false, "Use system clock as random generator's seed (default: no)");
        opt = OptionBuilder.withArgName("x").hasArg()
                .withDescription("Set random generator's seed to x (default: 0)").create("s");
        options.addOption(opt);
        opt = OptionBuilder.withArgName("x").hasArg()
                .withDescription("Maximum number of messages to produce (default: 10)").create("N");
        options.addOption(opt);
        opt = OptionBuilder.withArgName("x").hasArg()
                .withDescription("Minimum number of messages to produce (default: 1)").create("n");
        options.addOption(opt);
        opt = OptionBuilder.withArgName("x").hasArg()
                .withDescription("Maximum number of tags to produce (default: 1)").create("M");
        options.addOption(opt);
        opt = OptionBuilder.withArgName("x").hasArg()
                .withDescription("Set verbosity level to x (default: 0 = no messages)").withLongOpt("verbose")
                .create();
        options.addOption(opt);
        return options;
    }

    /**
     * Main processing loop for generating traces.
     * @param args
     * @param t_gen
     */
    public static final void process(String[] args, TraceGenerator t_gen) {
        Options options = t_gen.getCommandLineOptions();
        options.addOption("h", "help", false, "Show help");
        CommandLineParser parser = new PosixParser();
        CommandLine c_line = null;
        try {
            // parse the command line arguments
            c_line = parser.parse(options, args);
        } catch (ParseException exp) {
            // oops, something went wrong
            System.err.println("ERROR: " + exp.getMessage() + "\n");
            HelpFormatter hf = new HelpFormatter();
            hf.printHelp(t_gen.getAppName() + " [options]", options);
            System.exit(1);
        }
        assert c_line != null;
        if (c_line.hasOption("h")) {
            HelpFormatter hf = new HelpFormatter();
            hf.printHelp(t_gen.getAppName() + " [options]", options);
            System.exit(1);
        }
        t_gen.initialize(c_line);
        EventTrace trace = t_gen.generate();
        Translator trans = new XmlTranslator();
        trans.setTrace(trace);
        System.out.println(trans.translateTrace());
    }

    /**
     * Overrides Random's {@link Random.nextInt} to add the corner case where
     * the range is 0
     * @param val
     * @return
     */
    protected int nextInt(int val) {
        if (val == 0)
            return 0;
        return m_random.nextInt(val);
    }
}