Skip to content

Commit de3fc4d

Browse files
Priyank Srivastavaashleyfrieze
authored andcommitted
BAEL 3320 JCommander (eugenp#7971)
* init jcommander * add model layer jcommander app * service scaffolding * init jcommander cli layer * wire up services and commands * splitter impl; validator impl; tests and cleanup * cleanup pom * integration tests * fix uuid validator example * optimise uuid regex; if-else to switch * review comments * fix builder formatting * change list assertion in fetch charges tests * missing minor edit * move to new module libraries-3 * rm unwanted files
1 parent 0d25f15 commit de3fc4d

21 files changed

+823
-0
lines changed

libraries-3/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## Libraries-3
2+
3+
This module contains articles about various Java libraries.
4+
These are small libraries that are relatively easy to use and do not require any separate module of their own.
5+
6+
The code examples related to different libraries are each in their own module.
7+
8+
Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-modules) we already have separate modules. Please make sure to have a look at the existing modules in such cases.
9+

libraries-3/pom.xml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<artifactId>libraries-3</artifactId>
7+
<name>libraries-3</name>
8+
9+
<parent>
10+
<groupId>com.baeldung</groupId>
11+
<artifactId>parent-modules</artifactId>
12+
<version>1.0.0-SNAPSHOT</version>
13+
</parent>
14+
15+
<repositories>
16+
<repository>
17+
<id>jboss-public-repository-group</id>
18+
<name>JBoss Public Repository Group</name>
19+
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
20+
<releases>
21+
<enabled>true</enabled>
22+
<updatePolicy>never</updatePolicy>
23+
</releases>
24+
<snapshots>
25+
<enabled>true</enabled>
26+
<updatePolicy>daily</updatePolicy>
27+
</snapshots>
28+
</repository>
29+
</repositories>
30+
31+
<dependencies>
32+
<dependency>
33+
<groupId>com.beust</groupId>
34+
<artifactId>jcommander</artifactId>
35+
<version>${jcommander.version}</version>
36+
</dependency>
37+
<dependency>
38+
<groupId>org.projectlombok</groupId>
39+
<artifactId>lombok</artifactId>
40+
<version>${lombok.version}</version>
41+
</dependency>
42+
</dependencies>
43+
44+
<properties>
45+
<jcommander.version>1.78</jcommander.version>
46+
<lombok.version>1.18.6</lombok.version>
47+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
48+
<maven.compiler.target>1.8</maven.compiler.target>
49+
<maven.compiler.source>1.8</maven.compiler.source>
50+
</properties>
51+
</project>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.baeldung.jcommander.helloworld;
2+
3+
import com.beust.jcommander.JCommander;
4+
import com.beust.jcommander.Parameter;
5+
6+
public class HelloWorldApp {
7+
8+
/*
9+
* Execute:
10+
* mvn exec:java -Dexec.mainClass=com.baeldung.jcommander.helloworld.HelloWorldApp -q \
11+
* -Dexec.args="--name JavaWorld"
12+
*/
13+
public static void main(String[] args) {
14+
HelloWorldArgs jArgs = new HelloWorldArgs();
15+
JCommander helloCmd = JCommander
16+
.newBuilder()
17+
.addObject(jArgs)
18+
.build();
19+
20+
helloCmd.parse(args);
21+
System.out.println("Hello " + jArgs.getName());
22+
}
23+
}
24+
25+
class HelloWorldArgs {
26+
27+
@Parameter(
28+
names = "--name",
29+
description = "User name",
30+
required = true
31+
)
32+
private String name;
33+
34+
public String getName() {
35+
return name;
36+
}
37+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.baeldung.jcommander.usagebilling;
2+
3+
import com.baeldung.jcommander.usagebilling.cli.UsageBasedBilling;
4+
5+
public class UsageBasedBillingApp {
6+
7+
/*
8+
* Entry-point: invokes the cli passing the command-line args
9+
*
10+
* Invoking "Submit" sub-command:
11+
* mvn exec:java \
12+
-Dexec.mainClass=com.baeldung.jcommander.usagebilling.UsageBasedBillingApp -q \
13+
-Dexec.args="submit --customer cb898e7a-f2a0-46d2-9a09-531f1cee1839 --subscription subscriptionPQRMN001 --pricing-type PRE_RATED --timestamp 2019-10-03T10:58:00 --quantity 7 --price 24.56"
14+
*
15+
* Invoking "Fetch" sub-command:
16+
* mvn exec:java \
17+
-Dexec.mainClass=com.baeldung.jcommander.usagebilling.UsageBasedBillingApp -q \
18+
-Dexec.args="fetch --customer cb898e7a-f2a0-46d2-9a09-531f1cee1839 --subscription subscriptionPQRMN001 subscriptionPQRMN002 subscriptionPQRMN003 --itemized"
19+
*/
20+
public static void main(String[] args) {
21+
new UsageBasedBilling().run(args);
22+
}
23+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.baeldung.jcommander.usagebilling.cli;
2+
3+
import com.baeldung.jcommander.usagebilling.cli.splitter.ColonParameterSplitter;
4+
import com.baeldung.jcommander.usagebilling.cli.validator.UUIDValidator;
5+
import com.baeldung.jcommander.usagebilling.model.CurrentChargesRequest;
6+
import com.baeldung.jcommander.usagebilling.model.CurrentChargesResponse;
7+
import com.baeldung.jcommander.usagebilling.service.FetchCurrentChargesService;
8+
import com.beust.jcommander.Parameter;
9+
import com.beust.jcommander.Parameters;
10+
import lombok.Getter;
11+
12+
import java.util.List;
13+
14+
import static com.baeldung.jcommander.usagebilling.cli.UsageBasedBilling.*;
15+
import static com.baeldung.jcommander.usagebilling.service.FetchCurrentChargesService.getDefault;
16+
17+
@Parameters(
18+
commandNames = { FETCH_CMD },
19+
commandDescription = "Fetch charges for a customer in the current month, can be itemized or aggregated"
20+
)
21+
@Getter
22+
class FetchCurrentChargesCommand {
23+
24+
FetchCurrentChargesCommand() {
25+
}
26+
27+
private FetchCurrentChargesService service = getDefault();
28+
29+
@Parameter(names = "--help", help = true)
30+
private boolean help;
31+
32+
@Parameter(
33+
names = { "--customer", "-C" },
34+
description = "Id of the Customer who's using the services",
35+
validateWith = UUIDValidator.class,
36+
order = 1,
37+
required = true
38+
)
39+
private String customerId;
40+
41+
@Parameter(
42+
names = { "--subscription", "-S" },
43+
description = "Filter charges for specific subscription Ids, includes all subscriptions if no value is specified",
44+
variableArity = true,
45+
splitter = ColonParameterSplitter.class,
46+
order = 2
47+
)
48+
private List<String> subscriptionIds;
49+
50+
@Parameter(
51+
names = { "--itemized" },
52+
description = "Whether the response should contain breakdown by subscription, only aggregate values are returned by default",
53+
order = 3
54+
)
55+
private boolean itemized;
56+
57+
void fetch() {
58+
CurrentChargesRequest req = CurrentChargesRequest.builder()
59+
.customerId(customerId)
60+
.subscriptionIds(subscriptionIds)
61+
.itemized(itemized)
62+
.build();
63+
64+
CurrentChargesResponse response = service.fetch(req);
65+
System.out.println(response);
66+
}
67+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.baeldung.jcommander.usagebilling.cli;
2+
3+
import com.baeldung.jcommander.usagebilling.cli.converter.ISO8601TimestampConverter;
4+
import com.baeldung.jcommander.usagebilling.cli.validator.UUIDValidator;
5+
import com.baeldung.jcommander.usagebilling.model.UsageRequest;
6+
import com.baeldung.jcommander.usagebilling.model.UsageRequest.PricingType;
7+
import com.baeldung.jcommander.usagebilling.service.SubmitUsageService;
8+
import com.beust.jcommander.Parameter;
9+
import com.beust.jcommander.Parameters;
10+
import lombok.Getter;
11+
12+
import java.math.BigDecimal;
13+
import java.time.Instant;
14+
15+
import static com.baeldung.jcommander.usagebilling.cli.UsageBasedBilling.*;
16+
import static com.baeldung.jcommander.usagebilling.service.SubmitUsageService.getDefault;
17+
18+
@Parameters(
19+
commandNames = { SUBMIT_CMD },
20+
commandDescription = "Submit usage for a given customer and subscription, accepts one usage item"
21+
)
22+
@Getter
23+
class SubmitUsageCommand {
24+
25+
SubmitUsageCommand() {
26+
}
27+
28+
private SubmitUsageService service = getDefault();
29+
30+
@Parameter(names = "--help", help = true)
31+
private boolean help;
32+
33+
@Parameter(
34+
names = { "--customer", "-C" },
35+
description = "Id of the Customer who's using the services",
36+
validateWith = UUIDValidator.class,
37+
order = 1,
38+
required = true
39+
)
40+
private String customerId;
41+
42+
@Parameter(
43+
names = { "--subscription", "-S" },
44+
description = "Id of the Subscription that was purchased",
45+
order = 2,
46+
required = true
47+
)
48+
private String subscriptionId;
49+
50+
@Parameter(
51+
names = { "--pricing-type", "-P" },
52+
description = "Pricing type of the usage reported",
53+
order = 3,
54+
required = true
55+
)
56+
private PricingType pricingType;
57+
58+
@Parameter(
59+
names = { "--quantity" },
60+
description = "Used quantity; reported quantity is added over the billing period",
61+
order = 3,
62+
required = true
63+
)
64+
private Integer quantity;
65+
66+
@Parameter(
67+
names = { "--timestamp" },
68+
description = "Timestamp of the usage event, must lie in the current billing period",
69+
converter = ISO8601TimestampConverter.class,
70+
order = 4,
71+
required = true
72+
)
73+
private Instant timestamp;
74+
75+
@Parameter(
76+
names = { "--price" },
77+
description = "If PRE_RATED, unit price to be applied per unit of usage quantity reported",
78+
order = 5
79+
)
80+
private BigDecimal price;
81+
82+
void submit() {
83+
84+
UsageRequest req = UsageRequest.builder()
85+
.customerId(customerId)
86+
.subscriptionId(subscriptionId)
87+
.pricingType(pricingType)
88+
.quantity(quantity)
89+
.timestamp(timestamp)
90+
.price(price)
91+
.build();
92+
93+
String reqId = service.submit(req);
94+
System.out.println("Generated Request Id for reference: " + reqId);
95+
}
96+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.baeldung.jcommander.usagebilling.cli;
2+
3+
import com.beust.jcommander.JCommander;
4+
import com.beust.jcommander.ParameterException;
5+
import com.beust.jcommander.UnixStyleUsageFormatter;
6+
7+
public class UsageBasedBilling {
8+
9+
static final String SUBMIT_CMD = "submit";
10+
static final String FETCH_CMD = "fetch";
11+
12+
private JCommander jCommander;
13+
private SubmitUsageCommand submitUsageCmd;
14+
private FetchCurrentChargesCommand fetchChargesCmd;
15+
16+
public UsageBasedBilling() {
17+
this.submitUsageCmd = new SubmitUsageCommand();
18+
this.fetchChargesCmd = new FetchCurrentChargesCommand();
19+
jCommander = JCommander.newBuilder()
20+
.addObject(this)
21+
.addCommand(submitUsageCmd)
22+
.addCommand(fetchChargesCmd)
23+
.build();
24+
25+
setUsageFormatter(SUBMIT_CMD);
26+
setUsageFormatter(FETCH_CMD);
27+
}
28+
29+
public void run(String[] args) {
30+
String parsedCmdStr;
31+
try {
32+
jCommander.parse(args);
33+
parsedCmdStr = jCommander.getParsedCommand();
34+
35+
switch (parsedCmdStr) {
36+
case SUBMIT_CMD:
37+
if (submitUsageCmd.isHelp()) {
38+
getSubCommandHandle(SUBMIT_CMD).usage();
39+
}
40+
System.out.println("Parsing usage request...");
41+
submitUsageCmd.submit();
42+
break;
43+
44+
case FETCH_CMD:
45+
if (fetchChargesCmd.isHelp()) {
46+
getSubCommandHandle(SUBMIT_CMD).usage();
47+
}
48+
System.out.println("Preparing fetch query...");
49+
fetchChargesCmd.fetch();
50+
51+
break;
52+
53+
default:
54+
System.err.println("Invalid command: " + parsedCmdStr);
55+
}
56+
} catch (ParameterException e) {
57+
System.err.println(e.getLocalizedMessage());
58+
parsedCmdStr = jCommander.getParsedCommand();
59+
if (parsedCmdStr != null) {
60+
getSubCommandHandle(parsedCmdStr).usage();
61+
} else {
62+
jCommander.usage();
63+
}
64+
}
65+
}
66+
67+
private JCommander getSubCommandHandle(String command) {
68+
JCommander cmd = jCommander.getCommands().get(command);
69+
70+
if (cmd == null) {
71+
System.err.println("Invalid command: " + command);
72+
}
73+
return cmd;
74+
}
75+
76+
private void setUsageFormatter(String subCommand) {
77+
JCommander cmd = getSubCommandHandle(subCommand);
78+
cmd.setUsageFormatter(new UnixStyleUsageFormatter(cmd));
79+
}
80+
}

0 commit comments

Comments
 (0)