content: /*
   * Copyright 2010 Aalto University, ComNet
   * Released under GPLv3. See LICENSE.txt for details.
   */
  package ui;
  
  import java.util.Vector;
  
  import report.Report;
  import core.ApplicationListener;
  import core.ConnectionListener;
  import core.MessageListener;
  import core.MovementListener;
  import core.Settings;
  import core.SettingsError;
  import core.SimClock;
  import core.SimError;
  import core.SimScenario;
  import core.UpdateListener;
  import core.World;
  
  /**
   * Abstract superclass for user interfaces; contains also some simulation
   * settings.
   */
  public abstract class DTNSimUI {
  	/**
  	 * Number of reports -setting id ({@value}). Defines how many reports
  	 * are loaded.
  	 */
  	public static final String NROF_REPORT_S = "Report.nrofReports";
  	/**
  	 * Report class name -setting id prefix ({@value}). Defines name(s) of
  	 * the report classes to load. Must be suffixed with numbers starting from
  	 * one.
  	 */
  	public static final String REPORT_S = "Report.report";
  	/**
  	 * Movement model warmup time -setting id ({@value}). Defines how many
  	 * seconds of movement simulation is run without connectivity etc. checks
  	 * before starting the real simulation.
  	 */
  	public static final String MM_WARMUP_S =
  		movement.MovementModel.MOVEMENT_MODEL_NS + ".warmup";
  
  	/** report class' package name */
  	private static final String REPORT_PAC = "report.";
  
  	/** The World where all actors of the simulator are */
  	protected World world;
  	/** Reports that are loaded for this simulation */
  	protected Vector<Report> reports;
  	/** has simulation terminated normally */
  	protected boolean simDone;
  	/** is simulation termination requested */
  	protected boolean simCancelled;
  	/** Scenario of the current simulation */
  	protected SimScenario scen;
  	/** simtime of last UI update */
  	protected double lastUpdate;
  
  	/**
  	 * Constructor.
  	 */
  	public DTNSimUI() {
  		this.lastUpdate = 0;
  		this.reports = new Vector<Report>();
  		this.simDone = false;
  		this.simCancelled = false;
  	}
  
  	/**
  	 * Starts the simulation.
  	 */
  	public void start() {
  		initModel();
  		runSim();
  	}
  
  	/**
  	 * Runs simulation after the model has been initialized.
  	 */
  	protected abstract void runSim();
  
  	/**
  	 * Initializes the simulator model.
  	 */
  	private void initModel() {
  		Settings settings = null;
  
  		try {
  			settings = new Settings();
  			
  			// set time before instantiate scenario
  			double warmupTime = 0;
  			if (settings.contains(MM_WARMUP_S)) {
  				warmupTime = settings.getDouble(MM_WARMUP_S);
  				if (warmupTime > 0) {
  					SimClock c = SimClock.getInstance();
  					c.setTime(-warmupTime);
  				}
  			}
  			
  			this.scen = SimScenario.getInstance();
  
  			// add reports
  			for (int i=1, n = settings.getInt(NROF_REPORT_S); i<=n; i++){
  				String reportClass = settings.getSetting(REPORT_S + i);
  				addReport((Report)settings.createObject(REPORT_PAC +
  						reportClass));
  			}
  
  			this.world = this.scen.getWorld();
  			world.warmupMovementModel(warmupTime);
  		}
  		catch (SettingsError se) {
  			System.err.println("Can't start: error in configuration file(s)");
  			System.err.println(se.getMessage());
  			System.exit(-1);
  		}
  		catch (SimError er) {
  			System.err.println("Can't start: " + er.getMessage());
  			System.err.println("Caught at " + er.getStackTrace()[0]);
  			System.exit(-1);
  		}
  	}
  
  	/**
  	 * Runs maintenance jobs that are needed before exiting.
  	 */
  	public void done() {
  		for (Report r : this.reports) {
  			r.done();
  		}
  	}
  
  	/**
  	 * Adds a new report for simulator
  	 * @param r Report to add
  	 */
  	protected void addReport(Report r) {
  		if (r instanceof MessageListener) {
  			scen.addMessageListener((MessageListener)r);
  		}
  		if (r instanceof ConnectionListener) {
  			scen.addConnectionListener((ConnectionListener)r);
  		}
  		if (r instanceof MovementListener) {
  			scen.addMovementListener((MovementListener)r);
  		}
  		if (r instanceof UpdateListener) {
  			scen.addUpdateListener((UpdateListener)r);
  		}
  		if (r instanceof ApplicationListener) {
  			scen.addApplicationListener((ApplicationListener)r);
  		}
  
  		this.reports.add(r);
  	}
  }
  