/*******************************************************************************
 * Copyright (c) 2018 Eclipse RDF4J contributors.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Distribution License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *******************************************************************************/
package org.eclipse.rdf4j.console;

import org.apache.commons.cli.AlreadySelectedException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;

/**
 * Helper class for configuring console
 * 
 * @author Bart Hanssens
 */
class CmdLineParser {
	private final static Option HELP = new Option("h", "help", false, 
				"print this help");
	private final static Option VERSION = new Option("v", "version", false, 
				"print version information");
	private final static Option SERVER = new Option("s", "serverURL", true,
				"URL of RDF4J Server to connect to, e.g. http://localhost:8080/rdf4j-server/");
	private final static Option DIRECTORY = new Option("d", "dataDir", true, 
				"data dir to 'connect' to");
	private final static Option ECHO = new Option("e", "echo", false,
				"echoes input back to stdout, useful for logging script sessions");
	private final static Option QUIET = new Option("q", "quiet", false, 
				"suppresses prompts, useful for scripting");
	private final static Option FORCE = new Option("f", "force", false,
				"always answer yes to (suppressed) confirmation prompts");
	private final static Option CAUTIOUS = new Option("c", "cautious", false,
				"always answer no to (suppressed) confirmation prompts");
	private final static Option MODE = new Option("x", "exitOnError", false,
				"immediately exit the console on the first error");
		
	private final static OptionGroup CAUTION_GROUP = new OptionGroup().addOption(CAUTIOUS)
								.addOption(FORCE)
								.addOption(MODE);
	private final static OptionGroup LOCATION_GROUP = new OptionGroup().addOption(SERVER)
								.addOption(DIRECTORY);
	private final static Options OPTIONS = new Options()
						.addOptionGroup(LOCATION_GROUP)
						.addOptionGroup(CAUTION_GROUP)
						.addOption(HELP)
						.addOption(VERSION)
						.addOption(ECHO)
						.addOption(QUIET);

	private final Console console;
	private CommandLine commandLine;
	
	/**
	 * Parse command line arguments
	 * 
	 * @param args arguments
	 * @return parsed command line or null
	 */
	protected CommandLine parse(String[] args) {
		try {
			commandLine = new PosixParser().parse(OPTIONS, args);
		} catch (ParseException e) {
			commandLine = null;
			console.getConsoleIO().writeError(e.getMessage());
		}
		return commandLine;
	}
	
	/**
	 * Print usage / available command line OPTIONS to screen
	 */
	protected void printUsage() {
		ConsoleIO io = console.getConsoleIO();
		
		io.writeln("RDF4J Console, an interactive command shell for RDF4J repositories.");
		final HelpFormatter formatter = new HelpFormatter();
		formatter.setWidth(80);
		formatter.printHelp("start-console [OPTION] [repositoryID]", OPTIONS);
		io.writeln();
		io.writeln("For bug reports and suggestions, see http://www.rdf4j.org/");
	}

	/**
	 * Handle help or version parameter at the command line
	 * 
	 * @return false if an information option was given
	 */
	protected boolean handleInfoOptions() {
		if (commandLine.hasOption(HELP.getOpt())) {
			printUsage();
			return false;
		}
		if (commandLine.hasOption(VERSION.getOpt())) {
			console.getConsoleIO().writeln(console.getState().getApplicationName());
			return false;
		}
		return true;
	}

	/**
	 * Handle command line "exit on error" mode
	 */
	protected void handleExitOption() {
		console.setExitOnError(commandLine.hasOption(MODE.getOpt()));
	}
	
	/**
	 * Handle command line echo options
	 */
	protected void handleEchoOptions() {
		ConsoleIO io = console.getConsoleIO();
		
		io.setEcho(commandLine.hasOption(ECHO.getOpt()));
		io.setQuiet(commandLine.hasOption(QUIET.getOpt()));
	}
	
	/**
	 * Handle command line caution group
	 * 
	 * @return location of the (remote or local) repository 
	 */
	protected boolean handleCautionGroup() {
		ConsoleIO io = console.getConsoleIO();
		
		try {
			if (commandLine.hasOption(FORCE.getOpt())) {
				CAUTION_GROUP.setSelected(FORCE);
				io.setForce();
			}
			if (commandLine.hasOption(CAUTIOUS.getOpt())) {
				CAUTION_GROUP.setSelected(CAUTIOUS);
				io.setCautious();
			}
		} catch (AlreadySelectedException e) {
			printUsage();
			return false;
		}	
		return true;
	}
	
	/**
	 * Handle command line location group
	 * 
	 * @return location of the (remote or local) repository 
	 */
	protected String handleLocationGroup() {
		String location = null;
		
		try {
			if (commandLine.hasOption(DIRECTORY.getOpt())) {
				LOCATION_GROUP.setSelected(DIRECTORY);
				location = commandLine.getOptionValue(DIRECTORY.getOpt());
			}
			if (commandLine.hasOption(SERVER.getOpt())) {
				LOCATION_GROUP.setSelected(SERVER);
				location = commandLine.getOptionValue(SERVER.getOpt());
			}
		} catch (AlreadySelectedException e) {
			printUsage();
		}
		return location;
	}
	
	/**
	 * Get selected location from location group.
	 * Can be d(irectory) or s(erver)
	 * 
	 * @return string 
	 */
	protected String getSelectedLocation() {
		return LOCATION_GROUP.getSelected();
	}
	
	/**
	 * Get remaining argument from command line, if any.
	 * Returns empty string if there is no argument, null on error
	 * 
	 * @return argument as string, or null on error
	 */
	protected String handleOtherArg() {
		String[] otherArgs = commandLine.getArgs();
		if (otherArgs.length > 1) {
			printUsage();
			return null;
		}
		return (otherArgs.length == 1) ? otherArgs[0] : "";
	}
	
	/**
	 * Constructor
	 * 
	 * @param console 
	 */
	protected CmdLineParser(Console console) {
		this.console = console;
	}
}

@@ -601,16 +601,61 @@
 ndLine;%0A
+import org.apache.commons.cli.DefaultParser;%0A
 import o
@@ -860,51 +860,8 @@
 ion;
-%0Aimport org.apache.commons.cli.PosixParser;
 %0A%0A/*
@@ -2828,13 +2828,15 @@
 new 
-Posix
+Default
 Pars

Use DefaultParser instead of deprecated PosixParser