001package co.codewizards.cloudstore.client;
002
003import java.io.Console;
004
005/**
006 * <p>
007 * Sub-command for a certain CLI operation.
008 * <p>
009 * The CloudStore-command-line-interface uses a syntax similar to the svn command and the logic of the
010 * command 'java -jar co.codewizards.cloudstore.client-VERSION.jar SUBCOMMAND -arg1 val1 -arg2 val2 ...'
011 * is thus actually implemented by a class extending this class and {@link #getSubCommandName() registering}
012 * for a certain 'SUBCOMMAND'.
013 * <p>
014 * Every subclass of this class can declare its arguments using annotations like {@link Option}.
015 *
016 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de
017 */
018public abstract class SubCommand
019{
020        private String subCommandName;
021
022        /**
023         * Get the name of the sub-command, i.e. what the user has to write in the command line.
024         * @return the name of the sub-command.
025         */
026        public String getSubCommandName() {
027                if (subCommandName == null) {
028                        final String suffix = "SubCommand";
029                        String simpleName = this.getClass().getSimpleName();
030                        if (!simpleName.endsWith(suffix))
031                                throw new IllegalStateException(
032                                                String.format("Class name '%s' does not end with suffix '%s'! Rename the class or override the 'getSubCommand()' method!",
033                                                                simpleName, suffix));
034
035                        StringBuilder sb = new StringBuilder();
036                        sb.append(simpleName.substring(0, simpleName.length() - suffix.length()));
037                        if (sb.length() == 0)
038                                throw new IllegalStateException(
039                                                String.format("Class name '%s' equals suffix '%s'! There should be sth. before the suffix! Rename the class or override the 'getSubCommand()' method!",
040                                                                simpleName, suffix));
041
042                        sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
043                        subCommandName = sb.toString();
044                }
045                return subCommandName;
046        }
047
048        /**
049         * Get the description for this sub-command.
050         * @return the description.
051         */
052        public abstract String getSubCommandDescription();
053
054        public void prepare()
055        throws Exception
056        {
057        }
058
059        public abstract void run()
060        throws Exception;
061
062        protected String promptPassword(String fmt, Object ... args) {
063                Console console = System.console();
064                if (console == null)
065                        throw new IllegalStateException("There is no system console! Cannot prompt \"" + String.format(fmt, args) + "\"!!!");
066
067                char[] pw = console.readPassword(fmt, args);
068                if (pw == null)
069                        return null;
070                else
071                        return new String(pw);
072        }
073
074        protected String prompt(String fmt, Object ... args) {
075                Console console = System.console();
076                if (console == null)
077                        throw new IllegalStateException("There is no system console! Cannot prompt \"" + String.format(fmt, args) + "\"!!!");
078
079                String result = console.readLine(fmt, args);
080                return result;
081        }
082
083        public boolean isVisibleInHelp() {
084                return true;
085        }
086}