/******************************************************************************* * 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.simulation.ui.handlers; import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; 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.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.progress.IProgressConstants2; import org.simantics.DatabaseJob; import org.simantics.db.ReadGraph; import org.simantics.db.RequestProcessor; import org.simantics.db.Resource; import org.simantics.db.common.request.UniqueRead; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.AdaptionException; import org.simantics.db.exception.DatabaseException; import org.simantics.message.ILogger; import org.simantics.message.MessageService; import org.simantics.project.IProject; import org.simantics.simulation.Activator; import org.simantics.simulation.experiment.IExperiment; import org.simantics.simulation.model.ExperimentLoadingCancelled; import org.simantics.simulation.model.ExperimentLoadingFailed; import org.simantics.simulation.project.IExperimentActivationListener; import org.simantics.simulation.project.IExperimentManager; import org.simantics.simulation.ui.ExperimentManagerListener; import org.simantics.utils.DataContainer; import org.simantics.utils.ui.ErrorLogger; import org.simantics.utils.ui.workbench.WorkbenchUtils; /** * A utility for performing experiment activation as a {@link Job} in the * background. * * @author Tuukka Lehtonen * * @see ActivateExperimentAction * @see ActivateExperimentHandler */ public class ExperimentActivator { /** * @param project * @param experimentManager * @param experiment */ public static void scheduleActivation(RequestProcessor processor, IProject project, IExperimentManager experimentManager, Resource experiment) { scheduleActivation(processor, project, experimentManager, experiment, null); } /** * @param project * @param experimentManager * @param experiment */ public static void scheduleActivation(RequestProcessor processor, IProject project, IExperimentManager experimentManager, Resource experiment, Consumer callback) { String jobName = "Activate Experiment"; String experimentName = getName(processor, experiment); if (experimentName != null) jobName += " '" + experimentName + "'"; scheduleActivation(jobName, project, experimentManager, experiment, callback); } static class ExperimentActivationJob extends DatabaseJob { private IProject project; private IExperimentManager experimentManager; private Resource experiment; private Consumer callback; public ExperimentActivationJob(String name, IProject project, IExperimentManager experimentManager, Resource experiment, Consumer callback) { super(name); this.project = project; this.experimentManager = experimentManager; this.experiment = experiment; this.callback = callback; } @Override protected IStatus run(IProgressMonitor monitor) { try { return ExperimentActivator.activate(monitor, project, experimentManager, experiment, callback); } finally { monitor.done(); // Aid GC project = null; experimentManager = null; experiment = null; } } } /** * @param project * @param experimentManager * @param experiment */ public static void scheduleActivation(String jobName, IProject project, IExperimentManager experimentManager, Resource experiment) { scheduleActivation(jobName, project, experimentManager, experiment, null); } /** * @param project * @param experimentManager * @param experiment */ public static void scheduleActivation(String jobName, IProject project, IExperimentManager experimentManager, Resource experiment, Consumer callback) { Job job = new ExperimentActivationJob(jobName, project, experimentManager, experiment, callback); job.setProperty(IProgressConstants2.SHOW_IN_TASKBAR_ICON_PROPERTY, Boolean.TRUE); job.setUser(true); job.schedule(); } public static IStatus activate(IProgressMonitor monitor, IProject project, IExperimentManager experimentManager, Resource experiment) { return activate(monitor, project, experimentManager, experiment, null); } public static IStatus activate(IProgressMonitor monitor, IProject project, IExperimentManager experimentManager, Resource experiment, Consumer callback) { return new ExperimentActivator().activateExperiment(monitor, project, experimentManager, experiment, callback); } private static String getName(RequestProcessor processor, final Resource resource) { try { return processor.syncRequest(new UniqueRead() { @Override public String perform(ReadGraph graph) throws DatabaseException { try { return graph.adapt(resource, String.class); } catch (AdaptionException e) { return NameUtils.getSafeName(graph, resource); } } }); } catch (DatabaseException e) { ErrorLogger.defaultLogWarning(e); return null; } } private IStatus activateExperiment(IProgressMonitor monitor, IProject project, IExperimentManager manager, final Resource experimentResource, Consumer callback) { final SubMonitor mon = SubMonitor.convert(monitor, "Activating experiment", 100000); ExperimentManagerListener.listenManager(manager); final Semaphore activated = new Semaphore(0); final DataContainer activatedExperiment = new DataContainer<>(); final DataContainer problem = new DataContainer<>(); final AtomicInteger worstMessageSeverity = new AtomicInteger(IStatus.OK); final ILogger messageService = MessageService.getDefault(); manager.startExperiment(experimentResource, new IExperimentActivationListener() { @Override public void onExperimentActivated(final IExperiment experiment) { MessageService.defaultLog(new org.eclipse.core.runtime.Status(IStatus.INFO, "org.simantics.simulation.ui", 0, "Activated experiment " + experiment.getIdentifier() , null)); activatedExperiment.set(experiment); activated.release(); } @Override public void onFailure(Throwable e) { problem.set(e); activated.release(); } @Override public void onMessage(IStatus message) { messageService.log(message); int s = message.getSeverity(); if (s > worstMessageSeverity.get()) worstMessageSeverity.set(s); } @Override public IProgressMonitor getProgressMonitor() { return mon; } }, true); try { activated.acquire(); Throwable t = problem.get(); IStatus status = null; if (t != null) { if (t instanceof ExperimentLoadingFailed) { ExperimentLoadingFailed ex = (ExperimentLoadingFailed) t; if (t instanceof ExperimentLoadingCancelled) { status = Status.CANCEL_STATUS; } else { // Make sure that the error window gets correct parent // shell, i.e. the workbench window shell, not the job // progress window shell. Activator.logError("Experiment activation failed, see exception for details.", t); if (PlatformUI.isWorkbenchRunning()) PlatformUI.getWorkbench().getDisplay().asyncExec(showError("Experiment Activation Failed", t.getMessage() + "\n\nSee Error Log for details.")); } if (ex.getHelperAction() != null && PlatformUI.isWorkbenchRunning()) PlatformUI.getWorkbench().getDisplay().asyncExec(ex.getHelperAction()); } else { Activator.logError("Experiment activation failed, see exception for details.", t); if (PlatformUI.isWorkbenchRunning()) PlatformUI.getWorkbench().getDisplay().asyncExec(showError("Experiment Activation Failed", t.getMessage() + "\n\nSee Error Log for details.")); } } // if (worstMessageSeverity.get() > IStatus.OK) { // SWTUtils.asyncExec(PlatformUI.getWorkbench().getDisplay(), new Runnable() { // @Override // public void run() { // try { // WorkbenchUtils.activateView("org.simantics.message.view"); // } catch (PartInitException ex) { // ExceptionUtils.logError(ex); // } // } // }); // } if (callback != null) callback.accept(activatedExperiment.get()); return status != null ? status : Status.OK_STATUS; } catch (InterruptedException e) { return Status.CANCEL_STATUS; } } private Runnable showError(String title, String message) { return new Runnable() { @Override public void run() { Shell parent = WorkbenchUtils.getActiveWorkbenchWindowShell(); MessageDialog.openError(parent, title, message); } }; } }