Base on the resultset below, I have created a column stack chart. They have been converted to an 4-attribrute object list (called as SKUQtyMetric - all are strings except for Quantity as Integer)
When converting this to a stack chart, I could not get the second item to appear next to the first item in each of the x-ticks (X represents hour). If I am not mistaken, there should only be four DataSeries objects, each representing an outlet and then do an inner loop. Just as a side note, each outlet is designated a color even if there's more than one item (I am keeping a limit of three items to be selected for searching in database), hence there's the outletFromH code below.
The current rendering of the code (using Vaadin Charts 4) is as below:
Map<String, Set<String>> myMaps = new HashMap<String, Set<String>>();
for (SkuQtyMetric item : objList) {
if (!myMaps.containsKey(item.getOutletName())) {
myMaps.put(item.getOutletName(), new HashSet<String>());
}
myMaps.get(item.getOutletName()).add(item.getItemName());
}
String asgnColor = "#ffcccc";
for(Map.Entry<String, Set<String>> map: myMaps.entrySet()) {
DataSeries dataSeries = new DataSeries(map.getKey()+"");
PlotOptionsColumn plotOptions = new PlotOptionsColumn();
plotOptions.setStacking(Stacking.NORMAL);
DataLabels labels = new DataLabels(true);
Style style = new Style();
style.setFontSize("9px");
style.setTextShadow("0 0 3px black");
labels.setStyle(style);
labels.setColor(new SolidColor("white"));
plotOptions.setDataLabels(labels);
ls.add(dataSeries);
for(String itemName: map.getValue()) {
System.out.println("Inside " + map.getKey() + ", value is: " + itemName);
dataSeries.setId(itemName);
for(SkuQtyMetric metric : objList) {
for (Map.Entry<String, String> outletfromH : Constant.SYCARDA_COLOR.entrySet()) {
if (outletfromH.getKey().equalsIgnoreCase(map.getKey())) {
asgnColor = outletfromH.getValue();
}
}
System.out.println("DataSeries Id: " + dataSeries.getId() + " , Item metric name is: "+metric.getItemName());
if(dataSeries.getName().equalsIgnoreCase(metric.getOutletName())) {
if(dataSeries.getId().equalsIgnoreCase(metric.getItemName())) {
DataSeriesItem dataSeriesItem = new DataSeriesItem(xFor(metric.getHourNumber()), metric.getQuantityAmt());
dataSeriesItem.setId(metric.getItemName()+"_setSeriesId");
dataSeriesItem.setColor(new SolidColor(asgnColor));
dataSeries.setStack(metric.getItemName());
plotOptions.setColor(new SolidColor(asgnColor));
dataSeries.setPlotOptions(plotOptions);
dataSeries.add(dataSeriesItem);
}
}
}
}
}
for (int j = 0; j < ls.size(); j++) {
listSeries.add(ls.get(j));
}
chart.getConfiguration().getSubTitle().setText(subpageName);
chart.getConfiguration().setSeries(listSeries);
When rendered, I could only get this result:
That's the current chart but second item (coconut water) is missing, shown with red scribbling. What I am not sure is whether my Map class OR my list objects controlled isn't correct OR it might be that there should be eight not four DataSeries (each being a outlet and a product). If not, is there a much more efficient way to handle the code to render the chart than what I am doing right now?
It should be possible to have multiple DataSeriesItem in the same series that go in the same stack. Four series should be enough, no need to have 8. You can do it by setting the name of the DataSeriesItem and set the XAxis type to category so that the categories are computed from the point names. Or by setting numeric X values to the DataSeriesItem and setting the categories to the XAxis as a String[].
Having separate series makes some things easier, like tooltips, and showing/hiding data from the legend. But in theory everything can be in a single series.
In some cases you might need to be sure that data is sorted by X value, or by name if you use the name as categories otherwise some points might not show correctly, you can check if that's your case by checking the browser console for error or warnings about that.