All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nl.tudelft.goal.SimpleIDE.actions.RunAction Maven / Gradle / Ivy

The newest version!
/**
 * GOAL interpreter that facilitates developing and executing GOAL multi-agent
 * programs. Copyright (C) 2011 K.V. Hindriks, W. Pasman
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see .
 */

package nl.tudelft.goal.SimpleIDE.actions;

import java.awt.event.ActionEvent;
import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.JOptionPane;
import javax.swing.tree.TreeNode;

import goal.core.agent.Agent;
import goal.core.runtime.RuntimeEvent;
import goal.core.runtime.RuntimeEvent.EventType;
import goal.core.runtime.RuntimeEventObserver;
import goal.core.runtime.RuntimeManager;
import goal.tools.DebugRun;
import goal.tools.IDEGOALInterpreter;
import goal.tools.debugger.IDEDebugger;
import goal.tools.debugger.SteppingDebugger.RunMode;
import goal.tools.errorhandling.Resources;
import goal.tools.errorhandling.Warning;
import goal.tools.errorhandling.WarningStrings;
import goal.tools.errorhandling.exceptions.GOALException;
import goal.tools.errorhandling.exceptions.GOALRunFailedException;
import languageTools.program.mas.AgentDefinition;
import languageTools.program.mas.MASProgram;
import nl.tudelft.goal.SimpleIDE.EditManager;
import nl.tudelft.goal.SimpleIDE.IDEMainPanel;
import nl.tudelft.goal.SimpleIDE.IDENode;
import nl.tudelft.goal.SimpleIDE.IDEState;
import nl.tudelft.goal.SimpleIDE.IconFactory;
import nl.tudelft.goal.SimpleIDE.IdeFiles;
import nl.tudelft.goal.SimpleIDE.ProcessNode;
import nl.tudelft.goal.SimpleIDE.TextEditorInterface;
import nl.tudelft.goal.SimpleIDE.filenodes.AbstractFileNode;
import nl.tudelft.goal.SimpleIDE.filenodes.MASNode;

/**
 * Run a process or mas file. IDE figures out whether run or pause action is
 * appropriate
 *
 * @author W.Pasman 20jun2011
 */
public class RunAction extends GOALAction {
	private static final long serialVersionUID = 701784252328131654L;

	public RunAction() {
		setIcon(IconFactory.RUN.getIcon());
		setShortcut('R');
		setDescription("Launch multi-agent system"); //$NON-NLS-1$
	}

	@Override
	public void eventOccured(IDEState currentState, Object evt) {

		boolean enabled = false;

		if (currentState.getViewMode() == IDEMainPanel.EDIT_VIEW) {
			List sel = currentState.getSelectedFileNodes();
			if (!sel.isEmpty()) {
				enabled = updateState(sel.get(0));
			}
		} else {
			// debug mode
			List sel = currentState.getSelectedProcessNodes();
			if (!sel.isEmpty()) {
				enabled = updateState(sel.get(0));
			}
		}
		setActionEnabled(enabled);

	}

	private boolean updateState(AbstractFileNode node) {
		if (node.getParentMASNode() == null || getCurrentState().getRuntime() != null) {
			return false;
		}
		if (!IdeFiles.getInstance().getErrors(node.getParentMASNode().getBaseFile()).isEmpty()) {
			return false;
		}

		setDescription("Launch multi-agent system");
		return true;
	}

	private boolean updateState(IDENode node) {
		switch (node.getType()) {
		case MAS_PROCESS:
			setDescription("Run all agents"); //$NON-NLS-1$
			return ((ProcessNode) node).getProcessRunMode() != RunMode.RUNNING;
		case AGENT_PROCESS:
			setDescription("Run agent"); //$NON-NLS-1$
			return ((ProcessNode) node).getProcessRunMode() != RunMode.RUNNING;
		case ENVIRONMENT_PROCESS:
			setDescription("Run environment"); //$NON-NLS-1$
			return ((ProcessNode) node).getProcessRunMode() != RunMode.RUNNING;
		default:
			return false;
		}

	}

	@Override
	protected void execute(TreeNode selectedNode, ActionEvent ae) throws GOALException {

		// Check first whether we're in edit view and a MAS is already running.
		// In that case, simply switch view to debug view.
		if (getCurrentState().getViewMode() == IDEMainPanel.EDIT_VIEW && getCurrentState().getRuntime() != null) {
			getIDE().getMainPanel().switchView();
			return;
		}

		if (selectedNode instanceof AbstractFileNode) {
			// run a MAS file
			run((AbstractFileNode) selectedNode);
		} else {
			// run a Process node
			run((IDENode) selectedNode);
		}
	}

	/**
	 *
	 * @param node
	 * @throws GOALException
	 */
	private void run(IDENode node) throws GOALException {
		if (getCurrentState().getViewMode() == IDEMainPanel.DEBUG_VIEW) {
			// user runs a process node. Restart it and we're done
			getIDE().getMainPanel().getProcessPanel().runProcessNode((ProcessNode) node);
			return;
		}
	}

	private void run(AbstractFileNode node) throws GOALRunFailedException {

		// TODO: only require to save only used files.
		if (!checkAllSaved()) {
			// Do nothing if the user canceled the save all action.
			return;
		}

		// If the node is the root node, check if there is a single unique
		// MAS we can launch.
		MASNode masnode = node.getParentMASNode();
		if (masnode == null) {
			new Warning(Resources.get(WarningStrings.FAILED_RUN_NO_MAS)).emit();
			return;
		}

		// Parse MAS file. Ensures latest version is ran.
		File masFile = masnode.getBaseFile();

		DebugRun run = new DebugRun(masFile);
		if (!run.getErrors().isEmpty()) {
			new Warning(Resources.get(WarningStrings.FAILED_RUN_MAS_ERRORS)).emit();
			return;
		}

		MASProgram masProg = run.getProgram();

		Set definitions = new HashSet<>();
		for (String name : masProg.getAgentNames()) {
			definitions.add(masProg.getAgentDefinition(name));
		}

		// disable editing of all involved files.
		for (AgentDefinition agentDef : definitions) {
			TextEditorInterface editor = EditManager.getInstance()
					.getEditorPane(agentDef.getSourceInfo().getSource().toString());
			// TODO: QUICK HACK. #1717. We need to lock ALL files, not
			// just agent files.
			if (editor != null) {
				editor.setEditable(false);
			}
		}

		// Launch the MAS.
		try {
			// update all breakpoints
			for (File file : IdeFiles.getInstance().getUsedFiles(masProg)) {
				EditManager.getInstance().updateBreakpoints(file);
			}

			run.buildRuntime();
			RuntimeManager runtime = run.getManager();

			// Update view.
			getCurrentState().setRuntime(run);
			getIDE().getMainPanel().getProcessPanel().init();
			getIDE().getMainPanel().switchView();
			// Subscribe feedback and process panels as observers.
			runtime.addObserver(getIDE().getMainPanel().getFeedbackPanel());
			runtime.addObserver(getIDE().getMainPanel().getProcessPanel());

			// connect the breakpoints. Unfortunately we need a listener and 15
			// lines for that...
			runtime.addObserver(new RuntimeEventObserver() {
				@SuppressWarnings("unchecked")
				@Override
				public void eventOccured(RuntimeManager source, RuntimeEvent event) {
					if (event.getType() == EventType.AGENT_IS_LOCAL_AND_READY) {
						final Agent agent = (Agent) event.getSource();
						agent.getController().keepDataOnTermination();
						agent.getController().getDebugger()
								.setBreakpoints(getCurrentState().getBreakpointManager().getBreakpoints());
						agent.getController().getDebugger().step(); // SimpleIDE
																	// always
																	// wants to
																	// start
																	// stepping
					}
				}
			});
			runtime.start(false);
		} catch (Exception e) { // TODO: distinguish between types of
			// exceptions...
			new Warning(Resources.get(WarningStrings.FAILED_RUN_MAS), e).emit();
			for (TextEditorInterface editor : EditManager.getInstance().getEditors()) {
				editor.setEditable(true);
			}
		}

	}

	/**
	 * Save all files.
	 *
	 * @return {@code false} if user cancelled or a problem while saving
	 *         occurred; {@code true} otherwise.
	 */
	private boolean checkAllSaved() {
		if (EditManager.getInstance().isDirty()) { // content has been
			// edited
			int selection = JOptionPane.showConfirmDialog(getCurrentState().getRootComponent(),
					"Save all files?\n" //$NON-NLS-1$
							+ "Some files were edited but are not yet saved. " //$NON-NLS-1$
							+ "All files must be saved before launching.", //$NON-NLS-1$
					"Save all files?", JOptionPane.OK_CANCEL_OPTION); //$NON-NLS-1$

			switch (selection) {
			case JOptionPane.CANCEL_OPTION:
				// cancel -> exit
				return false;
			case JOptionPane.OK_OPTION:
				// OK -> save all and continue
				try {
					EditManager.getInstance().saveAll();
				} catch (GOALException e) {
					new Warning(Resources.get(WarningStrings.FAILED_SAVEALL), e).emit();
					return false;
				}
				break;
			}
		}
		return true;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy