/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * 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: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.modeling.utils; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.Job; import org.simantics.DatabaseJob; import org.simantics.Simantics; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.common.procedure.adapter.ListenerAdapter; import org.simantics.db.common.request.ParametrizedRead; import org.simantics.db.common.request.UnaryRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.request.Read; import org.simantics.simulation.experiment.ExperimentState; import org.simantics.simulation.experiment.IExperiment; import org.simantics.simulation.experiment.IExperimentListener; import org.simantics.ui.workbench.editor.input.InputValidationCombinators; import org.simantics.utils.ui.ExceptionUtils; /** * @author Tuukka Lehtonen */ public class ExperimentExistenceWatchdog { public static ExperimentExistenceWatchdog activate(IExperiment experiment, Resource experimentResource) { ExperimentExistenceWatchdog validator = new ExperimentExistenceWatchdog(experiment, experimentResource, InputValidationCombinators.hasURI()); validator.attachExperimentListener(); validator.activateValidation(); return validator; } private Session session; private final Resource experimentResource; private IExperiment experiment; private final ParametrizedRead inputValidator; private InputListener inputListener; private ExperimentExistenceWatchdog(IExperiment experiment, Resource experimentResource, ParametrizedRead inputValidator) { this.session = Simantics.getSession(); this.experiment = experiment; this.experimentResource = experimentResource; this.inputValidator = inputValidator; } private void attachExperimentListener() { experiment.addListener(new IExperimentListener() { @Override public void stateChanged(ExperimentState state) { if (state == ExperimentState.DISPOSED) { if (!isDisposed()) dispose(); } } }); } public void dispose() { deactivateValidation(); experiment = null; session = null; } protected boolean isDisposed() { return session == null || experimentResource == null || experiment == null; } public synchronized void activateValidation() { if (isDisposed()) throw new IllegalStateException(this + " is disposed"); if (inputListener != null) return; inputListener = new InputListener(); session.asyncRequest(validationRequest(), inputListener); } public synchronized void deactivateValidation() { if (isDisposed()) throw new IllegalStateException(this + " is disposed"); if (inputListener == null) return; inputListener.dispose(); inputListener = null; } /** * @param input * @return a read request that returns true for valid inputs * and false for non-existent or invalid inputs. */ private Read validationRequest() { return new UnaryRead(experimentResource) { @Override public Boolean perform(ReadGraph graph) throws DatabaseException { return graph.syncRequest(inputValidator.get(experimentResource)); } }; } private class InputListener extends ListenerAdapter { private boolean disposed = false; public void dispose() { disposed = true; } @Override public void execute(Boolean evaluation) { if (!Boolean.TRUE.equals(evaluation)) { scheduleExperimentShutdown(experiment); } } @Override public void exception(Throwable t) { ExceptionUtils.logError("ResourceEditorSupport.InputListener received an unexpected exception.", t); } @Override public boolean isDisposed() { return disposed || ExperimentExistenceWatchdog.this.isDisposed(); } } private static void scheduleExperimentShutdown(final IExperiment experiment) { Job job = new DatabaseJob("Experiment Shutdown Watchdog") { @Override protected IStatus run(IProgressMonitor monitor) { SubMonitor mon = SubMonitor.convert(monitor, "Shutdown", 100000); try { experiment.shutdown(mon.newChild(100000)); return Status.OK_STATUS; } finally { monitor.done(); } } }; job.schedule(); } }