package org.jactr.tools.experiment.bootstrap; /* * default logging */ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.function.Consumer; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.core.model.IModel; import org.jactr.core.model.ModelTerminatedException; import org.jactr.core.model.event.ModelEvent; import org.jactr.core.model.event.ModelListenerAdaptor; import org.jactr.core.runtime.ACTRRuntime; import org.jactr.scripting.ScriptingManager; import org.jactr.tools.experiment.IExperiment; import org.jactr.tools.experiment.dc.DataCollector; import org.w3c.dom.Document; import org.xml.sax.SAXException; /** * starts the experiment * * @author harrison */ public class StartModelExperiments implements Runnable { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(StartModelExperiments.class); static public final String CLASS_ATTR = "class"; static public final String CONFIGURATION_FILE = "ConfigurationFile"; static public final String SUBJECT_ID = "SubjectId"; /* * for experiment variable context */ static public final String EXPERIMENT_MODEL = "experiment.model"; /* * for model metadata */ static public final String MODELS_EXPERIMENT = "models.experiment"; public void run() { /* * exposes model's experiment as jactrExperiment */ ScriptingManager.install(new ScriptConfig()); Collection<IExperiment> experiments = new ArrayList<IExperiment>(); /* * we create a separate experiment for each model */ for (IModel model : ACTRRuntime.getRuntime().getModels()) { String subjectId = DataCollector.getSubjectId(model); IExperiment experiment = loadExperiment( System.getProperty(CONFIGURATION_FILE), (ex) -> { /* * always set the subjectId of the experiment */ ex.getVariableContext().set(SUBJECT_ID, subjectId); // provisional clock setting ex.setClock(ACTRRuntime.getRuntime().getClock(model)); ex.getVariableContext().set(EXPERIMENT_MODEL, model); model.setMetaData(MODELS_EXPERIMENT, ex); }); experiment.getVariableResolver().addAlias("actrWorkingDir", ACTRRuntime.getRuntime().getWorkingDirectory().getAbsolutePath()); model.addListener(new ModelListenerAdaptor() { @Override public void modelStarted(ModelEvent me) { // actual clock set experiment.setClock(ACTRRuntime.getRuntime().getClock(model)); } }, null); experiments.add(experiment); } /* * start the experiments */ experiments.forEach((e) -> e.start()); } /** * instantiate and load the experiment from the config file at location * * @param location * @return */ static public IExperiment loadExperiment(String location, Consumer<IExperiment> config) { if (location == null) throw new ModelTerminatedException( "No experiment configuration file found. Cannot continue"); Document document = loadConfiguration(location); String className = document.getDocumentElement().getAttribute(CLASS_ATTR); try { IExperiment experiment = (IExperiment) StartModelExperiments.class .getClassLoader().loadClass(className).newInstance(); if (config != null) config.accept(experiment); experiment.configure(document); return experiment; } catch (InstantiationException e) { throw new IllegalStateException(e); } catch (IllegalAccessException e) { throw new IllegalStateException(e); } catch (ClassNotFoundException e) { throw new IllegalStateException(e); } } static private Document loadConfiguration(String location) { /* * first get the url. we try resource first, then fully resolved, then * relative */ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { DocumentBuilder parser = factory.newDocumentBuilder(); return parser.parse(resolveURL(location).openStream()); } catch (ParserConfigurationException e) { throw new IllegalStateException(e); } catch (SAXException e) { throw new IllegalStateException(e); } catch (IOException e) { throw new IllegalStateException(e); } } static private URL resolveURL(String location) { URL rtn = StartModelExperiments.class.getClassLoader() .getResource(location); if (rtn != null) return rtn; try { return new URL(location); } catch (MalformedURLException e) { if (LOGGER.isDebugEnabled()) LOGGER.debug( location + " is not a url, attempting relative resolution", e); } URI root = new File(System.getProperty("user.dir")).toURI(); try { URI resolved = root.resolve(location); return resolved.toURL(); } catch (Exception e) { if (LOGGER.isDebugEnabled()) LOGGER.debug("Could not resolve " + location + " relative to " + root); } throw new IllegalArgumentException("Could not resolve " + location + " to a valid url. Is org.jactr.tools.experiment an Eclipse-RegisterBuddy? Is location on the classpath?"); } }