package dw.cli;
import java.util.ArrayList;
import java.util.List;
import com.martiansoftware.jsap.FlaggedOption;
import com.martiansoftware.jsap.JSAP;
import com.martiansoftware.jsap.JSAPException;
import com.martiansoftware.jsap.JSAPResult;
import com.martiansoftware.jsap.Switch;
import com.martiansoftware.jsap.defaultsources.PropertyDefaultSource;
public class OptionParser {
private boolean _success;
private CliOptions _cliOptions;
private String _helpMessage;
private final PasswordReader _pwdReader;
private List<String> _genericArguments = new ArrayList<String>();
private List<String> _commandArguments = new ArrayList<String>();
private String _command;
public String[] getCommandArguments(){
return _commandArguments.toArray(new String[]{});
}
private static final String PASSWORD_OPTION = "password";
private static final String PASSWORD_INTERACTIVE_OPTION = "password-interactive";
private static final String DEBUG_OPTION = "debug";
private JSAP _genericOptionsJSAP = buildJsap();
public OptionParser(String[] args){
this(args, new PasswordReader());
}
public OptionParser(String[] args, PasswordReader pwdReader){
_pwdReader = pwdReader;
feedGenericAndCommandOptions(args);
}
public void parse(){
boolean success;
String helpMessage;
CliOptions cliOptions;
JSAPResult config = _genericOptionsJSAP.parse(_genericArguments.toArray(new String[]{}));
if ( ! config.success() || !checkOptionsAreConsistent(config, _command) ){
success = false;
helpMessage = "";
for (@SuppressWarnings("rawtypes") java.util.Iterator errs = config.getErrorMessageIterator();
errs.hasNext();) {
helpMessage += errs.next() + "\n";
}
helpMessage += getUsage();
cliOptions = null;
} else {
success = true;
helpMessage = getUsage();
if ( _command == null && config.getBoolean("help")){
_command = "help";
}
if ( _command == null && config.getBoolean("version")){
_command = "version";
}
cliOptions = new CliOptions();
cliOptions.password = getPassword(config);
cliOptions.user = config.getString("user");
cliOptions.url = config.getURL("url");
cliOptions.debug = config.getBoolean("debug");
cliOptions.command = _command;
cliOptions.commandArguments = _commandArguments.toArray(new String[]{});
}
_success = success;
_helpMessage = helpMessage;
_cliOptions = cliOptions;
}
private void feedGenericAndCommandOptions(String[] args){
boolean alreadyReadCommand = false;
for ( int i=0 ; i < args.length ; i++ ){
String arg = args[i];
if ( alreadyReadCommand){
_commandArguments.add(arg);
} else {
if ( arg.startsWith("-") ){
_genericArguments.add(arg);
if ( ! arg.equals("--" + PASSWORD_INTERACTIVE_OPTION) && !arg.equals("--" + DEBUG_OPTION)){
i++;
if ( i < args.length ){
_genericArguments.add(args[i]);
}
}
} else {
_command = arg;
alreadyReadCommand = true;
}
}
}
}
public boolean userAskForHelp(){
JSAP jsap = new JSAP();
try {
registerHelpParameter(jsap);
} catch (JSAPException e) {
throw new RuntimeException("Something went really wrong", e);
}
JSAPResult parsed = jsap.parse(_genericArguments.toArray(new String[]{}));
return (_command != null && _command.equals("help")) || parsed.getBoolean("help");
}
private static JSAP buildJsap(){
JSAP jsap = new JSAP();
try {
jsap.registerParameter(new FlaggedOption("user")
.setStringParser(JSAP.STRING_PARSER)
.setRequired(false)
.setShortFlag('u')
.setLongFlag("user"));
jsap.registerParameter(new FlaggedOption("url")
.setStringParser(JSAP.URL_PARSER)
.setRequired(true)
.setShortFlag(JSAP.NO_SHORTFLAG)
.setLongFlag("url"));
jsap.registerParameter(new FlaggedOption(PASSWORD_OPTION)
.setStringParser(JSAP.STRING_PARSER)
.setRequired(false)
.setShortFlag('p')
.setLongFlag(PASSWORD_OPTION));
jsap.registerParameter(new Switch("version")
.setLongFlag("version"));
jsap.registerParameter(new Switch(PASSWORD_INTERACTIVE_OPTION)
.setLongFlag(PASSWORD_INTERACTIVE_OPTION));
jsap.registerParameter(new Switch("debug")
.setLongFlag(DEBUG_OPTION));
registerHelpParameter(jsap);
} catch (JSAPException e){
throw new RuntimeException("Something went really wrong", e);
}
registerDefaultSource(jsap);
return jsap;
}
private static void registerHelpParameter(JSAP jsap) throws JSAPException{
jsap.registerParameter(new Switch("help")
.setShortFlag('h')
.setLongFlag("help"));
}
private static void registerDefaultSource(JSAP jsap) {
String home = System.getProperty("user.home");
PropertyDefaultSource source = new PropertyDefaultSource(home + "/.dokujclientrc", false);
jsap.registerDefaultSource(source);
}
public boolean success(){
return _success;
}
public CliOptions getCliOptions(){
return _cliOptions;
}
public String getHelpMessage(){
return _helpMessage;
}
public static String getUsage(){
String message = buildJsap().getUsage() + " command";
message += "\n\nAvailable commands:";
for(String command : CommandFactory.commandList()){
message += "\n\t" + command;
}
message += "\n\nTo get help for a given command: help <command>";
return message;
}
private boolean checkOptionsAreConsistent(JSAPResult config, String command){
if (command == null && !config.getBoolean("help") && !config.getBoolean("version")){
return false;
}
if (config.contains(PASSWORD_OPTION) && config.getBoolean(PASSWORD_INTERACTIVE_OPTION)) {
return false;
}
return true;
}
private String getPassword(JSAPResult config){
if (config.contains(PASSWORD_OPTION)){
return config.getString(PASSWORD_OPTION);
}
if (config.getBoolean(PASSWORD_INTERACTIVE_OPTION)){
return _pwdReader.readPassword();
}
return "";
}
}