package org.jactr.embed;
/*
* default logging
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Supplier;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jactr.core.model.IModel;
import org.jactr.core.reality.connector.IConnector;
import org.jactr.core.runtime.ACTRRuntime;
import org.jactr.core.runtime.controller.DefaultController;
import org.jactr.core.runtime.controller.IController;
import org.jactr.core.runtime.controller.debug.DebugController;
import org.jactr.io.parser.ModelParserFactory;
import org.jactr.io.participant.ASTParticipantRegistry;
import org.jactr.scripting.ScriptingManager;
/**
* The start of a runtime builder to better support embedding. If running
* outside of the Eclipse environment and are using externally contributed
* modules, you must ensure that classpaths are accessible. This is not
* reusable, and assumes no one else is attempting to conifugre the runtime
*
* @author harrison
*/
public class RuntimeBuilder
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(RuntimeBuilder.class);
private Collection<Runnable> _parserInitializers;
private Collection<Runnable> _astInitializers;
private Collection<Runnable> _scriptInitializers;
private Supplier<Object> _applicationDataSupplier;
private Collection<IModel> _models;
private IConnector _connector;
static public RuntimeBuilder newBuilder()
{
return new RuntimeBuilder();
}
protected RuntimeBuilder()
{
_parserInitializers = new ArrayList<Runnable>();
_astInitializers = new ArrayList<Runnable>();
_scriptInitializers = new ArrayList<Runnable>();
_models = new ArrayList<IModel>();
}
/**
* add the model to the runtime to be built. This model must have all it's
* instruments installed already.
*
* @param model
* @return
*/
public RuntimeBuilder addModel(IModel model)
{
_models.add(model);
return this;
}
/**
* If you need to add access to custom model parsers, it can be contributed at
* this point. Accessible via the {@link ModelParserFactory} singleton
*
* @param initializer
* @return
*/
public RuntimeBuilder addParserInitializer(Runnable initializer)
{
_parserInitializers.add(initializer);
return this;
}
/**
* If you need to add access to custome ast participants (used by modules &
* extensions), it is contributed here. Accesible via the
* {@link ASTParticipantRegistry} singelton
*
* @param intializer
* @return
*/
public RuntimeBuilder addASTInitializer(Runnable intializer)
{
_astInitializers.add(intializer);
return this;
}
/**
* If you need to add access to custom scripting support. Accessible via the
* {@link ScriptingManager} singleton
*
* @param initializer
* @return
*/
public RuntimeBuilder addScriptInitializer(Runnable initializer)
{
_scriptInitializers.add(initializer);
return this;
}
public RuntimeBuilder setApplicationData(Supplier<Object> supplier)
{
_applicationDataSupplier = supplier;
return this;
}
/**
* @param connector
* @return
*/
public RuntimeBuilder with(IConnector connector)
{
_connector = connector;
return this;
}
/**
* Terminal build operator that will construct and configure the runtime. It
* returns the controller that should be used to manage the runtime.
*
* @return
*/
public IController build()
{
buildInternal();
return defaultController();
}
/**
* Alternatitve terminal build operator that constructs the runtime, returning
* a debug controller for finer grained runtime control.
*
* @return
*/
public IController debugBuild()
{
buildInternal();
return debugController();
}
protected DefaultController defaultController()
{
ACTRRuntime runtime = ACTRRuntime.getRuntime();
DefaultController controller = new DefaultController();
runtime.setController(controller);
return controller;
}
protected DebugController debugController()
{
ACTRRuntime runtime = ACTRRuntime.getRuntime();
DebugController controller = new DebugController();
runtime.setController(controller);
return controller;
}
protected void buildInternal()
{
resetRuntime();
bootstrap();
initialize();
}
protected void resetRuntime()
{
ACTRRuntime runtime = ACTRRuntime.getRuntime();
IController controller = runtime.getController();
if (controller != null)
{
if (controller.isRunning()) try
{
controller.terminate().get();
}
catch (Exception e)
{
LOGGER.error("Failed to terminate runtime, forcing forward ", e);
}
runtime.setController(null);
}
runtime.setConnector(null);
/*
* zero our application data
*/
runtime.setApplicationData(null);
Collection<IModel> models = runtime.getModels();
// cleanup any existing models
models.forEach((m) -> {
runtime.removeModel(m);
m.dispose();
});
}
protected void bootstrap()
{
/*
* TODO defensive exception handling
*/
for (Runnable init : _scriptInitializers)
init.run();
for (Runnable init : _astInitializers)
init.run();
for (Runnable init : _parserInitializers)
init.run();
if (_applicationDataSupplier != null)
ACTRRuntime.getRuntime().setApplicationData(
_applicationDataSupplier.get());
}
protected void initialize()
{
ACTRRuntime runtime = ACTRRuntime.getRuntime();
runtime.setConnector(_connector);
for (IModel model : _models)
runtime.addModel(model);
}
}