19 package org.sleuthkit.autopsy.datasourcesummary.uiutils;
21 import java.awt.Color;
22 import java.nio.ByteBuffer;
23 import java.util.Collections;
24 import java.util.List;
26 import java.util.stream.Collectors;
27 import java.util.stream.IntStream;
28 import java.util.stream.Stream;
29 import org.apache.commons.lang3.tuple.Pair;
30 import org.apache.poi.ss.usermodel.Sheet;
31 import org.apache.poi.ss.util.CellRangeAddress;
32 import org.apache.poi.xddf.usermodel.XDDFColor;
33 import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
34 import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
35 import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
36 import org.apache.poi.xddf.usermodel.chart.AxisPosition;
37 import org.apache.poi.xddf.usermodel.chart.BarDirection;
38 import org.apache.poi.xddf.usermodel.chart.BarGrouping;
39 import org.apache.poi.xddf.usermodel.chart.ChartTypes;
40 import org.apache.poi.xddf.usermodel.chart.LegendPosition;
41 import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
42 import org.apache.poi.xddf.usermodel.chart.XDDFCategoryAxis;
43 import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
44 import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
45 import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
46 import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
47 import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
48 import org.apache.poi.xssf.usermodel.XSSFChart;
49 import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
50 import org.apache.poi.xssf.usermodel.XSSFDrawing;
51 import org.apache.poi.xssf.usermodel.XSSFSheet;
78 List<? extends Object> rowKeys = categories.stream()
79 .filter(cat -> cat != null && cat.getItems() != null)
80 .map(cat -> cat.getItems())
81 .max((items1, items2) -> Integer.compare(items1.size(), items2.size()))
82 .orElse(Collections.emptyList())
84 .map((barChartItem) -> barChartItem.getKey())
85 .collect(Collectors.toList());
88 Map<Pair<Integer, Integer>, Double> valueMap = IntStream.range(0, categories.size())
89 .mapToObj(idx -> Pair.of(idx, categories.get(idx)))
90 .filter(pair -> pair.getValue() != null && pair.getValue().getItems() != null)
91 .flatMap(categoryPair -> {
92 return IntStream.range(0, categoryPair.getValue().getItems().size())
93 .mapToObj(idx -> Pair.of(idx, categoryPair.getValue().getItems().get(idx)))
94 .map(itemPair -> Pair.of(
95 Pair.of(categoryPair.getKey(), itemPair.getKey()),
96 itemPair.getValue() == null ? null : itemPair.getValue().getValue()));
98 .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue(), (v1, v2) -> v1));
102 List<Pair<Object, List<Double>>> values = IntStream.range(0, rowKeys.size())
103 .mapToObj(idx -> Pair.of(idx, rowKeys.get(idx)))
105 List<Double> items = IntStream.range(0, categories.size())
106 .mapToObj(idx -> valueMap.get(Pair.of(idx, rowPair.getKey())))
107 .collect(Collectors.toList());
109 return Pair.of(rowPair.getValue(), items);
111 .collect(Collectors.toList());
118 Stream<ColumnModel<Pair<Object, List<Double>>,
DefaultCellModel<?>>> dataColumns = IntStream.range(0, categories.size())
120 categories.get(idx).getKey().toString(),
126 Stream.concat(Stream.of(categoryColumn), dataColumns)
127 .collect(Collectors.toList()),
158 String valueFormatString,
160 List<BarChartSeries> categories) {
181 String chartTitle, String sheetName,
182 List<BarChartSeries> categories,
183 int colOffset,
int rowPadding,
int colSize,
int rowSize) {
186 this.tableExport =
getTableModel(categories, keyColumnHeader, chartTitle);
203 write(sheet, 0, 0, env);
208 if (!(sheet instanceof XSSFSheet)) {
209 throw new ExcelExportException(
"Sheet must be an XSSFSheet in order to write.");
212 XSSFSheet xssfSheet = (XSSFSheet) sheet;
215 ItemDimensions tableDimensions = tableExport.
write(xssfSheet, rowStart + rowPadding, colStart, env);
217 XSSFDrawing drawing = xssfSheet.createDrawingPatriarch();
219 int chartColStart = colStart + categories.size() + 1 +
colOffset;
222 XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, chartColStart, rowStart + rowPadding, chartColStart + colSize + 1, rowStart + rowSize + 1);
224 XSSFChart chart = drawing.createChart(anchor);
225 chart.setTitleText(chartTitle);
226 chart.setTitleOverlay(
false);
227 XDDFChartLegend legend = chart.getOrAddLegend();
228 legend.setPosition(LegendPosition.BOTTOM);
231 XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
232 bottomAxis.setTitle(keyColumnHeader);
233 XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
234 leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
235 leftAxis.setVisible(
false);
237 XDDFBarChartData data = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
238 data.setBarGrouping(BarGrouping.STACKED);
240 XDDFDataSource<String> headerSource = XDDFDataSourcesFactory.fromStringCellRange(xssfSheet,
244 data.setBarDirection(BarDirection.COL);
247 for (
int i = 0; i < categories.size(); i++) {
248 XDDFChartData.Series series = data.addSeries(headerSource,
249 XDDFDataSourcesFactory.fromNumericCellRange(xssfSheet,
253 series.setTitle(categories.size() > i && categories.get(i).getKey() != null ? categories.get(i).getKey().toString() :
"", null);
254 if (categories.get(i).getColor() != null) {
255 Color color = categories.get(i).getColor();
256 byte[] colorArrARGB = ByteBuffer.allocate(4).putInt(color.getRGB()).array();
257 byte[] colorArrRGB =
new byte[]{colorArrARGB[1], colorArrARGB[2], colorArrARGB[3]};
258 XDDFSolidFillProperties fill =
new XDDFSolidFillProperties(XDDFColor.from(colorArrRGB));
259 XDDFShapeProperties properties = series.getShapeProperties();
260 if (properties == null) {
261 properties =
new XDDFShapeProperties();
263 properties.setFillProperties(fill);
264 series.setShapeProperties(properties);
BarChartExport(String keyColumnHeader, String valueFormatString, String chartTitle, List< BarChartSeries > categories)
static final int DEFAULT_COL_SIZE
final String keyColumnHeader
static final int DEFAULT_ROW_SIZE
static ExcelTableExport< Pair< Object, List< Double > >,?extends ExcelCellModel > getTableModel(List< BarChartSeries > categories, String keyColumnHeader, String chartTitle)
BarChartExport(String keyColumnHeader, String valueFormatString, String chartTitle, String sheetName, List< BarChartSeries > categories, int colOffset, int rowPadding, int colSize, int rowSize)
ItemDimensions write(Sheet sheet, int rowStart, int colStart, ExcelExport.WorksheetEnv env)
final ExcelTableExport< Pair< Object, List< Double > >,?extends ExcelCellModel > tableExport
static final int DEFAULT_COL_OFFSET
void renderSheet(Sheet sheet, ExcelExport.WorksheetEnv env)
final List< BarChartSeries > categories
static final int DEFAULT_ROW_PADDING
ItemDimensions write(Sheet sheet, int rowStart, int colStart, ExcelExport.WorksheetEnv env)