[JAVA-22519] Created new module libraries-stream and added 5 articles (#15403)
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.airline;
|
||||
|
||||
import com.github.rvesse.airline.annotations.Cli;
|
||||
import com.github.rvesse.airline.help.Help;
|
||||
|
||||
@Cli(name = "baeldung-cli",
|
||||
description = "Baeldung Airline Tutorial",
|
||||
defaultCommand = Help.class,
|
||||
commands = { DatabaseSetupCommand.class, LoggingCommand.class, Help.class })
|
||||
public class CommandLine {
|
||||
|
||||
public static void main(String[] args) {
|
||||
com.github.rvesse.airline.Cli<Runnable> cli = new com.github.rvesse.airline.Cli<>(CommandLine.class);
|
||||
Runnable cmd = cli.parse(args);
|
||||
cmd.run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.baeldung.airline;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.github.rvesse.airline.HelpOption;
|
||||
import com.github.rvesse.airline.annotations.Command;
|
||||
import com.github.rvesse.airline.annotations.Option;
|
||||
import com.github.rvesse.airline.annotations.OptionType;
|
||||
import com.github.rvesse.airline.annotations.restrictions.AllowedRawValues;
|
||||
import com.github.rvesse.airline.annotations.restrictions.MutuallyExclusiveWith;
|
||||
import com.github.rvesse.airline.annotations.restrictions.Pattern;
|
||||
import com.github.rvesse.airline.annotations.restrictions.RequiredOnlyIf;
|
||||
|
||||
@Command(name = "setup-db", description = "Setup our database")
|
||||
public class DatabaseSetupCommand implements Runnable {
|
||||
@Inject
|
||||
private HelpOption<DatabaseSetupCommand> help;
|
||||
|
||||
@Option(type = OptionType.COMMAND,
|
||||
name = {"-d", "--database"},
|
||||
description = "Type of RDBMS.",
|
||||
title = "RDBMS type: mysql|postgresql|mongodb")
|
||||
@AllowedRawValues(allowedValues = { "mysql", "postgres", "mongodb" })
|
||||
protected String rdbmsMode = "mysql";
|
||||
|
||||
@Option(type = OptionType.COMMAND,
|
||||
name = {"--rdbms:url", "--url"},
|
||||
description = "URL to use for connection to RDBMS.",
|
||||
title = "RDBMS URL")
|
||||
@MutuallyExclusiveWith(tag="mode")
|
||||
@Pattern(pattern="^(http://.*):(d*)(.*)u=(.*)&p=(.*)")
|
||||
protected String rdbmsUrl = "";
|
||||
|
||||
@Option(type = OptionType.COMMAND,
|
||||
name = {"--rdbms:host", "--host"},
|
||||
description = "Host to use for connection to RDBMS.",
|
||||
title = "RDBMS host")
|
||||
@MutuallyExclusiveWith(tag="mode")
|
||||
protected String rdbmsHost = "";
|
||||
|
||||
@RequiredOnlyIf(names={"--rdbms:host", "--host"})
|
||||
@Option(type = OptionType.COMMAND,
|
||||
name = {"--rdbms:user", "-u", "--user"},
|
||||
description = "User for login to RDBMS.",
|
||||
title = "RDBMS user")
|
||||
protected String rdbmsUser;
|
||||
|
||||
@RequiredOnlyIf(names={"--rdbms:host", "--host"})
|
||||
@Option(type = OptionType.COMMAND,
|
||||
name = {"--rdbms:password", "--password"},
|
||||
description = "Password for login to RDBMS.",
|
||||
title = "RDBMS password")
|
||||
protected String rdbmsPassword;
|
||||
|
||||
@Option(type = OptionType.COMMAND,
|
||||
name = {"--driver", "--jars"},
|
||||
description = "List of drivers",
|
||||
title = "--driver <PATH_TO_YOUR_JAR> --driver <PATH_TO_YOUR_JAR>")
|
||||
protected List<String> jars = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
//skipping store our choices...
|
||||
if (!help.showHelpIfRequested()) {
|
||||
if(!"".equals(rdbmsHost)) {
|
||||
System.out.println("Connecting to database host: " + rdbmsHost);
|
||||
System.out.println("Credential: " + rdbmsUser + " / " + rdbmsPassword);
|
||||
} else {
|
||||
System.out.println("Connecting to database url: " + rdbmsUrl);
|
||||
}
|
||||
System.out.println(jars.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.airline;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.github.rvesse.airline.HelpOption;
|
||||
import com.github.rvesse.airline.annotations.Command;
|
||||
import com.github.rvesse.airline.annotations.Option;
|
||||
|
||||
@Command(name = "setup-log", description = "Setup our log")
|
||||
public class LoggingCommand implements Runnable {
|
||||
|
||||
@Inject
|
||||
private HelpOption<LoggingCommand> help;
|
||||
|
||||
@Option(name = { "-v", "--verbose" }, description = "Set log verbosity on/off")
|
||||
private boolean verbose = false;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
//skipping store user choice
|
||||
if (!help.showHelpIfRequested())
|
||||
System.out.println("Verbosity: " + verbose);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.baeldung.jcommander.helloworld;
|
||||
|
||||
import com.beust.jcommander.JCommander;
|
||||
import com.beust.jcommander.Parameter;
|
||||
|
||||
public class HelloWorldApp {
|
||||
|
||||
/*
|
||||
* Execute:
|
||||
* mvn exec:java -Dexec.mainClass=com.baeldung.jcommander.helloworld.HelloWorldApp -q \
|
||||
* -Dexec.args="--name JavaWorld"
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
HelloWorldArgs jArgs = new HelloWorldArgs();
|
||||
JCommander helloCmd = JCommander
|
||||
.newBuilder()
|
||||
.addObject(jArgs)
|
||||
.build();
|
||||
|
||||
helloCmd.parse(args);
|
||||
System.out.println("Hello " + jArgs.getName());
|
||||
}
|
||||
}
|
||||
|
||||
class HelloWorldArgs {
|
||||
|
||||
@Parameter(
|
||||
names = "--name",
|
||||
description = "User name",
|
||||
required = true
|
||||
)
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.jcommander.usagebilling;
|
||||
|
||||
import com.baeldung.jcommander.usagebilling.cli.UsageBasedBilling;
|
||||
|
||||
public class UsageBasedBillingApp {
|
||||
|
||||
/*
|
||||
* Entry-point: invokes the cli passing the command-line args
|
||||
*
|
||||
* Invoking "Submit" sub-command:
|
||||
* mvn exec:java \
|
||||
-Dexec.mainClass=com.baeldung.jcommander.usagebilling.UsageBasedBillingApp -q \
|
||||
-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"
|
||||
*
|
||||
* Invoking "Fetch" sub-command:
|
||||
* mvn exec:java \
|
||||
-Dexec.mainClass=com.baeldung.jcommander.usagebilling.UsageBasedBillingApp -q \
|
||||
-Dexec.args="fetch --customer cb898e7a-f2a0-46d2-9a09-531f1cee1839 --subscription subscriptionPQRMN001 subscriptionPQRMN002 subscriptionPQRMN003 --itemized"
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
new UsageBasedBilling().run(args);
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package com.baeldung.jcommander.usagebilling.cli;
|
||||
|
||||
import static com.baeldung.jcommander.usagebilling.cli.UsageBasedBilling.FETCH_CMD;
|
||||
import static com.baeldung.jcommander.usagebilling.service.FetchCurrentChargesService.getDefault;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.baeldung.jcommander.usagebilling.cli.splitter.ColonParameterSplitter;
|
||||
import com.baeldung.jcommander.usagebilling.cli.validator.UUIDValidator;
|
||||
import com.baeldung.jcommander.usagebilling.model.CurrentChargesRequest;
|
||||
import com.baeldung.jcommander.usagebilling.model.CurrentChargesResponse;
|
||||
import com.baeldung.jcommander.usagebilling.service.FetchCurrentChargesService;
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Parameters(
|
||||
commandNames = { FETCH_CMD },
|
||||
commandDescription = "Fetch charges for a customer in the current month, can be itemized or aggregated"
|
||||
)
|
||||
@Getter
|
||||
class FetchCurrentChargesCommand {
|
||||
|
||||
FetchCurrentChargesCommand() {
|
||||
}
|
||||
|
||||
private FetchCurrentChargesService service = getDefault();
|
||||
|
||||
@Parameter(names = "--help", help = true)
|
||||
private boolean help;
|
||||
|
||||
@Parameter(
|
||||
names = { "--customer", "-C" },
|
||||
description = "Id of the Customer who's using the services",
|
||||
validateWith = UUIDValidator.class,
|
||||
order = 1,
|
||||
required = true
|
||||
)
|
||||
private String customerId;
|
||||
|
||||
@Parameter(
|
||||
names = { "--subscription", "-S" },
|
||||
description = "Filter charges for specific subscription Ids, includes all subscriptions if no value is specified",
|
||||
variableArity = true,
|
||||
splitter = ColonParameterSplitter.class,
|
||||
order = 2
|
||||
)
|
||||
private List<String> subscriptionIds;
|
||||
|
||||
@Parameter(
|
||||
names = { "--itemized" },
|
||||
description = "Whether the response should contain breakdown by subscription, only aggregate values are returned by default",
|
||||
order = 3
|
||||
)
|
||||
private boolean itemized;
|
||||
|
||||
void fetch() {
|
||||
CurrentChargesRequest req = CurrentChargesRequest.builder()
|
||||
.customerId(customerId)
|
||||
.subscriptionIds(subscriptionIds)
|
||||
.itemized(itemized)
|
||||
.build();
|
||||
|
||||
CurrentChargesResponse response = service.fetch(req);
|
||||
System.out.println(response);
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package com.baeldung.jcommander.usagebilling.cli;
|
||||
|
||||
import static com.baeldung.jcommander.usagebilling.cli.UsageBasedBilling.SUBMIT_CMD;
|
||||
import static com.baeldung.jcommander.usagebilling.service.SubmitUsageService.getDefault;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
|
||||
import com.baeldung.jcommander.usagebilling.cli.converter.ISO8601TimestampConverter;
|
||||
import com.baeldung.jcommander.usagebilling.cli.validator.UUIDValidator;
|
||||
import com.baeldung.jcommander.usagebilling.model.UsageRequest;
|
||||
import com.baeldung.jcommander.usagebilling.model.UsageRequest.PricingType;
|
||||
import com.baeldung.jcommander.usagebilling.service.SubmitUsageService;
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Parameters(
|
||||
commandNames = { SUBMIT_CMD },
|
||||
commandDescription = "Submit usage for a given customer and subscription, accepts one usage item"
|
||||
)
|
||||
@Getter
|
||||
class SubmitUsageCommand {
|
||||
|
||||
SubmitUsageCommand() {
|
||||
}
|
||||
|
||||
private SubmitUsageService service = getDefault();
|
||||
|
||||
@Parameter(names = "--help", help = true)
|
||||
private boolean help;
|
||||
|
||||
@Parameter(
|
||||
names = { "--customer", "-C" },
|
||||
description = "Id of the Customer who's using the services",
|
||||
validateWith = UUIDValidator.class,
|
||||
order = 1,
|
||||
required = true
|
||||
)
|
||||
private String customerId;
|
||||
|
||||
@Parameter(
|
||||
names = { "--subscription", "-S" },
|
||||
description = "Id of the Subscription that was purchased",
|
||||
order = 2,
|
||||
required = true
|
||||
)
|
||||
private String subscriptionId;
|
||||
|
||||
@Parameter(
|
||||
names = { "--pricing-type", "-P" },
|
||||
description = "Pricing type of the usage reported",
|
||||
order = 3,
|
||||
required = true
|
||||
)
|
||||
private PricingType pricingType;
|
||||
|
||||
@Parameter(
|
||||
names = { "--quantity" },
|
||||
description = "Used quantity; reported quantity is added over the billing period",
|
||||
order = 3,
|
||||
required = true
|
||||
)
|
||||
private Integer quantity;
|
||||
|
||||
@Parameter(
|
||||
names = { "--timestamp" },
|
||||
description = "Timestamp of the usage event, must lie in the current billing period",
|
||||
converter = ISO8601TimestampConverter.class,
|
||||
order = 4,
|
||||
required = true
|
||||
)
|
||||
private Instant timestamp;
|
||||
|
||||
@Parameter(
|
||||
names = { "--price" },
|
||||
description = "If PRE_RATED, unit price to be applied per unit of usage quantity reported",
|
||||
order = 5
|
||||
)
|
||||
private BigDecimal price;
|
||||
|
||||
void submit() {
|
||||
|
||||
UsageRequest req = UsageRequest.builder()
|
||||
.customerId(customerId)
|
||||
.subscriptionId(subscriptionId)
|
||||
.pricingType(pricingType)
|
||||
.quantity(quantity)
|
||||
.timestamp(timestamp)
|
||||
.price(price)
|
||||
.build();
|
||||
|
||||
String reqId = service.submit(req);
|
||||
System.out.println("Generated Request Id for reference: " + reqId);
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package com.baeldung.jcommander.usagebilling.cli;
|
||||
|
||||
import com.beust.jcommander.JCommander;
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.beust.jcommander.UnixStyleUsageFormatter;
|
||||
|
||||
public class UsageBasedBilling {
|
||||
|
||||
static final String SUBMIT_CMD = "submit";
|
||||
static final String FETCH_CMD = "fetch";
|
||||
|
||||
private JCommander jCommander;
|
||||
private SubmitUsageCommand submitUsageCmd;
|
||||
private FetchCurrentChargesCommand fetchChargesCmd;
|
||||
|
||||
public UsageBasedBilling() {
|
||||
this.submitUsageCmd = new SubmitUsageCommand();
|
||||
this.fetchChargesCmd = new FetchCurrentChargesCommand();
|
||||
jCommander = JCommander.newBuilder()
|
||||
.addObject(this)
|
||||
.addCommand(submitUsageCmd)
|
||||
.addCommand(fetchChargesCmd)
|
||||
.build();
|
||||
|
||||
setUsageFormatter(SUBMIT_CMD);
|
||||
setUsageFormatter(FETCH_CMD);
|
||||
}
|
||||
|
||||
public void run(String[] args) {
|
||||
String parsedCmdStr;
|
||||
try {
|
||||
jCommander.parse(args);
|
||||
parsedCmdStr = jCommander.getParsedCommand();
|
||||
|
||||
switch (parsedCmdStr) {
|
||||
case SUBMIT_CMD:
|
||||
if (submitUsageCmd.isHelp()) {
|
||||
getSubCommandHandle(SUBMIT_CMD).usage();
|
||||
}
|
||||
System.out.println("Parsing usage request...");
|
||||
submitUsageCmd.submit();
|
||||
break;
|
||||
|
||||
case FETCH_CMD:
|
||||
if (fetchChargesCmd.isHelp()) {
|
||||
getSubCommandHandle(SUBMIT_CMD).usage();
|
||||
}
|
||||
System.out.println("Preparing fetch query...");
|
||||
fetchChargesCmd.fetch();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
System.err.println("Invalid command: " + parsedCmdStr);
|
||||
}
|
||||
} catch (ParameterException e) {
|
||||
System.err.println(e.getLocalizedMessage());
|
||||
parsedCmdStr = jCommander.getParsedCommand();
|
||||
if (parsedCmdStr != null) {
|
||||
getSubCommandHandle(parsedCmdStr).usage();
|
||||
} else {
|
||||
jCommander.usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JCommander getSubCommandHandle(String command) {
|
||||
JCommander cmd = jCommander.getCommands().get(command);
|
||||
|
||||
if (cmd == null) {
|
||||
System.err.println("Invalid command: " + command);
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
private void setUsageFormatter(String subCommand) {
|
||||
JCommander cmd = getSubCommandHandle(subCommand);
|
||||
cmd.setUsageFormatter(new UnixStyleUsageFormatter(cmd));
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.baeldung.jcommander.usagebilling.cli.converter;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.beust.jcommander.converters.BaseConverter;
|
||||
|
||||
public class ISO8601TimestampConverter extends BaseConverter<Instant> {
|
||||
|
||||
private static final DateTimeFormatter TS_FORMATTER = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss");
|
||||
|
||||
public ISO8601TimestampConverter(String optionName) {
|
||||
super(optionName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant convert(String value) {
|
||||
try {
|
||||
return LocalDateTime
|
||||
.parse(value, TS_FORMATTER)
|
||||
.atOffset(ZoneOffset.UTC)
|
||||
.toInstant();
|
||||
} catch (DateTimeParseException e) {
|
||||
throw new ParameterException(getErrorString(value, format("an ISO-8601 formatted timestamp (%s)", TS_FORMATTER.toString())));
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.jcommander.usagebilling.cli.splitter;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.beust.jcommander.converters.IParameterSplitter;
|
||||
|
||||
public class ColonParameterSplitter implements IParameterSplitter {
|
||||
|
||||
@Override
|
||||
public List<String> split(String value) {
|
||||
return asList(value.split(":"));
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.jcommander.usagebilling.cli.validator;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.beust.jcommander.IParameterValidator;
|
||||
import com.beust.jcommander.ParameterException;
|
||||
|
||||
public class UUIDValidator implements IParameterValidator {
|
||||
|
||||
private static final String UUID_REGEX =
|
||||
"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}";
|
||||
|
||||
@Override
|
||||
public void validate(String name, String value) throws ParameterException {
|
||||
if (!isValidUUID(value)) {
|
||||
throw new ParameterException(
|
||||
"String parameter " + value + " is not a valid UUID.");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidUUID(String value) {
|
||||
return Pattern
|
||||
.compile(UUID_REGEX)
|
||||
.matcher(value).matches();
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.jcommander.usagebilling.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
@Builder
|
||||
@Getter
|
||||
public class CurrentChargesRequest {
|
||||
|
||||
private String customerId;
|
||||
private List<String> subscriptionIds;
|
||||
private boolean itemized;
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package com.baeldung.jcommander.usagebilling.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
@Builder
|
||||
@Getter
|
||||
public class CurrentChargesResponse {
|
||||
|
||||
private String customerId;
|
||||
private BigDecimal amountDue;
|
||||
private List<LineItem> lineItems;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb
|
||||
.append("Current Month Charges: {")
|
||||
.append("\n\tcustomer: ")
|
||||
.append(this.customerId)
|
||||
.append("\n\ttotalAmountDue: ")
|
||||
.append(this.amountDue.setScale(2, RoundingMode.HALF_UP))
|
||||
.append("\n\tlineItems: [");
|
||||
|
||||
for (LineItem li : this.lineItems) {
|
||||
sb
|
||||
.append("\n\t\t{")
|
||||
.append("\n\t\t\tsubscription: ")
|
||||
.append(li.subscriptionId)
|
||||
.append("\n\t\t\tamount: ")
|
||||
.append(li.amount.setScale(2, RoundingMode.HALF_UP))
|
||||
.append("\n\t\t\tquantity: ")
|
||||
.append(li.quantity)
|
||||
.append("\n\t\t},");
|
||||
}
|
||||
|
||||
sb.append("\n\t]\n}\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
@Builder
|
||||
@Getter
|
||||
public static class LineItem {
|
||||
|
||||
private String subscriptionId;
|
||||
private BigDecimal amount;
|
||||
private Integer quantity;
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.baeldung.jcommander.usagebilling.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
@AllArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
@Builder
|
||||
@Getter
|
||||
public class UsageRequest {
|
||||
|
||||
private String customerId;
|
||||
private String subscriptionId;
|
||||
private PricingType pricingType;
|
||||
private Integer quantity;
|
||||
private BigDecimal price;
|
||||
private Instant timestamp;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb
|
||||
.append("\nUsage: {")
|
||||
.append("\n\tcustomer: ")
|
||||
.append(this.customerId)
|
||||
.append("\n\tsubscription: ")
|
||||
.append(this.subscriptionId)
|
||||
.append("\n\tquantity: ")
|
||||
.append(this.quantity)
|
||||
.append("\n\ttimestamp: ")
|
||||
.append(this.timestamp)
|
||||
.append("\n\tpricingType: ")
|
||||
.append(this.pricingType);
|
||||
|
||||
if (PricingType.PRE_RATED == this.pricingType) {
|
||||
sb
|
||||
.append("\n\tpreRatedAt: ")
|
||||
.append(this.price);
|
||||
}
|
||||
|
||||
sb.append("\n}\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public enum PricingType {
|
||||
PRE_RATED, UNRATED
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package com.baeldung.jcommander.usagebilling.service;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Arrays.fill;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.concurrent.ThreadLocalRandom.current;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.baeldung.jcommander.usagebilling.model.CurrentChargesRequest;
|
||||
import com.baeldung.jcommander.usagebilling.model.CurrentChargesResponse;
|
||||
import com.baeldung.jcommander.usagebilling.model.CurrentChargesResponse.LineItem;
|
||||
|
||||
class DefaultFetchCurrentChargesService implements FetchCurrentChargesService {
|
||||
|
||||
@Override
|
||||
public CurrentChargesResponse fetch(CurrentChargesRequest request) {
|
||||
List<String> subscriptions = request.getSubscriptionIds();
|
||||
|
||||
if (subscriptions == null || subscriptions.isEmpty()) {
|
||||
System.out.println("Fetching ALL charges for customer: " + request.getCustomerId());
|
||||
subscriptions = mockSubscriptions();
|
||||
|
||||
} else {
|
||||
System.out.println(format("Fetching charges for customer: %s and subscriptions: %s", request.getCustomerId(), subscriptions));
|
||||
}
|
||||
|
||||
CurrentChargesResponse charges = mockCharges(request.getCustomerId(), subscriptions, request.isItemized());
|
||||
System.out.println("Fetched charges...");
|
||||
return charges;
|
||||
}
|
||||
|
||||
private CurrentChargesResponse mockCharges(String customerId, List<String> subscriptions, boolean itemized) {
|
||||
List<LineItem> lineItems = mockLineItems(subscriptions);
|
||||
BigDecimal amountDue = lineItems
|
||||
.stream()
|
||||
.map(li -> li.getAmount())
|
||||
.reduce(new BigDecimal("0"), BigDecimal::add);
|
||||
|
||||
return CurrentChargesResponse
|
||||
.builder()
|
||||
.customerId(customerId)
|
||||
.lineItems(itemized ? lineItems : emptyList())
|
||||
.amountDue(amountDue)
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<LineItem> mockLineItems(List<String> subscriptions) {
|
||||
return subscriptions
|
||||
.stream()
|
||||
.map(subscription -> LineItem.builder()
|
||||
.subscriptionId(subscription)
|
||||
.quantity(current().nextInt(20))
|
||||
.amount(new BigDecimal(current().nextDouble(1_000)))
|
||||
.build())
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
private List<String> mockSubscriptions() {
|
||||
String[] subscriptions = new String[5];
|
||||
fill(subscriptions, UUID.randomUUID().toString());
|
||||
return asList(subscriptions);
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.baeldung.jcommander.usagebilling.service;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.baeldung.jcommander.usagebilling.model.UsageRequest;
|
||||
|
||||
class DefaultSubmitUsageService implements SubmitUsageService {
|
||||
|
||||
@Override
|
||||
public String submit(UsageRequest request) {
|
||||
System.out.println("Submitting usage..." + request);
|
||||
|
||||
System.out.println("Submitted usage successfully...");
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.jcommander.usagebilling.service;
|
||||
|
||||
import com.baeldung.jcommander.usagebilling.model.CurrentChargesRequest;
|
||||
import com.baeldung.jcommander.usagebilling.model.CurrentChargesResponse;
|
||||
|
||||
public interface FetchCurrentChargesService {
|
||||
|
||||
static FetchCurrentChargesService getDefault() {
|
||||
return new DefaultFetchCurrentChargesService();
|
||||
}
|
||||
|
||||
CurrentChargesResponse fetch(CurrentChargesRequest request);
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.jcommander.usagebilling.service;
|
||||
|
||||
import com.baeldung.jcommander.usagebilling.model.UsageRequest;
|
||||
|
||||
public interface SubmitUsageService {
|
||||
|
||||
static SubmitUsageService getDefault() {
|
||||
return new DefaultSubmitUsageService();
|
||||
}
|
||||
|
||||
String submit(UsageRequest request);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.baeldung.picocli.git;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import com.baeldung.picocli.git.commands.programmative.GitCommand;
|
||||
import com.baeldung.picocli.git.commands.subcommands.GitAddCommand;
|
||||
import com.baeldung.picocli.git.commands.subcommands.GitCommitCommand;
|
||||
import com.baeldung.picocli.git.commands.subcommands.GitConfigCommand;
|
||||
|
||||
import picocli.CommandLine;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application implements CommandLineRunner {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
private GitCommand gitCommand;
|
||||
private GitAddCommand addCommand;
|
||||
private GitCommitCommand commitCommand;
|
||||
private GitConfigCommand configCommand;
|
||||
|
||||
@Autowired
|
||||
public Application(GitCommand gitCommand, GitAddCommand addCommand, GitCommitCommand commitCommand, GitConfigCommand configCommand) {
|
||||
this.gitCommand = gitCommand;
|
||||
this.addCommand = addCommand;
|
||||
this.commitCommand = commitCommand;
|
||||
this.configCommand = configCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String... args) {
|
||||
CommandLine commandLine = new CommandLine(gitCommand);
|
||||
commandLine.addSubcommand("add", addCommand);
|
||||
commandLine.addSubcommand("commit", commitCommand);
|
||||
commandLine.addSubcommand("config", configCommand);
|
||||
|
||||
commandLine.parseWithHandler(new CommandLine.RunLast(), args);
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.baeldung.picocli.git.commands.declarative;
|
||||
|
||||
import static picocli.CommandLine.*;
|
||||
import static picocli.CommandLine.Command;
|
||||
|
||||
import com.baeldung.picocli.git.commands.subcommands.GitAddCommand;
|
||||
import com.baeldung.picocli.git.commands.subcommands.GitCommitCommand;
|
||||
import com.baeldung.picocli.git.commands.subcommands.GitConfigCommand;
|
||||
import com.baeldung.picocli.git.model.ConfigElement;
|
||||
|
||||
import picocli.CommandLine;
|
||||
|
||||
@Command(
|
||||
name = "git",
|
||||
subcommands = {
|
||||
GitAddCommand.class,
|
||||
GitCommitCommand.class,
|
||||
GitConfigCommand.class
|
||||
}
|
||||
)
|
||||
public class GitCommand implements Runnable {
|
||||
public static void main(String[] args) {
|
||||
CommandLine commandLine = new CommandLine(new GitCommand());
|
||||
commandLine.registerConverter(ConfigElement.class, ConfigElement::from);
|
||||
|
||||
commandLine.parseWithHandler(new RunLast(), args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("The popular git command");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.baeldung.picocli.git.commands.methods;
|
||||
|
||||
import static picocli.CommandLine.Command;
|
||||
|
||||
import picocli.CommandLine;
|
||||
|
||||
@Command(name = "git")
|
||||
public class GitCommand implements Runnable {
|
||||
public static void main(String[] args) {
|
||||
CommandLine.run(new GitCommand(), args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("The popular git command");
|
||||
}
|
||||
|
||||
@Command(name = "add")
|
||||
public void addCommand() {
|
||||
System.out.println("Adding some files to the staging area");
|
||||
}
|
||||
|
||||
@Command(name = "commit")
|
||||
public void commitCommand() {
|
||||
System.out.println("Committing files in the staging area, how wonderful?");
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.picocli.git.commands.programmative;
|
||||
|
||||
import static picocli.CommandLine.Command;
|
||||
import static picocli.CommandLine.RunLast;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.baeldung.picocli.git.commands.subcommands.GitAddCommand;
|
||||
import com.baeldung.picocli.git.commands.subcommands.GitCommitCommand;
|
||||
|
||||
import picocli.CommandLine;
|
||||
|
||||
@Command(name = "git")
|
||||
@Component
|
||||
public class GitCommand implements Runnable {
|
||||
public static void main(String[] args) {
|
||||
CommandLine commandLine = new CommandLine(new GitCommand());
|
||||
commandLine.addSubcommand("add", new GitAddCommand());
|
||||
commandLine.addSubcommand("commit", new GitCommitCommand());
|
||||
|
||||
commandLine.parseWithHandler(new RunLast(), args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("The popular git command");
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.baeldung.picocli.git.commands.subcommands;
|
||||
|
||||
import static picocli.CommandLine.*;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Command(
|
||||
name = "add"
|
||||
)
|
||||
@Component
|
||||
public class GitAddCommand implements Runnable {
|
||||
@Option(names = "-A")
|
||||
private boolean allFiles;
|
||||
|
||||
@Parameters(index = "0..*")
|
||||
private List<Path> files;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (allFiles) {
|
||||
System.out.println("Adding all files to the staging area");
|
||||
}
|
||||
|
||||
if (files != null) {
|
||||
files.forEach(path -> System.out.println("Adding " + path + " to the staging area"));
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.picocli.git.commands.subcommands;
|
||||
|
||||
import static picocli.CommandLine.Command;
|
||||
import static picocli.CommandLine.Option;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Command(
|
||||
name = "commit"
|
||||
)
|
||||
@Component
|
||||
public class GitCommitCommand implements Runnable {
|
||||
@Option(names = {"-m", "--message"}, required = true)
|
||||
private String[] messages;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("Committing files in the staging area, how wonderful?");
|
||||
if (messages != null) {
|
||||
System.out.println("The commit message is");
|
||||
for (String message : messages) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.picocli.git.commands.subcommands;
|
||||
|
||||
import static picocli.CommandLine.Command;
|
||||
import static picocli.CommandLine.Parameters;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.baeldung.picocli.git.model.ConfigElement;
|
||||
|
||||
@Command(
|
||||
name = "config"
|
||||
)
|
||||
@Component
|
||||
public class GitConfigCommand implements Runnable {
|
||||
@Parameters(index = "0")
|
||||
private ConfigElement element;
|
||||
|
||||
@Parameters(index = "1")
|
||||
private String value;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("Setting " + element.value() + " to " + value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.baeldung.picocli.git.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public enum ConfigElement {
|
||||
USERNAME("user.name"),
|
||||
EMAIL("user.email");
|
||||
|
||||
private final String value;
|
||||
|
||||
ConfigElement(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static ConfigElement from(String value) {
|
||||
return Arrays.stream(values())
|
||||
.filter(element -> element.value.equals(value))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IllegalArgumentException("The argument " + value + " doesn't match any ConfigElement"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.picocli.helloworld;
|
||||
|
||||
import static picocli.CommandLine.Command;
|
||||
|
||||
import picocli.CommandLine;
|
||||
|
||||
@Command(
|
||||
name = "hello",
|
||||
description = "Says hello"
|
||||
)
|
||||
public class HelloWorldCommand implements Runnable {
|
||||
public static void main(String[] args) {
|
||||
CommandLine.run(new HelloWorldCommand(), args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("Hello World!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user