package org.simantics.simulation.project; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import org.simantics.databoard.Bindings; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.VirtualGraph; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.request.WriteResultRequest; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.service.VirtualGraphSupport; import org.simantics.layer0.Layer0; import org.simantics.scl.runtime.function.Function2; import org.simantics.simulation.experiment.ExperimentState; import org.simantics.simulation.experiment.IExperiment; import org.simantics.simulation.experiment.IExperimentListener; import org.simantics.simulation.ontology.SimulationResource; import org.simantics.utils.ui.ErrorLogger; /** * Facade for handling experiment run modeling and experiment activation * related tasks. * * @author Tuukka Lehtonen */ public class ExperimentRuns { /** * @param session * @param experimentResource * @param experiment * @param listener */ public static void createRun(Session session, Resource experimentResource, IExperiment experiment, IExperimentActivationListener listener, Consumer successCallback) { VirtualGraphSupport support = session.getService(VirtualGraphSupport.class); createRun(session, support.getWorkspacePersistent("experiments"), experimentResource, experiment, listener, successCallback); } /** * Create new experiment run in a selected virtual graph. * * @param session * @param graph * @param experimentResource * @param experiment * @param listener */ public static void createRun(final Session session, VirtualGraph graph, final Resource experimentResource, final IExperiment experiment, final IExperimentActivationListener listener, final Consumer successCallback) { createRun(session, graph, experimentResource, experiment, SimulationResource.URIs.Run, listener, successCallback); } public static void createRun(final Session session, VirtualGraph vg, final Resource experimentResource, final IExperiment experiment, final String experimentRunTypeURI, final IExperimentActivationListener listener, final Consumer successCallback) { createRun(session, vg, experimentResource, experiment, experimentRunTypeURI, listener, null, successCallback); } /** * Create new experiment run in a selected virtual graph. * * @param session * @param vg * @param experimentResource * @param experiment * @param experimentRunTypeURI * @param listener * @param successCallback if non-null invoked with the created run resource * as an argument, just before invoking * listener.onExperimentActivated(experiment) */ public static void createRun(final Session session, VirtualGraph vg, final Resource experimentResource, final IExperiment experiment, final String experimentRunTypeURI, final IExperimentActivationListener listener, final Function2 externalWrite, final Consumer successCallback) { final AtomicReference run = new AtomicReference<>(); session.asyncRequest(new WriteRequest(vg) { @Override public void perform(WriteGraph graph) throws DatabaseException { // System.out.println("ExperimentActivator " + experimentResource + " " + experiment.getIdentifier()); run.set( createRun(graph, experimentResource, experiment, experimentRunTypeURI, externalWrite) ); } }, e -> { if (e != null) { if (listener != null) listener.onFailure(e); else ErrorLogger.defaultLogError(e); } else { attachStateListener(session, experiment, run.get()); if (successCallback != null) successCallback.accept(run.get()); if (listener != null) listener.onExperimentActivated(experiment); } }); } /** * Create new experiment run in a selected virtual graph. * * @param session * @param vg * @param experimentResource * @param experiment * @param experimentRunTypeURI * @param listener * @param successCallback if non-null invoked with the created run resource * as an argument, just before invoking * listener.onExperimentActivated(experiment) */ public static Resource createRun(WriteGraph graph, VirtualGraph vg, Resource experimentResource, IExperiment experiment, String experimentRunTypeURI, Function2 externalWrite) throws DatabaseException { return graph.syncRequest(new WriteResultRequest(vg) { @Override public Resource perform(WriteGraph graph) throws DatabaseException { return createRun(graph, experimentResource, experiment, experimentRunTypeURI, externalWrite); } }); } public static Resource createRun(WriteGraph graph, Resource experimentResource, IExperiment experiment, String experimentRunTypeURI, Function2 externalWrite) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); SimulationResource SIMU = SimulationResource.getInstance(graph); Resource run = graph.newResource(); String label = NameUtils.findFreshLabel(graph, "Experiment", experimentResource); graph.claim(run, L0.InstanceOf, null, graph.getResource(experimentRunTypeURI)); graph.addLiteral(run, L0.HasName, L0.NameOf, L0.String, experiment.getIdentifier(), Bindings.STRING); graph.addLiteral(run, L0.HasLabel, L0.HasLabel_Inverse, L0.String, label, Bindings.STRING); graph.addLiteral(run, SIMU.HasActivationTime, SIMU.HasActivationTime_Inverse, L0.Long, System.currentTimeMillis(), Bindings.LONG); graph.claim(experimentResource, L0.ConsistsOf, L0.PartOf, run); markRunActive(graph, run, externalWrite); return run; } /** * Mark the run active in the transient virtual graph. * * @param graph * @param run * @param externalWrite * @throws DatabaseException */ private static void markRunActive( WriteGraph graph, Resource run, Function2 externalWrite) throws DatabaseException { SimulationResource SIMU = SimulationResource.getInstance(graph); VirtualGraph runtime = graph.getService(VirtualGraph.class); graph.syncRequest(new WriteRequest(runtime) { @Override public void perform(WriteGraph graph) throws DatabaseException { graph.claim(run, SIMU.IsActive, run); if(externalWrite != null) externalWrite.apply(graph, run); } }); } /** * Add listener for tracking run IsActive state in the graph. * * @param session * @param experiment * @param run */ private static void attachStateListener(final Session session, IExperiment experiment, final Resource run) { experiment.addListener(new IExperimentListener() { @Override public void stateChanged(ExperimentState state) { if (state == ExperimentState.DISPOSED) { VirtualGraph runtime = session.getService(VirtualGraph.class); session.asyncRequest(new WriteRequest(runtime) { @Override public void perform(WriteGraph graph) throws DatabaseException { SimulationResource SIMU = SimulationResource.getInstance(graph); graph.denyStatement(run, SIMU.IsActive, run); } }, e -> { if (e != null) ErrorLogger.defaultLogError(e); }); } } }); } }