I need to map the 'count' property of the Source objects Stream to Target object's regCount & otherCount properties based on the indicator field by grouping them with PoNum property [ Ex : if (indicator.equals("Y") ? regCount = 15: otherCount = 400)]
Currently I'm doing something like the below
Map<Integer, List<SourceBean>> srcMap = srcBeanList.stream()
.collect(Collectors.groupingBy(SourceBean::getPoNum, Collectors.toList()));
for (Entry<Integer, List<SourceBean>> entry : srcMap.entrySet()) {
TargetBean tgtBean = new TargetBean();
for(SourceBean srcBean : entry.getValue()) {
tgtBean.setPoNum(srcBean.getPoNum());
tgtBean.setVendor(srcBean.getVendor());
if(srcBean.getIndicator().equals("N")) {
tgtBean.setRegCount(srcBean.getLblCnt());
}
else if(srcBean.getIndicator().equals("Y")) {
tgtBean.setOtherCount(srcBean.getLblCnt());
}
}
tgtBeanBeanList.add(tgtBean);
}
Please suggest how to achieve this mapping in Java 8 stream mapping possibly using flatmap
public class SourceBean {
private Integer poNum;
private String vendor;
private String indicator (Y/N);
private Integer count;
}
Source Json
[
{
"poNum" : 2490,
"count" : 15,
"vendor" : "Vend A",
"indicator " : "Y"
}, {
"poNum" : 2490,
"count" : 400,
"vendor" : "Vend A",
"indicator " : "N"
}
]
public class TargetBean {
private Integer poNum;
private String vendor;
private String regCount;
private String otherCount;
}
Target Json
[
{
"poNum" : 2490,
"regCount" : 15,
"otherCount" : 400,
"vendor" : "Vend A"}
]
I define a transform method named List2Bean(): it help to realize your forloop logic about combine SourceBeanList into one TargetBean. However it returns a List to apply for stream operation.
And then, focus on how I use .values().stream().map() operation. It is the key to realize your logic.
public class Test {
public TargetBean List2Bean(List<SourceBean> sourceBeanList){
TargetBean tgtBean = new TargetBean();
for(SourceBean srcBean : sourceBeanList) {
tgtBean.setPoNum(srcBean.getPoNum());
tgtBean.setVendor(srcBean.getVendor());
if(srcBean.getIndicator().equals("N")) {
tgtBean.setRegCount(String.valueOf(srcBean.getCount()));
}
else if(srcBean.getIndicator().equals("Y")) {
tgtBean.setOtherCount(String.valueOf(srcBean.getCount()));
}
}
return tgtBean;
}
public static void main(String[] args){
Test test = new Test();
List<SourceBean> srcBeanList = new ArrayList<>();
srcBeanList.add(new SourceBean(2490, "Vend A", "Y", 15));
srcBeanList.add(new SourceBean(2490, "Vend A", "N", 400));
Map<Integer, List<SourceBean>> srcMap = srcBeanList.stream()
.collect(Collectors.groupingBy(SourceBean::getPoNum, Collectors.toList()));
//List<TargetBean> targetBeanList = (List<TargetBean>)
List<TargetBean> tgtMaplist =
srcMap.values().stream().map( e -> {return test.List2Bean(e.getValue());})
.collect(Collectors.toList());
tgtMaplist.stream().forEach(t -> {
System.out.println(t.getPoNum() + " " + t.getVendor() + " " + t.getRegCount() + " " + t.getOtherCount() );
});
}
}
Related
Custom dimension
`public class GetUsersData {
private static final String APPLICATION_NAME = "Wtr-web";
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final String KEY_FILE_LOCATION = "D:\\ga3\\credentials.json";
// private static final String USER_VIEW_ID = "281667139"; // userIdView
private static final String CLIENT_VIEW_ID = "281540591"; // all page
// private static Map<String, String> convertedUserMap = new LinkedHashMap<>();
public UsersData getUsersData() throws Exception {
// Create the DateRange object.
DateRange dateRange = new DateRange();
dateRange.setStartDate("30DaysAgo");
dateRange.setEndDate("today");
return getStatistics(initializeAnalyticsReporting(), dateRange, CLIENT_VIEW_ID);
}
private AnalyticsReporting initializeAnalyticsReporting() throws GeneralSecurityException, Exception {
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream(KEY_FILE_LOCATION))
.createScoped(Collections.singletonList(AnalyticsReportingScopes.ANALYTICS_READONLY));
// Construct the Analytics Reporting service object.
return new AnalyticsReporting.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME).build();
}
private UsersData getStatistics(AnalyticsReporting service, DateRange dateRange, String userViewId) {
// Create the Metrics object.
Metric visits = new Metric().setExpression("ga:visits");
Dimension UserId = new Dimension().setName("ga:UserID");
// Create the ReportRequest object.
ReportRequest request = new ReportRequest().setViewId(userViewId).setDateRanges(Arrays.asList(dateRange))
.setMetrics(Arrays.asList(visits))
.setDimensions(Arrays.asList(UserId));
// Create the GetReportsRequest object.
GetReportsRequest getReport = new GetReportsRequest().setReportRequests(Arrays.asList(request));
GetReportsResponse response = null;
try {
response = service.reports().batchGet(getReport).execute();
} catch (Exception e) {
e.printStackTrace();
System.out.println(" data not found");
}
if (response != null) {
for (Report report : response.getReports()) {
ColumnHeader columnHeader = report.getColumnHeader();
ClassInfo classInfo = report.getClassInfo();
List<ReportRow> rows = report.getData().getRows();
if (rows == null) {
System.out.println("No data found for the request.");
}
for (ReportRow row : rows) {
List<String> dimensions = row.getDimensions();
List<DateRangeValues> metrics = row.getMetrics();
}
}
}
return new UsersData();
}
}`
com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Unknown dimension(s): ga:UserID\nFor details see https://developers.google.com/analytics/devguides/reporting/core/dimsmets.",
"reason" : "badRequest"
} ],
"message" : "Unknown dimension(s): ga:UserID\nFor details see https://developers.google.com/analytics/devguides/reporting/core/dimsmets.",
"status" : "INVALID_ARGUMENT"
}
UserID is my custom dimension. how can i resolve this issue.
I want to have mutually exclusive command options for the below snippet :
#Command(description = "test command")
public void test(
#Option(names = { "-a"}, required = true, arity = "0", description = "print A") boolean a,
#Option(names = { "-b"}, required = true, description = "pint B") boolean b)
//
}
If I use #ArgGroup for a class field then It works but I want to achieve the same for methods.
class TestClass{
#ArgGroup(exclusive = true, multiplicity = "1")
private Sample sample = new Sample();
public static class Sample {
#Option(names = { "-a"}, required = true, arity = "0", description = "print A") boolean a ;
#Option(names = { "-b"}, required = true, description = "pint B") boolean b ;
}
}
You should be able to use an #ArgGroup-annotated method, just like an #ArgGroup-annotated field.
For example:
class SomeCommand implements Runnable {
private Sample sample;
#ArgGroup(exclusive = true, multiplicity = "1")
void setGroup(Sample sample) {
System.out.printf("setGroup was called with %s%n", sample);
this.sample = sample;
}
static class Sample {
#Option(names = "-a", required = true, arity = "0", description = "print A") boolean a ;
#Option(names = "-b", required = true, description = "print B") boolean b ;
public String toString() {
return String.format("Sample[a=%s, b=%s]#%x", a, b, hashCode());
}
}
public void run() {
System.out.printf("In run, sample=%s%n", this.sample);
}
public static void main(String... args) {
//System.setProperty("picocli.trace", "DEBUG");
new CommandLine(new SomeCommand()).execute("-a");
}
}
When I run this, I see the following output:
setGroup was called with Sample[a=false, b=false]#7de62196
In run, sample=Sample[a=true, b=false]#7de62196
So, you can use an #ArgGroup-annotated method; it will initially be invoked with a new instance, and this instance will be modified after the setter method was called.
(We can get more insight into what is happening under the hood by enabling picocli tracing.)
ive got some code that works very well with picocli:
#Command(name = "parse", sortOptions = false, description = "parse input files and write to database")
class CommandLineArgumentParser {
#Option(names = { "-h", "--help" }, usageHelp = true, description = "display this message")
private boolean helpRequested = false;
#Option(names = { "-s", "--startDate"}, description = "First day at which to parse data",
converter = GermanDateConverter.class, paramLabel = "dd.MM.yyyy")
public LocalDate start;
#Option(names = { "-e", "--endDate"}, description = "Last day (inclusive) at which to stop parsing",
converter = GermanDateConverter.class, paramLabel = "dd.MM.yyyy")
public LocalDate end;
private static class GermanDateConverter implements ITypeConverter<LocalDate> {
#Override
public LocalDate convert(String value) throws Exception {
LocalDate result = null;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
result = LocalDate.parse(value, formatter);
if (result.getYear() < 1900) {
throw new IllegalArgumentException("year should be after 1900");
}
return result;
}
}
#SpringBootApplication
public class Application implements CommandLineRunner {
public void run(String... args) throws Exception {
CommandLineArgumentParser commandlineparser = new CommandLineArgumentParser();
CommandLine commandLine = new CommandLine(commandlineparser);
try {
commandLine.parseArgs(args);
} catch (MissingParameterException e) {
System.out.println(e);
System.out.println();
CommandLine.usage(CommandLineArgumentParser.class, System.out);
System.exit(1);
} catch (ParameterException e) {
System.out.println(e);
System.out.println();
CommandLine.usage(CommandLineArgumentParser.class, System.out);
System.exit(1);
}
if (commandLine.isUsageHelpRequested()) {
commandLine.usage(System.out);
return;
} else if (commandLine.isVersionHelpRequested()) {
commandLine.printVersionHelp(System.out);
return;
}
if (commandlineparser.start == null) {
log.warn("no start date specified, using: 01.01.2005");
commandlineparser.start = LocalDate.of(2005, 01, 01);
}
if (commandlineparser.end == null) {
LocalDate timePoint = LocalDate.now();
log.warn("no end date specified, using today: " + timePoint.toString());
commandlineparser.end = timePoint;
}
}
but i did not find a simple example that shows multiple commands used, for example this one:
https://github.com/remkop/picocli/blob/master/src/test/java/picocli/Demo.java
does not compile:
int exitCode = new CommandLine(new Demo()).execute(args);
The method execute(CommandLine, List<Object>) in the type CommandLine is not applicable for the arguments (String[])
could somebody please post a example on howto use multiple commands?
I suspect you’re using an older version of the library. The execute(String []) : int method was introduced in picocli 4.0.
Upgrading and using the execute method instead of the parseArgs method will allow you to remove a lot of boilerplate code from the application: handling requests for usage/version help and dealing with invalid input is done automatically with the execute method.
Your commands should implement Runnable or Callable, and this is where the business logic of each command lives.
Modifying your example and giving it a subcommand:
#Command(name = "parse", sortOptions = false,
mixinStandardHelpOptions = true, version = “1.0”,
description = "parse input files and write to database",
subcommands = MySubcommand.class)
class CommandLineArgumentParser implements Callable<Integer> {
#Option(names = { "-s", "--startDate"}, description = "First day at which to parse data",
converter = GermanDateConverter.class, paramLabel = "dd.MM.yyyy")
public LocalDate start;
#Option(names = { "-e", "--endDate"}, description = "Last day (inclusive) at which to stop parsing",
converter = GermanDateConverter.class, paramLabel = "dd.MM.yyyy")
public LocalDate end;
private static class GermanDateConverter implements ITypeConverter<LocalDate> {
#Override
public LocalDate convert(String value) throws Exception {
LocalDate result = null;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
result = LocalDate.parse(value, formatter);
if (result.getYear() < 1900) {
throw new IllegalArgumentException("year should be after 1900");
}
return result;
}
}
#Override
public Integer call() {
if (start == null) {
log.warn("no start date specified, using: 01.01.2005");
start = LocalDate.of(2005, 01, 01);
}
if (end == null) {
LocalDate timePoint = LocalDate.now();
log.warn("no end date specified, using today: " + timePoint.toString());
end = timePoint;
}
// more business logic here ...
// add finally return an exit code
int exitCode = ok ? 0 : 1;
return exitCode;
}
}
#Command(name = "foo")
class MySubcommand implements Callable<Integer> {
#Override
public Integer call() {
System.out.println("hi");
return 0;
}
}
#SpringBootApplication
public class Application implements CommandLineRunner {
public void run(String... args) throws Exception {
int exitCode = new CommandLine(
CommandLineArgumentParser.class,
new picocli.spring.PicocliSpringFactory())
.execute(args);
System.exit(exitCode);
}
}
Note that when using Spring in combination with picocli subcommands, you need to call the CommandLine constructor with a picocli.spring.PicocliSpringFactory.
For a more complete Spring example, see the picocli-spring-boot-starter README.
I am trying to get a list of equipment IDs to show under one data structure, instead of a listing with the equipment name alongside each ID.
I'm trying to get it to show:
Site Equipment
Inlet P1
M&C-SP2500
329
Sick Maihak-MCS 100e
330
336
538
Inlet P2
etc....
The data is from MySQL query and using an ObservableList.
private ObservableList<Customer_EquipTree> equiptrees;
TreeItem<String> rootItem = new TreeItem<String>("Site Equipment");
rootItem.setExpanded(true);
for (Customer_EquipTree equiptree : equiptrees) {
TreeItem<String> equip = new TreeItem<String>(equiptree.getEquipment());
TreeItem<String> clID = new TreeItem<String>(equiptree.getclID().toString());
boolean found = false;
for (TreeItem<String> siteDes : rootItem.getChildren()) {
if (siteDes.getValue().contentEquals(equiptree.getSiteDesignation())) {
siteDes.getChildren().add(equip);
equip.getChildren().add(clID);
found = true;
break;
}
}
if (!found) {
TreeItem<String> siteDes = new TreeItem<String>(equiptree.getSiteDesignation());
rootItem.getChildren().add(siteDes);
siteDes.getChildren().add(equip);
equip.getChildren().add(clID);
locationTreeView.setRoot(rootItem);
}
}
This is how I have
public class Customer_EquipTree {
private String SiteDesignation;
private String Equipment;
private Integer Checklistid;
private Integer clID;
public Customer_EquipTree(String SiteDesignation, String Equipment, Integer Checklistid, Integer clID) {
this.SiteDesignation = SiteDesignation;
this.Equipment = Equipment;
this.Checklistid = Checklistid;
this.clID = clID;
}
public String getSiteDesignation() {
return SiteDesignation;
}
public void setSiteDesignation(String SiteDesignation) {
this.SiteDesignation = SiteDesignation;
}
public String getEquipment() {
return Equipment;
}
public void setEquipment(String Equipment) {
this.Equipment = Equipment;
}
public Integer getChecklistid() {
return Checklistid;
}
public void setChecklistid(Integer Checklistid) {
this.Checklistid = Checklistid;
}
public Integer getclID() {
return clID;
}
public void setclID(Integer clID) {
this.clID = clID;
}
#Override
public String toString() {
return SiteDesignation + " " + Equipment.toString();
}
}
It seems to me that your Customer_EquipTree is basically a tuple of site, equipment and id and there is one for every id. It looks you need to look for existing equipment the same way you look for existing sites.
You should create a helper method for this to avoid code duplication:
public static <T> TreeItem<T> findOrInsert(TreeItem<T> parent, T childValue) {
for (TreeItem<T> child : parent.getChildren()) {
if (child.getValue().equals(childValue)) {
return child;
}
}
TreeItem<T> result = new TreeItem<T>(childValue);
parent.getChildren().add(result);
return result;
}
for (Customer_EquipTree equiptree : equiptrees) {
TreeItem<String> siteDes = findOrInsert(rootItem, equiptree.getSiteDesignation());
TreeItem<String> equip = findOrInsert(siteDes, equiptree.getEquipment());
equip.getChildren().add(new TreeItem<>(equiptree.getclID().toString()));
}
BTW: using ORDER BY in your sql query would allow you to simplify the tree creation a bit, since you can be sure the items with matching site/equipment values occur next to each other in the ResultSet, e.g.
TreeItem<String> rootItem = new TreeItem<String>("Site Equipment");
try (Statement st = conn.createStatement()) {
ResultSet rs = st.executeQuery("SELECT siteDesignation, equipment, clID FROM Customer_EquipTree ORDER BY siteDesignation, equipment");
String currentSite = null;
String currentEquipment = null;
TreeItem<Sting> tiSite = null;
TreeItem<String> tiEquipment = null;
while (rs.next()) {
String site = rs.getString(1);
String equipment = rs.getString(2);
String id = rs.getString(3);
if (!site.equals(currentSite)) {
currentSite = site;
tiSite = new TreeItem<>(site);
rootItem.getChildren().add(tiSite);
currentEquipment = null; // equipment needs to be replaced too
}
if (!equipment.equals(currentEquipment)) {
currentEquipment = equipment;
tiEquipment = new TreeItem<>(equipment);
tiSite.getChildren().add(tiEquipment);
}
tiEquipment.getChildren().add(new TreeItem<>(id));
}
}
I have written the following code and keep running into this error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at yournamep3.Yournamep3test.main(Yournamep3test.java:23)
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
public class Yournamep3test {
public static void main(String[] args) {
// Check if target file exists
File targetFile = new File(args[0]);
try {
PrintWriter out = new PrintWriter(targetFile);
out.write("\r\nStringed musical Instrument program");
for (int arrayIndex = 0; arrayIndex < 10; arrayIndex++) {
out.write("\r\n\r\n");
out.write("\r\nCreating new Stringed Musical Instrument object now..............");
Yournamep3 violinInstrument = new Yournamep3();
violinInstrument.setNameOfInstrument("Violin # " + (arrayIndex+1));
out.write("\r\nCreated instrument with name - "
+ violinInstrument.getNameOfInstrument());
int num = violinInstrument.getNumberOfStrings();
out.write("\r\nNumber of strings in instrument is " + num);
out.write("\r\nNames of String are ");
String strings[] = violinInstrument.getStringNames();
for (int counter = 0; counter < num; counter++) {
out.write("\r\n" + strings[counter]);
}
out.write("\r\nIs the Instrument playing - "
+ violinInstrument.isPlaying());
out.write("\r\nIs the Instrument tuned - "
+ violinInstrument.isTuned());
out.write("\r\nTuning now.........");
violinInstrument.setTuned(true);
out.write("\r\nIs the Instrument tuned - "
+ violinInstrument.isTuned());
out.write("\r\nCalling the Instrument play method now..");
violinInstrument.startPlayInstrument();
out.write("\r\nIs the Instrument playing - "
+ violinInstrument.isPlaying());
out.write("\r\nStopping playing of instrument..............");
violinInstrument.stopPlayInstrument();
out.write("\r\nIs the Instrument playing - "
+ violinInstrument.isPlaying());
}
out.close();
} catch (IOException e) {
}
}
}
I think the issue is with line 23. Any advice would be appreciated, thanks.
This is the other part of the code yournamep3
public class Yournamep3 {
//fields to determine if the instrument is isTuned,
private boolean isTuned;
//and if the instrument is currently isPlaying.
private boolean isPlaying;
private String name;
private int numberOfStrings = 4; // number of strings
private String nameofStringsInInstrument[] = {"E", "C", "D", "A"}; //an array of string names
//A constructor method that set the isTuned and currently isPlaying fields to false.
public Yournamep3() {
this.isTuned = false;
this.isPlaying = false;
}
/**
* #return the name
*/
public String getNameOfInstrument() {
return name;
}
/**
* #param name the name to set
*/
public void setNameOfInstrument(String nameOfInstrument) {
this.name = nameOfInstrument;
}
// Other methods
public boolean isPlaying() {
return isPlaying;
}
public void setPlaying(boolean playing) {
this.isPlaying = playing;
}
public boolean isTuned() {
return isTuned;
}
public void setTuned(boolean isTuned) {
this.isTuned = isTuned;
}
public void startPlayInstrument() {
System.out.println("The Instrument is now Playing.");
isPlaying = true;
}
public void stopPlayInstrument() {
System.out.println("The Instrument is not Playing anymore.");
isPlaying = false;
}
public void startTuneInstrument() {
System.out.println("The Instrument is Tuned.");
isTuned = true;
}
public void stopTuneInstrument() {
System.out.println("The Instrument is not Tuned.");
isTuned = false;
}
public int getNumberOfStrings() {
return this.numberOfStrings ;
}
public String[] getStringNames() {
return nameofStringsInInstrument;
}
}
I would look at your getStringNames() method for your violinInstrument. It seems to me that it isn't populating your String array properly, or the getNumberOfStrings() method does not give the right number of strings. If you put the code for that up, I can help a bit more.
Line 23 appears to be
Yournamep3 violinInstrument = new Yournamep3();
If that's the case you should check the constructor for Yournamemp3
Since Line 23 is
File targetFile = new File(args [0]);
It indicates that your args object is empty. ArrayIndexOutOfBoundException is thrown to indicate that an array has been accessed with an illegal index. 0 is an illegal index.