001: /*
002: * This is free software, licensed under the Gnu Public License (GPL)
003: * get a copy from <http://www.gnu.org/licenses/gpl.html>
004: * $Id: Command.java,v 1.10 2005/11/27 16:20:27 hzeller Exp $
005: * author: Henner Zeller <H.Zeller@acm.org>
006: */
007: package henplus;
008:
009: import java.util.Iterator;
010:
011: import org.apache.commons.cli.CommandLine;
012: import org.apache.commons.cli.Options;
013:
014: /**
015: * Interface to be implemented for user level commands.
016: * <p>The CommandDispatcher
017: * and the HelpCommand operate on this interface. This interface needs
018: * to be implemented by your own Commands or Plugins that should be
019: * supported by HenPlus. If the documenation given here is not enough
020: * (though I hope it is), just read some of the implementations given
021: * in henplus.commands.
022: * </p>
023: * <p>
024: * If you are writing Plugins, consider extending the
025: * {@link AbstractCommand} as it provides a default implementation
026: * and you are immune to NoSuchMethodErrors if this interface changes
027: * but not yet your plugin...</p>
028: *
029: * @version $Revision: 1.10 $
030: * @author Henner Zeller
031: */
032: public interface Command {
033: /**
034: * constant returned by the {@link #execute(SQLSession,String,String)}
035: * method, if everything went fine.
036: */
037: public final static int SUCCESS = 0;
038:
039: /**
040: * constant returned by the {@link #execute(SQLSession,String,String)}
041: * if the command could not be executed because of an syntax error.
042: * In that case, the CommandDispatcher will display the synopsis of
043: * that command.
044: */
045: public final static int SYNTAX_ERROR = 1;
046:
047: /**
048: * constant returned by the {@link #execute(SQLSession,String,String)}
049: * if the command could not be executed because of some problem, that
050: * is not a syntax error.
051: */
052: public final static int EXEC_FAILED = 2;
053:
054: /**
055: * returns the prefices of all command-strings this command can handle.
056: * The special prefix is the empty string that matches anything that is
057: * not handled by all other commands. It is used in the SQLCommand.
058: */
059: String[] getCommandList();
060:
061: /**
062: * returns 'false', if the commands supported by this Commands should
063: * not be part of the toplevel command completion. So if the user
064: * presses TAB on an empty string to get the full list of possible
065: * commands, this command should not show up.
066: * In HenPlus, this returns 'false' for the SQL-commands
067: * ('select', 'update', 'drop' ..), since this would
068: * clobber the toplevel list of available commands.
069: * If unsure, return 'true'.
070: */
071: boolean participateInCommandCompletion();
072:
073: /**
074: * execute the command given. The command is given completely without
075: * the final delimiter (which would be newline or semicolon). Before
076: * this method is called, the CommandDispatcher checks with the
077: * {@link #isComplete(String)} method, if this command is complete.
078: *
079: * @param session the SQLsession this command is executed from.
080: * @param command the command as string.
081: * @param parameters the rest parameters following the command.
082: * @return one of SUCCESS, SYNTAX_ERROR, EXEC_FAILED to indicate
083: * the exit status of this command. On SYNTAX_ERROR, the
084: * CommandDispatcher displays a synopsis if available.
085: */
086: int execute(SQLSession session, String command, String parameters);
087:
088: /**
089: * Returns a list of strings that are possible at this stage. Used
090: * for the readline-completion in interactive mode. Based on the
091: * partial command and the lastWord you have to determine the words
092: * that are available at this stage. Return 'null', if you don't know
093: * a possible completion.
094: *
095: * @param disp the CommandDispatcher - you might want to access
096: * other values through it.
097: * @param partialCommand The command typed so far
098: * @param lastWord the last word returned by readline.
099: */
100: Iterator complete(CommandDispatcher disp, String partialCommand,
101: String lastWord);
102:
103: /**
104: * returns, whether the command is complete.
105: *
106: * <p>This method is called, whenever the input encounters a newline or
107: * a semicolon to decide if this separator is to separate different
108: * commands or if it is part of the command itself.
109: *
110: * <p>The delimiter (newline or semicolon) is contained (at the end)
111: * in the String passed to this method. This
112: * method returns <code>false</code>, if the delimiter is part of the
113: * command and will not be regarded as delimiter between commands -- the
114: * reading part of the command dispatcher will go on reading characters
115: * and not execute the command.
116: *
117: * <p>This method will return true for most simple commands like
118: * 'help'. For commands that have a more complicated syntax, this
119: * might not be true.
120: * <ul>
121: * <li>'select * from foobar' is not complete after a return, since we can
122: * expect a where clause. If it has a semicolon at the end, we
123: * know, that is is complete. So newline is <em>not</em> a delimiter
124: * while ';' is (return command.endsWith(";")).
125: * <li>definitions of stored procedures are even more complicated: it
126: * depends on the syntax whether a semicolon is part of the
127: * command or can be regarded as delimiter. Here, neither ';' nor
128: * newline can be regarded as delimiter per-se. Only the Command
129: * implementation can decide upon this. In Oracle, a single '/' on
130: * one line is used to denote this command-complete.
131: * </ul>
132: * Note, this method should only apply a very lazy syntax check so it does
133: * not get confused and uses too much cycles unecessarily..
134: *
135: * @param command the partial command read so far given to decide by
136: * the command whether it is complete or not.
137: */
138: boolean isComplete(String command);
139:
140: /**
141: * returns true, if this command requires a valid SQLSession, i.e. if the
142: * {@link #execute(SQLSession,String,String)} method makes use of the
143: * session (e.g. to get some Database connection) or not. Return 'true'
144: * if unsure (you should be sure..). This is to thwart attempts to
145: * execute a command without session.
146: *
147: * @param cmd the subcommand this is requested for; one of the
148: * commands returned by {@link #getCommandList()}.
149: */
150: boolean requiresValidSession(String cmd);
151:
152: /**
153: * shutdown this command. This is called on exit of the CommandDispatcher
154: * and allows you to do some cleanup (close connections, flush files..)
155: */
156: void shutdown();
157:
158: /**
159: * return a short string describing the purpose of the commands
160: * handled by this Command-implementation. This is the string listed
161: * in the bare 'help' overview (like
162: * <code>'describe a database object'</code>)
163: * Should contain no newline, no leading spaces.
164: */
165: String getShortDescription();
166:
167: /**
168: * retuns a synopsis-string. The synopsis string returned should follow
169: * the following conventions:
170: * <ul>
171: * <li>expected parameters are described with angle brackets like in
172: * <code>export-xml <table> <filename></li>
173: * <li>optional parameters are described with square brackets like in
174: * <code>help [command]</code></li>
175: * </ul>
176: * <p>Should contain no newline, no leading spaces.
177: * This synopsis is printed in the detailed help of a command or if the
178: * execute()-method returned a SYNTAX_ERROR.
179: *
180: * @param cmd the command the synopsis is for. This is one of the possible
181: * commands returned by {@link #getCommandList()}.
182: */
183: String getSynopsis(String cmd);
184:
185: /**
186: * returns a longer string describing this action. This should return
187: * a String describing details of the given command. This String should
188: * start with a TAB-character in each new line (the first line is a
189: * new line). The last line should not end with newline.
190: *
191: * @param cmd The command the long description is asked for. This
192: * is one of the possible commands returned by
193: * {@link #getCommandList()}.
194: */
195: String getLongDescription(String cmd);
196:
197: /**
198: * Options are set, after the commandline has been parsed.
199: * @param options
200: */
201: public void setOptions(Options options);
202:
203: /**
204: * This method is called before parsing the commandline. You can register command-specific options here.
205: * @param r
206: */
207: public void registerOptions(Options r);
208:
209: /**
210: * After parsing the parameters, this method is called.
211: *
212: * there can be some default options left.
213: * These are set to the commands through this method. This is only
214: * for compatibility with the old commandline options, please use
215: * named options only!
216: * @param line TODO
217: */
218: public void handleCommandline(CommandLine line);
219:
220: }
221:
222: /*
223: * Local variables:
224: * c-basic-offset: 4
225: * compile-command: "ant -emacs -find build.xml"
226: * End:
227: */
|