From bc6f13289b019ee8caee20d70d19e6f538230338 Mon Sep 17 00:00:00 2001
From: parthiv39731 <70740707+parthiv39731@users.noreply.github.com>
Date: Mon, 4 Mar 2024 21:18:10 +0530
Subject: [PATCH 1/3] BAEL-7618, Intro to the Apache Commons CLI
---
libraries-cli/pom.xml | 6 +
.../commonscli/CommonsCliUnitTest.java | 176 ++++++++++++++++++
2 files changed, 182 insertions(+)
create mode 100644 libraries-cli/src/test/java/com/baeldung/commonscli/CommonsCliUnitTest.java
diff --git a/libraries-cli/pom.xml b/libraries-cli/pom.xml
index d204f3c735..31940c0c92 100644
--- a/libraries-cli/pom.xml
+++ b/libraries-cli/pom.xml
@@ -50,6 +50,11 @@
lombok
${lombok.version}
+
+ commons-cli
+ commons-cli
+ ${commons-cli.version}
+
@@ -62,6 +67,7 @@
4.7.0
1.78
2.7.2
+ 1.6.0
2.7.8
5.3.25
diff --git a/libraries-cli/src/test/java/com/baeldung/commonscli/CommonsCliUnitTest.java b/libraries-cli/src/test/java/com/baeldung/commonscli/CommonsCliUnitTest.java
new file mode 100644
index 0000000000..6d99e4a440
--- /dev/null
+++ b/libraries-cli/src/test/java/com/baeldung/commonscli/CommonsCliUnitTest.java
@@ -0,0 +1,176 @@
+package com.baeldung.commonscli;
+
+import org.apache.commons.cli.AlreadySelectedException;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.MissingArgumentException;
+import org.apache.commons.cli.MissingOptionException;
+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 static org.junit.jupiter.api.Assertions.*;
+
+import org.apache.commons.cli.UnrecognizedOptionException;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CommonsCliUnitTest {
+ Logger logger = LoggerFactory.getLogger(CommonsCliUnitTest.class);
+
+ @Test
+ void whenMutuallyExclusiveOptionsProvidedTogether_thenThrowAlreadySelectedException() {
+ Option interactiveOption = new Option("i", false, "Prompts the user before overwriting the existing files");
+ Option forceOption = new Option("f", false, "Overwrites the existing files without prompting");
+
+ OptionGroup optionGroup = new OptionGroup();
+ optionGroup.addOption(interactiveOption)
+ .addOption(forceOption);
+
+ Options options = new Options();
+ options.addOptionGroup(optionGroup);
+
+ String[] commandWithConflictingOptions = new String[]{"cp", "-i", "-f", "file1", "file2"};
+ CommandLineParser commandLineParser = new DefaultParser();
+ assertThrows(AlreadySelectedException.class, () -> {
+ try {
+ CommandLine commandLine = commandLineParser.parse(options, commandWithConflictingOptions);
+ } catch (ParseException e) {
+ assertTrue(e instanceof AlreadySelectedException);
+ handleException(new RuntimeException(e));
+ throw e;
+ }
+ });
+ }
+
+ @Test
+ void whenMandatoryOptionMissing_thenThrowMissingOptionException() {
+ Options options = createOptions();
+ String[] commandWithMissingMandatoryOption = new String[]{"-h", "PGSERVER", "-U", "postgres"};
+ CommandLineParser commandLineParser = new DefaultParser();
+ assertThrows(MissingOptionException.class, () -> {
+ try {
+ CommandLine commandLine = commandLineParser.parse(options, commandWithMissingMandatoryOption);
+ } catch (ParseException e) {
+ assertTrue(e instanceof MissingOptionException);
+ handleException(new RuntimeException(e));
+ throw e;
+ }
+ });
+ }
+
+ @Test
+ void whenOptionArgumentIsMissing_thenThrowMissingArgumentException() {
+ Options options = createOptions();
+ String[] commandWithOptionArgumentOption = new String[]{"-h", "PGSERVER", "-U", "postgres", "-d"};
+ CommandLineParser commandLineParser = new DefaultParser();
+ assertThrowsExactly(MissingArgumentException.class, () -> {
+ try {
+ CommandLine commandLine = commandLineParser.parse(options, commandWithOptionArgumentOption);
+ } catch (ParseException e) {
+ assertTrue(e instanceof MissingArgumentException);
+ handleException(new RuntimeException(e));
+ throw e;
+ }
+ });
+ }
+
+ @Test
+ void whenUnrecognizedOptionProvided_thenThrowUnrecognizedOptionException() {
+ Options options = createOptions();
+ String[] commandWithIncorrectOption = new String[]{"-h", "PGSERVER", "-U", "postgres", "-d", "empDB", "-y"};
+ CommandLineParser commandLineParser = new DefaultParser();
+ assertThrows(UnrecognizedOptionException.class, () -> {
+ try {
+ CommandLine commandLine = commandLineParser.parse(options, commandWithIncorrectOption);
+ } catch (ParseException e) {
+ assertTrue(e instanceof UnrecognizedOptionException);
+ handleException(new RuntimeException(e));
+ throw e;
+ }
+ });
+ }
+
+ private void handleException(RuntimeException e) {
+ logger.error("handle exception:" + e.getMessage());
+ }
+
+ @Test
+ void whenNeedHelp_thenPrintHelp() {
+ HelpFormatter helpFormatter = new HelpFormatter();
+ Options options = createOptions();
+ options.addOption("?", "help", false, "Display help information");
+ helpFormatter.printHelp("psql -U username -h host -d empDB", options);
+ }
+
+ @Test
+ void whenCliOptionProvided_thenParseAndExtractOptionAndArgumentValues() throws ParseException {
+
+ Options options = new Options();
+
+ Option hostOption = createOption("h", "host", "HOST","Database server host", false);
+ Option userNameOption = createOption("U", "username", "USERNAME", "Database user name", true);
+ Option dbNameOption = createOption("d", "dbName", "DBNAME", "Database name to connect to", true);
+
+ options.addOption(hostOption)
+ .addOption(dbNameOption)
+ .addOption(userNameOption);
+
+ String[] commandWithShortNameOptions = new String[] { "-h", "PGSERVER", "-U", "postgres", "-d", "empDB" };
+ parseThenProcessCommand(options, commandWithShortNameOptions, "h", "U", "d" );
+
+ String[] commandWithLongNameOptions = new String[] { "--username", "postgres", "--dbName", "empDB" };
+ parseThenProcessCommand(options, commandWithLongNameOptions, "host", "username", "dbName" );
+ }
+
+ private Options createOptions() {
+ Options options = new Options();
+
+ Option hostOption = createOption("h", "host", "HOST", "Database server host", true);
+ Option userNameOption = createOption("U", "username", "USERNAME", "Database user name", true);
+ Option dbNameOption = createOption("d", "dbName", "DBNAME", "Database name to connect to", true);
+
+ return options.addOption(hostOption)
+ .addOption(dbNameOption)
+ .addOption(userNameOption);
+ }
+
+ private void parseThenProcessCommand(Options options, String[] commandArgs, String hostOption,
+ String usernameOption, String dbNameOption) throws ParseException {
+ CommandLineParser commandLineParser = new DefaultParser();
+
+ CommandLine commandLine = commandLineParser.parse(options, commandArgs);
+ String hostname = commandLine.hasOption("h") ? commandLine.getOptionValue(hostOption) : "localhost";
+ String userName = commandLine.getOptionValue(usernameOption);
+ String dbName = commandLine.getOptionValue(dbNameOption);
+
+ if (commandLine.hasOption("h")) {
+ assertEquals("PGSERVER", hostname);
+ } else {
+ assertEquals("localhost", hostname);
+ }
+
+ assertEquals("postgres", userName);
+ assertEquals("empDB", dbName);
+ createConnection(hostname, userName, dbName);
+ }
+
+ private void createConnection(String host, String userName, String dbName) {
+ //call underlying service
+ }
+
+ private Option createOption(String shortName, String longName, String argName, String description, boolean required) {
+ return Option.builder(shortName)
+ .longOpt(longName)
+ .argName(argName)
+ .desc(description)
+ .hasArg()
+ .required(required)
+ .build();
+ }
+
+}
From af09ea71c8a0204bf97259d16d3df4e9b562d82d Mon Sep 17 00:00:00 2001
From: parthiv39731 <70740707+parthiv39731@users.noreply.github.com>
Date: Tue, 5 Mar 2024 00:27:45 +0530
Subject: [PATCH 2/3] BAEL-7618, Intro to the Apache Commons CLI
---
.../main/resources/common-cli-classdg.puml | 62 +++++++++++++++++++
1 file changed, 62 insertions(+)
create mode 100644 libraries-cli/src/main/resources/common-cli-classdg.puml
diff --git a/libraries-cli/src/main/resources/common-cli-classdg.puml b/libraries-cli/src/main/resources/common-cli-classdg.puml
new file mode 100644
index 0000000000..1212b7d563
--- /dev/null
+++ b/libraries-cli/src/main/resources/common-cli-classdg.puml
@@ -0,0 +1,62 @@
+@startuml
+hide empty attributes
+skinparam Handwritten false
+skinparam ClassBorderColor black
+skinparam BackgroundColor #fffce8/#f8f9fa
+skinparam class {
+ ArrowColor SeaGreen
+ BackgroundColor #fffce8
+}
+
+interface CommandLineParser {
+ +parse():CommandLine
+}
+class CommandLine {
+ +getOptionValue():String
+ +hasOption():boolean
+}
+class DefaultParser {
+ +parse():CommandLine
+}
+
+class OptionGroup {
+ +addOption():OptionGroup
+}
+class Options {
+ +addOptions():Options
+ +addOptionGroup():Options
+ +hasOption():boolean
+}
+
+class Option {
+ +Option.Builder
+}
+
+
+class HelpFormatter {
+ +printHelp()
+}
+
+class MissingOptionException
+class MissingArgumentException
+class UnrecognizedOptionException
+class AlreadySelectedException
+class ParseException
+
+HelpFormatter -down-> Options:uses
+Options -right-> Option:uses
+Options -up-> OptionGroup:uses
+OptionGroup -down-> Option:uses
+
+CommandLineParser -up-> Options:uses
+DefaultParser -up-|> CommandLineParser:implements
+
+ParseException -up-|> AlreadySelectedException:implements
+ParseException -up-|> MissingOptionException:implements
+ParseException -down-|> MissingArgumentException:implements
+ParseException -down-|> UnrecognizedOptionException:implements
+
+CommandLineParser -left-> ParseException:throws
+CommandLineParser -right-> CommandLine:creates
+
+@enduml
\ No newline at end of file
From b7de895554a79c18a9a9138f98b31a55c1381122 Mon Sep 17 00:00:00 2001
From: parthiv39731 <70740707+parthiv39731@users.noreply.github.com>
Date: Wed, 6 Mar 2024 23:10:26 +0530
Subject: [PATCH 3/3] BAEL-7618, Intro to the Apache Commons CLI
---
libraries-cli/src/main/resources/common-cli-classdg.puml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libraries-cli/src/main/resources/common-cli-classdg.puml b/libraries-cli/src/main/resources/common-cli-classdg.puml
index 1212b7d563..b7578a85f5 100644
--- a/libraries-cli/src/main/resources/common-cli-classdg.puml
+++ b/libraries-cli/src/main/resources/common-cli-classdg.puml
@@ -51,10 +51,10 @@ OptionGroup -down-> Option:uses
CommandLineParser -up-> Options:uses
DefaultParser -up-|> CommandLineParser:implements
-ParseException -up-|> AlreadySelectedException:implements
-ParseException -up-|> MissingOptionException:implements
-ParseException -down-|> MissingArgumentException:implements
-ParseException -down-|> UnrecognizedOptionException:implements
+ParseException <|-up- AlreadySelectedException:implements
+ParseException <|-up- MissingOptionException:implements
+ParseException <|-down- MissingArgumentException:implements
+ParseException <|-down- UnrecognizedOptionException:implements
CommandLineParser -left-> ParseException:throws
CommandLineParser -right-> CommandLine:creates