/**
* Copyright (c) 2010 Marc A. Paradise
*
* This file is part of "BBSSH"
*
* BBSSH is based upon MidpSSH by Karl von Randow.
* MidpSSH was based upon Telnet Floyd and FloydSSH by Radek Polak.
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
package org.bbssh.keybinding;
import net.rim.device.api.i18n.ResourceBundleFamily;
import org.bbssh.i18n.BBSSHResource;
import org.bbssh.session.RemoteSessionInstance;
/**
* Abstract class that encapsulates a discrete action that can be taken while connected to an active emulation session.
*
*/
public abstract class ExecutableCommand implements BBSSHResource {
protected ResourceBundleFamily res = ResourceBundleFamily.getBundle(BUNDLE_ID, BUNDLE_NAME);
public static final int PARAM_TYPE_NONE = 0;
public static final int PARAM_TYPE_TERM_KEY = 1;
public static final int PARAM_TYPE_ALPHANUM = 2;
public static final int PARAM_TYPE_INT = 3;
public static final int PARAM_TYPE_DIRECTIONAL_KEY = 4;
protected static final int NOTIFY_BEHAVIOR_NONE = 0;
protected static final int NOTIFY_BEHAVIOR_NAME_ONLY = 1;
protected static final int NOTIFY_BEHAVIOR_VALUE_ONLY = 2;
protected static final int NOTIFY_BEHAVIOR_NAME_AND_VALUE = 3;
/**
* gets the unique ID that represents this command.
*
* @return unique command id
*/
abstract public int getId();
/**
* Required method that performs any work associated with with this command.
*
* If you maintain any state data in your ExecutableCommand you must manage synchronization.
*
* This is likely to become protected in the future, and will be invoked only by the framework after validations are
* complete.
*
* @param inst session against which this command will be applied.
* @param parameter additional parameter if required. implementors must check to ensure this is valid and of
* required data type.
* @return true if successfully handled.
*
* #see net.rim.device.api.system.KeypadListener
*/
public abstract boolean execute(RemoteSessionInstance inst, Object parameter);
/**
* Implement this method to provide a user-friendly (and localized) short name of a command.
*
* @return red-id of a user-friendly name
*/
public abstract int getNameResId();
/**
* Override this method to provide a user-friendly (and localized) long description of your command.
*
* @return res-id of the description of this command.
*/
public abstract int getDescriptionResId();
/**
* Return true if you require a valid argument.
*/
public abstract boolean isParameterRequired();
/**
* Returns true if this accepts a parameter that is entirely optional.
*
* @return true if optional parameter is accepted.
*/
public boolean isParameterOptional() {
return false;
}
/**
* provide displayable name of this command.
*/
public String toString() {
return res.getString(getNameResId());
}
/**
* Invoke this to determine if a command can be bound by the user as a keystroke-based command.
*
* @return true if the command is available for key binding.
*/
public abstract boolean isKeyBindable();
/**
* Invoke this to determine if a command can be used as a macro action.
*
* @return true if this is available as a macro action.
*/
public abstract boolean isMacroAction();
/**
* Return a translated description of the parameter value passed in. This is used in key bindings, for displaying
* proper name.
*
* @param parameter
* @return translation of the parameter value. "N/A" if no translation found or applicable.
*/
public String translateParameter(Object parameter) {
if (parameter instanceof String) {
return (String) parameter;
}
if (parameter instanceof Integer || parameter instanceof Long) {
return parameter.toString();
}
return "";
}
public boolean equals(Object compareTo) {
if (compareTo == null)
return false;
if (!(compareTo instanceof ExecutableCommand)) {
return false;
}
if (((ExecutableCommand) compareTo).getId() == getId()) {
return true;
}
return false;
}
// @todo can we look at marker interfaces instead of these various "isConnectionRequired/et al)
/**
* Override this to control whether a given command is available for current platform (hardware + software)
* implementation.
*
* @return true if available.
*/
public boolean isAvailableOnCurrentPlatform() {
return true;
}
/**
* @return true if a connection must be
*/
public abstract boolean isConnectionRequired();
// @todo : validate(final Object parameter)
// @todo : getParameterType(int pos)
/**
* @return true if this command requires a UI lock. Thi sis generally necessary if the command will be presenting
* modifying the UI in any way (such as changing which screen is displayed, showing a menu, popup, etc).
*/
public boolean isUILockRequired() {
return false;
}
/**
*
* @return a NOTIFY_BEHAVIOR_* const that describes what shoudl be displayed on the terminal when this command is
* executed
*/
public int getNotifyBehavior() {
return NOTIFY_BEHAVIOR_NONE;
}
}