Skip to content
Snippets Groups Projects
Commit 11bf86c7 authored by Andrey Ruzhanskiy's avatar Andrey Ruzhanskiy
Browse files

Merge branch 'feat/CLI_Parser-2' into 'master'

Feat/cli parser 2

See merge request !3
parents 1d4e6b43 7e2fc73b
No related branches found
No related tags found
1 merge request!3Feat/cli parser 2
Showing
with 392 additions and 1 deletion
......@@ -28,6 +28,7 @@ repositories {
dependencies {
// Use JUnit test framework
compile group: 'commons-cli', name: 'commons-cli', version: '1.4'
testImplementation('org.junit.jupiter:junit-jupiter:5.4.2')
// Logging
......
package de.tudresden.inf.mci.brailleplot;
import de.tudresden.inf.mci.brailleplot.commandline.CommandLineParser;
import de.tudresden.inf.mci.brailleplot.commandline.SettingType;
import de.tudresden.inf.mci.brailleplot.commandline.SettingsReader;
import de.tudresden.inf.mci.brailleplot.commandline.SettingsWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Optional;
import java.util.concurrent.ConcurrentLinkedDeque;
/**
......@@ -105,10 +111,17 @@ public final class App {
mLogger.info("Application started");
// Parse command line parameters
CommandLineParser cliParser = new CommandLineParser();
SettingsWriter settings = cliParser.parse(args);
SettingsReader settingsReader = settings;
// If requested, print help and exit
Optional<Boolean> printHelp = settingsReader.isTrue(SettingType.DISPLAY_HELP);
if (printHelp.isPresent() && printHelp.get()) {
cliParser.printHelp();
return EXIT_SUCCESS;
}
// Parse csv data
......
package de.tudresden.inf.mci.brailleplot.commandline;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
/**
* Performs command line parsing and creates a {@link Settings} object.
* @author Georg Graßnick
* @version 2019.05.31
*/
public class CommandLineParser {
private Options mOptions;
public CommandLineParser() {
setupOptions();
}
private void setupOptions() {
mOptions = new Options();
mOptions.addOption("h", SettingType.DISPLAY_HELP.toString(), false, "Print help and exit")
.addOption("c", SettingType.CSV_LOCATION.toString(), true, "Path to CSV")
.addOption("s", SettingType.SEMANTIC_MAPPING.toString(), true, "Literal for semantic mapping")
.addOption("p", SettingType.PRINTER_CONFIG_PATH.toString(), true, "path to printer configuration file");
}
/**
* Parse command line parameters.
* @param args The arguments from the commandline.
* @return A {@link Settings} object that represents the values from the command line parameters.
* @throws ParsingException On any underlying error.
*/
public final Settings parse(final String[] args) throws ParsingException {
org.apache.commons.cli.CommandLineParser parser = new DefaultParser();
CommandLine cmdLine;
try {
cmdLine = parser.parse(mOptions, args);
} catch (ParseException pe) {
throw new ParsingException("Could not parse command line", pe);
}
return new Settings(cmdLine);
}
/**
* Print usage information to the command line.
*/
public final void printHelp() {
HelpFormatter formatter = new HelpFormatter();
String headerForOptions = "Convert csv into braille";
String footerForOptions = "Report Issues to Leonard Kupper";
formatter.printHelp("braillegraphics", headerForOptions, mOptions, footerForOptions, true);
}
}
package de.tudresden.inf.mci.brailleplot.commandline;
/**
* Exception class.
* Indicates, some error has occurred while parsing the command line parameters.
* Most likely created by malformed user input.
* @author Georg Graßnick
* @version 2019.05.31
*/
public class ParsingException extends Exception {
public ParsingException() { }
public ParsingException(final String message) {
super(message);
}
public ParsingException(final Throwable cause) {
super(cause);
}
public ParsingException(final String message, final Throwable cause) {
super(message, cause);
}
}
package de.tudresden.inf.mci.brailleplot.commandline;
/**
* Represents all possible parsed options parsed from the command line.
* @author Georg Graßnick
* @version 2019.05.31
*/
public enum SettingType {
DISPLAY_HELP("help"),
CSV_LOCATION("csv-path"),
PRINTER_CONFIG_PATH("printer-config-path"),
SEMANTIC_MAPPING("semantic-mapping");
private final String mName;
SettingType(final String name) {
this.mName = name;
}
static SettingType fromString(final String s) {
switch (s) {
case "help":
return DISPLAY_HELP;
case "csv-path":
return CSV_LOCATION;
case "printer-config-path":
return PRINTER_CONFIG_PATH;
case "semantic-mapping":
return SEMANTIC_MAPPING;
default:
throw new IllegalArgumentException("Setting not available");
}
}
public String toString() {
return mName;
}
}
package de.tudresden.inf.mci.brailleplot.commandline;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
/**
* Encapsulates Settings for the Application from the command line.
* @author Georg Graßnick
* @version 2019.05.31
*/
public final class Settings implements SettingsReader, SettingsWriter {
private Map<SettingType, String> mSettings;
private final Logger mLogger = LoggerFactory.getLogger(this.getClass());
private static final String BOOL_TRUE = Boolean.toString(true);
private static final String BOOL_FALSE = Boolean.toString(false);
/**
* Constructor.
* @param cmdLine CommandLine object to take information from.
*/
Settings(final CommandLine cmdLine) {
mSettings = new HashMap<>();
setup(cmdLine);
}
/**
* Populates the Settings class with arguments from the command line.
* @param cmdLine {@link CommandLine} object to take take settings from.
*/
private void setup(final CommandLine cmdLine) {
for (Iterator<Option> it = cmdLine.iterator(); it.hasNext();) {
Option o = it.next();
if (o.hasArg()) {
SettingType type = SettingType.fromString(o.getLongOpt());
mSettings.put(type, o.getValue());
mLogger.trace("Added string \"{}\" with value \"{}\"", type, o.getValue());
} else {
mSettings.put(SettingType.fromString(o.getLongOpt()), BOOL_TRUE);
mLogger.trace("Added flag \"{}\" set to \"{}\"", SettingType.fromString(o.getLongOpt()), BOOL_TRUE);
}
}
}
/**
* Check if a specific setting is set.
* @param setting The requested setting.
* @return true if the parameter is set, else false.
*/
public boolean isPresent(final SettingType setting) {
return mSettings.containsKey(setting);
}
/**
* Get the value of a setting, if set.
* @param setting The requested Setting to request the value for.
* @return {@link Optional}{@literal <String>} if setting is set, or {@link Optional#empty()} if the requested setting
* was not specified by the user.
* Use {@link Settings#isPresent(SettingType)} to check the value of a boolean parameter.
*/
public Optional<String> getSetting(final SettingType setting) {
if (!mSettings.containsKey(setting)) {
return Optional.empty();
}
return Optional.of(mSettings.get(setting));
}
/**
* Get the boolean value of a setting, if set.
* @param setting The requested Setting to request the value for.
* @return {@link Optional}{@literal <Boolean>} if setting is set, or {@link Optional#empty()} if the requested setting
* was not specified by the user.
*/
public Optional<Boolean> isTrue(final SettingType setting) {
if (!mSettings.containsKey(setting)) {
return Optional.empty();
}
if (mSettings.get(setting).equals(BOOL_TRUE)) {
return Optional.of(true);
} else {
return Optional.of(false);
}
}
/**
* Set the value of a setting.
* @param setting {@link SettingType} the setting to be changed.
* @param value {@link String} The value to set.
*/
public void setSetting(final SettingType setting, final String value) {
mSettings.replace(setting, value);
}
/**
* Set the value of a setting to a specific {@link Boolean}.
* @param setting {@link SettingType} the setting to be changed.
* @param isTrue {@link String} The value to set.
*/
public void setSetting(final SettingType setting, final Boolean isTrue) {
if (isTrue) {
mSettings.replace(setting, BOOL_TRUE);
} else {
mSettings.replace(setting, BOOL_FALSE);
}
}
/**
* Delete the set value of a setting, if it is set.
* @param setting {@link SettingType} the setting to be removed.
*/
public void deleteSettingValue(final SettingType setting) {
mSettings.remove(setting);
}
}
package de.tudresden.inf.mci.brailleplot.commandline;
import java.util.Optional;
/**
* Supplies an interface for reading settings.
* @author Georg Graßnick
* @version 2019.06.01
*/
public interface SettingsReader {
Optional<String> getSetting(SettingType setting);
boolean isPresent(SettingType setting);
Optional<Boolean> isTrue(SettingType setting);
}
package de.tudresden.inf.mci.brailleplot.commandline;
/**
* Implementing classes are guaranteed to support manipulating settings.
* Currently, the implementation is not thread safe!
* @author Georg Graßnick
* @version 2019.06.01
*/
public interface SettingsWriter extends SettingsReader {
void setSetting(SettingType setting, String value);
void setSetting(SettingType setting, Boolean isTrue);
void deleteSettingValue(SettingType setting);
}
/**
* Responsible for command line parsing and the creation of an {@link de.tudresden.inf.mci.brailleplot.commandline.Settings} object
* which can be queried by {@link de.tudresden.inf.mci.brailleplot.commandline.SettingsReader}
* and manipulated by {@link de.tudresden.inf.mci.brailleplot.commandline.SettingsWriter}.
*/
package de.tudresden.inf.mci.brailleplot.commandline;
package de.tudresden.inf.mci.brailleplot.commandline;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.fail;
/**
* Tests the CommandlineParser and the querying of parameters of the Settings object.
*/
class CommandLineParserTest {
private CommandLineParser commandLineParser = new CommandLineParser();
@Test
void testParseLegalArgs() {
String[] args = {"-h", "--csv-path", "foobar"};
Assertions.assertDoesNotThrow(() -> {commandLineParser.parse(args);});
}
@Test
void testIllegalArgs() {
String[] args = {"-h --foobar"};
Assertions.assertThrows(ParsingException.class, () -> {commandLineParser.parse(args);});
}
@Test
void testEmptyArgs() {
String[] args = {""};
Assertions.assertDoesNotThrow(() -> {commandLineParser.parse(args);});
}
@Test
void testBoolFlagRecognized() {
String[] args = {"-h"};
SettingsReader settings;
try {
settings = commandLineParser.parse(args);
} catch (ParsingException pe) {
fail();
return; // Never executed, satisfy compiler
}
Optional<Boolean> flag = settings.isTrue(SettingType.DISPLAY_HELP);
Assertions.assertTrue(flag.isPresent());
Assertions.assertTrue(flag.get());
}
@Test
void testBoolFlagCorrectlyNotRecognized() {
String[] args = {""};
SettingsReader settings;
try {
settings = commandLineParser.parse(args);
} catch (ParsingException pe) {
fail();
return; // Never executed, satisfy compiler
}
Optional<Boolean> flag = settings.isTrue(SettingType.DISPLAY_HELP);
Assertions.assertFalse(flag.isPresent());
}
@Test
void testParameterRecognized() {
final String param = "xyz";
String[] args = {"--csv-path", param};
SettingsReader settings;
try {
settings = commandLineParser.parse(args);
} catch (ParsingException pe) {
fail();
return; // Never executed, satisfy compiler
}
Optional<String> flag = settings.getSetting(SettingType.CSV_LOCATION);
Assertions.assertTrue(flag.isPresent());
Assertions.assertTrue(flag.get().equals(param));
}
@Test
void testParameterCorrectlyNotRecognized() {
String[] args = {""};
SettingsReader settings;
try {
settings = commandLineParser.parse(args);
} catch (ParsingException pe) {
fail();
return; // Never executed, satisfy compiler
}
Optional<String> flag = settings.getSetting(SettingType.CSV_LOCATION);
Assertions.assertFalse(flag.isPresent());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment