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

org.ow2.frascati.fscript.console.TextConsole Maven / Gradle / Ivy

The newest version!
/**
 * OW2 FraSCAti FScript
 * Copyright (C) 2009-2010 INRIA, University of Lille 1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Contact: [email protected]
 *
 * Author: Christophe Demarey
 *
 * Contributor(s): Philippe Merle
 *
 */
package org.ow2.frascati.fscript.console;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Ordering.natural;
import static java.util.Collections.emptySet;
import static java.util.Collections.sort;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import javax.script.Bindings;
import javax.script.SimpleBindings;

import jline.ConsoleReader;

import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.fscript.FScript;
import org.objectweb.fractal.fscript.FScriptEngine;
import org.objectweb.fractal.fscript.console.Command;
import org.objectweb.fractal.fscript.console.SessionDiagnosticListener;
import org.objectweb.fractal.fscript.diagnostics.DiagnosticListener;
import org.objectweb.fractal.fscript.model.Axis;
import org.objectweb.fractal.fscript.model.Model;
import org.objectweb.fractal.util.Fractal;
import org.ow2.frascati.fscript.FraSCAtiFScript;
import org.ow2.frascati.fscript.console.commands.AbstractCommand;

import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;

/**
 * A FraSCAtiScript console ("shell") to manipulate SCA and Fractal architectures interactively on the
 * command-line.
 * 
 * @author Christophe Demarey
 */
public class TextConsole
     extends org.objectweb.fractal.fscript.console.TextConsole
{
	/** The console context. */
	private Bindings bindings = null;

	/**
	 * Convenient constructor used to start a console with an 
	 * empty engine context.
	 * @param fscript The FScript implementation
	 * @throws IOException
	 */
	public TextConsole(Component fscript) throws IOException
	{
		this(fscript, new SimpleBindings());
	}

	/**
	 * Default constructor
	 * @param fscript The FScript implementation
	 * @param ctx The context to use for this console.
	 * @throws IOException
	 */
	public TextConsole(Component fscript, Bindings ctx) throws IOException
	{
		checkNotNull(fscript);
		this.fscript = fscript;
		this.bindings = ctx;
		this.commands = newHashMap();
		registerCommands();

		this.console = new ConsoleReader();
		register(new QuitCommand());
		addCompletors();

		BANNER = "FraSCAtiScript console.\n\n" + "Useful commands:\n"
		+ "- type ':help' for a list of available commands\n"
		+ "- type ':help ' for detailed help on a specific command\n"
		+ "- type ':quit' to exit\n\n";

		PROMPT = "FraSCAtiScript> ";
	}
	
    /**
     * Get the command context that will be used to execute this command.
     * @return the command context.
     */
    public final Bindings getContext()
    {
    	return this.bindings;
    }

	protected final void registerCommands()
	{
		// Internal commands
		register(new HelpCommand());

		Properties commandsConfig = new Properties();
		try {
			String resourceName = "org/ow2/frascati/fscript/console/commands.properties";
			ClassLoader cl = FraSCAtiFScript.getSingleton().getClassLoaderManager().getClassLoader();
			InputStream commandsStream = cl.getResourceAsStream(resourceName);
			if (commandsStream == null) {
				showError("Could not find configuration file " + resourceName + ".");
				throw new RuntimeException("Could not find configuration file "
						+ resourceName + ".");
			}
			commandsConfig.load(commandsStream);
		} catch (IOException e) {
			showError("Could not read commands configuration file.", e);
			throw new RuntimeException("Could not read commands configuration file.", e);
		}
		for (Object o : commandsConfig.keySet()) {
			String key = (String) o;
			if (key.endsWith(".class")) {
				String name = key.substring("command.".length(), key.lastIndexOf('.'));
				String klass = commandsConfig.getProperty(key);
				String shortDesc = commandsConfig.getProperty("command." + name
						+ ".shortDesc");
				String longDesc = commandsConfig.getProperty("command." + name
						+ ".longDesc");
				Command cmd = createCommand(name, klass, shortDesc, longDesc);
				if (cmd != null) {
					register(cmd);
				}
			}
		}
	}

	protected final void register(Command cmd)
	{
		cmd.setSession(this);
		cmd.setFScriptEngine(fscript);
		this.commands.put(cmd.getName(), cmd);
	}

	private class QuitCommand
	      extends AbstractCommand
	{
		@Override
		public final String getName()
		{
			return "quit";
		}

		@Override
		public final String getShortDescription()
		{
			return "Quit the console.";
		}

		@Override
		public final String getLongDescription()
		{
			return getShortDescription();
		}

		public final void execute(String args) throws Exception
		{
			TextConsole.this.finished = true;
		}
	}


	protected class HelpCommand
	        extends AbstractCommand
	{
		public HelpCommand() {};

		@Override
		public final String getName()
		{
			return "help";
		}

		@Override
		public final String getShortDescription()
		{
			return "Shows a list of available commands.";
		}

		@Override
		public final String getLongDescription()
		{
			return super.getShortDescription();
		}

		public final void execute(String args) throws Exception
		{
			if (args.length() == 0) {
				listAvailableCommands();
			} else {
				String name = args.startsWith(":") ? args.substring(1) : args;
				Command cmd = commands.get(name);
				if (cmd != null) {
					showMessage(cmd.getLongDescription());
				} else {
					showError("No such command: " + name);
				}
			}
		}

		private void listAvailableCommands() 
		{
			showTitle("Available commands");
			showMessage("Type ':help ' for more details on a specific command.");
			newline();

			List sortedCmds = newArrayList(commands.values());
			sort(sortedCmds, natural().onResultOf(new Function() {
						public final String apply(Command cmd)
						{
							return cmd.getName();
						}
					}));
			String[][] table = new String[sortedCmds.size() + 1][2];
			table[0][0] = "Command";
			table[0][1] = "Description";
			int i = 0;
			for (Command command : sortedCmds) {
				table[i + 1][0] = command.toString();
				table[i + 1][1] = command.getShortDescription();
				i += 1;
			}
			showTable(table);
		}
	}

	protected class Request
	{
		private final Command command;
		private final String arguments;

		public Request(String commandName, String arguments)
		{
			this.command = commands.get(commandName);
			this.arguments = arguments;
		}

		public final void execute() throws Exception
		{
			if (command != null) {
				command.execute(arguments);
			} else {
				showError("Invalid request.");
			}
		}
	}

	protected final Request parseRequest(String line)
	{
		if (line == null) {
			return new Request("quit", "");
		} else if (line.startsWith(":")) {
			int i = line.indexOf(' ');
			if (i != -1) {
				return new Request(line.substring(1, i), line.substring(i + 1));
			} else {
				return new Request(line.substring(1), "");
			}
		} else if (line.endsWith(";") || line.contains("{")) {
			return new Request("exec", line);
		} else {
			return new Request("eval", line);
		}
	}

	public final void setFScriptEngine(Component newEngine)
	{
		this.fscript = newEngine;
		for (Command cmd : commands.values()) {
			cmd.setFScriptEngine(this.fscript);
		}
	}

	public final void setSessionInterpreter(Component fscript)
	{
		for (Command cmd : commands.values()) {
			cmd.setFScriptEngine(fscript);
		}
	}

	public final DiagnosticListener getDiagnosticListener()
	{
		return new SessionDiagnosticListener(this);
	}

	public final void processRequest(String line) throws Exception
	{
		if (line != null && line.length() == 0) {
			return;
		}
		Request request = parseRequest(line);
		if (request != null) {
			request.execute();
		}
	}

	public final Set getGlobalVariablesNames()
	{
		FScriptEngine engine = FScript.getFScriptEngine(fscript);
		return engine.getGlobals();
	}

	public final Set getAxesNames()
	{
		Model model = getModel();
		if (model != null) {
			Set axes = model.getAxes();
			Set names = new HashSet();
			for (Axis axis : axes) {
				names.add(axis.getName());
			}
			return names;
		} else {
			return emptySet();
		}
	}

	protected final Model getModel()
	{
		try {
			for (Component c : Fractal.getContentController(fscript).getFcSubComponents()) {
				String name = Fractal.getNameController(c).getFcName();
				if ("model".equals(name)) {
					return (Model) c.getFcInterface("model");
				}
			}
			return null;
		} catch (Exception e) {
			showWarning("Incompatible FScript implementation.");
			showWarning("Axis name completion disabled.");
			return null;
		}
	}

	public final Set getCommandNames()
	{
		return commands.keySet();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy