blob: 7fac068423d0b1f5c434c991664ec426583c0c9d [file] [log] [blame]
// SimulationManager.java
package org.eclipse.stem.analysis.automaticexperiment;
/*******************************************************************************
* Copyright (c) 2006, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.stem.core.graph.Graph;
import org.eclipse.stem.core.graph.GraphFactory;
import org.eclipse.stem.core.model.Model;
import org.eclipse.stem.core.scenario.Scenario;
import org.eclipse.stem.core.scenario.ScenarioInitializationException;
import org.eclipse.stem.core.scenario.ScenarioPackage;
import org.eclipse.stem.core.sequencer.Sequencer;
import org.eclipse.stem.jobs.execution.ExecutableManager;
import org.eclipse.stem.jobs.simulation.ISimulation;
import org.eclipse.stem.jobs.simulation.Messages;
import org.eclipse.stem.jobs.simulation.Simulation;
import org.eclipse.stem.jobs.simulation.SimulationCaching;
import org.eclipse.stem.jobs.simulation.SimulationEvent;
/**
* This class manages the life-cycle of active {@link Simulation}s. There is a
* singleton instance of the manager that is referenced by other parts of the
* system to manage {@link Simulation}. It creates {@link Simulation} instances
* from {@link Scenario} instances and can obtain {@link Scenario} instances
* from file URI's or from {@link IConfigurationElement}'s. It maintains a
* collection of all of the active {@link Simulation}s in the system and
* generates {@link SimulationEvent}'s whenever a {@link Simulation} is added to
* that collection or removed.
* <p>
* The {@link CustomSimulationManager} maintains a sequence number and assigns
* successive values of that number to the {@link Simulation} instances it
* creates.
*/
public class CustomSimulationManager extends ExecutableManager {
/**
* Singleton instance of the manager
*/
private volatile static CustomSimulationManager INSTANCE = null;
/**
* This is the sequence number assigned to each successive
* {@link Simulation} instance the manager creates.
*/
private static int sequenceNumber = 0;
/**
* Constant empty array.
*/
public static final ISimulation[] NONE = new Simulation[] {};
/**
* This is the collection of active {@link Simulation} jobs
*/
private List<ISimulation> activeSimulations = null;
/**
* Constructor
*/
private CustomSimulationManager() {
activeSimulations = new ArrayList<ISimulation>();
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(
ScenarioPackage.eNAME, new XMIResourceFactoryImpl());
} // SimulationManager
/**
* @return the singleton instance of the model
*/
public static final CustomSimulationManager getManager() {
if (INSTANCE == null) {
synchronized (CustomSimulationManager.class) {
if (INSTANCE == null) {
INSTANCE = new CustomSimulationManager();
}
}
}
return INSTANCE;
} // getModel
/**
* Return the next simulation sequence number and increment the value.
*
* @return the next simulation sequence number
*/
synchronized private static final int getAndIncrementSimulationSequenceNumber() {
return sequenceNumber++;
} // getAndIncrementSimulationSequenceNumber
/**
* This is used for testing purposes to reset the state of the model.
*/
public static final void resetSimulationManager() {
INSTANCE = null;
sequenceNumber = 0;
} // resetSimulationManager
/**
* @return the active {@link Simulation}s
*/
public final List<ISimulation> getActiveSimulations() {
return activeSimulations;
} // getActiveSimulations
/**
* Add a {@link Simulation} to the collection of active {@link Simulation}s.
*
* @param simulation
* the {@link ISimulation} to add
*/
private final void addActiveSimulation(final ISimulation simulation) {
activeSimulations.add(simulation);
} // addActiveSimulation
/**
* Remove an {@link ISimulation} from the collection of active
* {@link ISimulation}s.
*
* @param simulation
* the {@link ISimulation} to remove
*/
public final void removeActiveSimulation(final ISimulation simulation) {
activeSimulations.remove(simulation);
} // removeActiveSimulation
/**
* Create a {@link ISimulation} from a {@link Scenario} instance.
*
* @param scenario
* the {@link Scenario} to simulate
* @param monitor
* Progress monitor
* @return a {@link ISimulation} that's ready to run.
*/
public ISimulation createSimulation(final Scenario scenario, final IProgressMonitor monitor) {
ISimulation retValue = null;
try {
boolean useCache = false;
Scenario simulationScenario = null;
if (useCache) {
if (SimulationCaching.INSTANCE.isScenarioInCache(scenario.getURI())) {
simulationScenario = SimulationCaching.INSTANCE.getCachedScenario(scenario.getURI());
boolean running = false;
for(ISimulation sim : getActiveSimulations()) {
if(sim.getScenario().equals(simulationScenario)) {
// The scenario is already running. Copy the whole scenario before resetting
Scenario newSimulation = null;
newSimulation = (Scenario)EcoreUtil.copy(simulationScenario);
if(simulationScenario.getModel() != null) newSimulation.setModel((Model)EcoreUtil.copy(simulationScenario.getModel()));
if(simulationScenario.getSequencer() != null) newSimulation.setSequencer((Sequencer)EcoreUtil.copy(simulationScenario.getSequencer()));
running = true;
break;
}
}
if(!running)simulationScenario.reset(); // safe since canonical graph is set
}
else {
// Read scenario
// Add to cache
SimulationCaching.INSTANCE.addScenarioToCache(scenario);
}
}
if(scenario.getCanonicalGraph() == null)
scenario.initialize(); // needed for preferences ...
else scenario.reset();
final Simulation simulation = new Simulation(scenario,
getAndIncrementSimulationSequenceNumber(), GraphFactory.eINSTANCE.createSimpleGraphPartitioner());
simulation.setPriority(Job.LONG);
retValue = simulation;
addActiveSimulation(retValue);
} catch (final ScenarioInitializationException se) {
// We could get an exception here if the Scenario doesn't have
// a Sequencer or Model which would cause problems when trying to
// initialize
Simulation.handleException(se, true);
retValue = null;
}
return retValue;
} // createSimulation
/**
* Create a {@link ISimulation} from a {@link Scenario} instance and then
* start it running.
*
* @param scenario
* the {@link Scenario} to be simulated
*/
public void createAndRunSimulation(final Scenario scenario) {
new Job(Messages.getString("SimMgr.Start_Sim")) { //$NON-NLS-1$
@Override
protected IStatus run(final IProgressMonitor monitor) {
try {
final ISimulation simulation = createSimulation(scenario, monitor);
monitor.subTask(Messages.getString("SimMgr.Run")); //$NON-NLS-1$
simulation.run();
} catch (final Exception e) {
// The error was logged in createSimulation
monitor.done();
} // catch Exception
return Status.OK_STATUS;
} // run
}.schedule();
} // createAndRunSimulation
/**
* Given a {@link Graph} find the {@link ISimulation} that created it.
*
* @param graph
* an instance of a {@link Graph}
* @return the {@link ISimulation} instance that created the {@link Graph},
* <code>null</code>, if no match could be found.
*/
public ISimulation mapGraphToSimulation(final Graph graph) {
ISimulation retValue = null;
for (final ISimulation simulation : activeSimulations) {
final Graph simulationGraph = simulation.getScenario()
.getCanonicalGraph();
// Is this the one we're looking for?
if (graph == simulationGraph) {
// Yes
retValue = simulation;
break;
} // if
} // for each ISimulation
return retValue;
} // mapGraphToSimulation
} // SimulationManager