19 package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport;
 
   21 import java.lang.reflect.Constructor;
 
   22 import java.lang.reflect.InvocationTargetException;
 
   23 import java.util.Arrays;
 
   24 import java.util.List;
 
   25 import org.apache.poi.ss.usermodel.Sheet;
 
   26 import org.apache.poi.ss.util.CellRangeAddress;
 
   27 import org.apache.poi.xddf.usermodel.chart.LegendPosition;
 
   28 import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
 
   29 import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
 
   30 import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
 
   31 import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
 
   32 import org.apache.poi.xddf.usermodel.chart.XDDFPieChartData;
 
   33 import org.apache.poi.xssf.usermodel.XSSFChart;
 
   34 import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
 
   35 import org.apache.poi.xssf.usermodel.XSSFDrawing;
 
   36 import org.apache.poi.xssf.usermodel.XSSFSheet;
 
   37 import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieChart;
 
   48 class PieChartExport 
implements ExcelItemExportable, ExcelSheetExport {
 
   50     private static final int DEFAULT_ROW_SIZE = 20;
 
   51     private static final int DEFAULT_COL_SIZE = 10;
 
   52     private static final int DEFAULT_ROW_PADDING = 1;
 
   53     private static final int DEFAULT_COL_OFFSET = 1;
 
   55     private final ExcelTableExport<PieChartItem, ? extends CellModel> tableExport;
 
   56     private final int colOffset;
 
   57     private final int rowPadding;
 
   58     private final int colSize;
 
   59     private final int rowSize;
 
   60     private final String chartTitle;
 
   61     private final String sheetName;
 
   73     PieChartExport(String keyColumnHeader,
 
   74             String valueColumnHeader, String valueFormatString,
 
   76             List<PieChartItem> slices) {
 
   77         this(keyColumnHeader, valueColumnHeader, valueFormatString, chartTitle, chartTitle, slices,
 
   78                 DEFAULT_COL_OFFSET, DEFAULT_ROW_PADDING, DEFAULT_COL_SIZE, DEFAULT_ROW_SIZE);
 
   97     PieChartExport(String keyColumnHeader,
 
   98             String valueColumnHeader, String valueFormatString,
 
   99             String chartTitle, String sheetName,
 
  100             List<PieChartItem> slices,
 
  101             int colOffset, 
int rowPadding, 
int colSize, 
int rowSize) {
 
  103         this.tableExport = 
new ExcelTableExport<>(chartTitle,
 
  105                         new ColumnModel<>(keyColumnHeader, (slice) -> 
new DefaultCellModel<>(slice.getLabel())),
 
  106                         new ColumnModel<>(valueColumnHeader, (slice) -> 
new DefaultCellModel<>(slice.getValue(), null, valueFormatString))
 
  109         this.colOffset = colOffset;
 
  110         this.rowPadding = rowPadding;
 
  111         this.colSize = colSize;
 
  112         this.rowSize = rowSize;
 
  113         this.chartTitle = chartTitle;
 
  114         this.sheetName = sheetName;
 
  118     public String getSheetName() {
 
  123     public void renderSheet(Sheet sheet, ExcelExport.WorksheetEnv env) throws ExcelExport.ExcelExportException {
 
  124         write(sheet, 0, 0, env);
 
  128     public ItemDimensions write(Sheet sheet, 
int rowStart, 
int colStart, ExcelExport.WorksheetEnv env) throws ExcelExportException {
 
  129         if (!(sheet instanceof XSSFSheet)) {
 
  130             throw new ExcelExportException(
"Sheet must be an XSSFSheet in order to write.");
 
  133         XSSFSheet xssfSheet = (XSSFSheet) sheet;
 
  136         ItemDimensions tableDimensions = tableExport.write(xssfSheet, rowStart + rowPadding, colStart, env);
 
  138         XSSFDrawing drawing = xssfSheet.createDrawingPatriarch();
 
  140         int chartColStart = colStart + 2 + colOffset;
 
  143         XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, chartColStart, rowStart + rowPadding, chartColStart + colSize + 1, rowStart + rowSize + 1);
 
  145         XSSFChart chart = drawing.createChart(anchor);
 
  146         chart.setTitleText(chartTitle);
 
  147         chart.setTitleOverlay(
false);
 
  148         XDDFChartLegend legend = chart.getOrAddLegend();
 
  149         legend.setPosition(LegendPosition.RIGHT);
 
  152         XDDFDataSource<String> cat = XDDFDataSourcesFactory.fromStringCellRange(xssfSheet,
 
  153                 new CellRangeAddress(tableDimensions.getRowStart() + 1, tableDimensions.getRowEnd(),
 
  154                         tableDimensions.getColStart(), tableDimensions.getColStart()));
 
  156         XDDFNumericalDataSource<Double> val = XDDFDataSourcesFactory.fromNumericCellRange(xssfSheet,
 
  157                 new CellRangeAddress(tableDimensions.getRowStart() + 1, tableDimensions.getRowEnd(),
 
  158                         tableDimensions.getColStart() + 1, tableDimensions.getColStart() + 1));
 
  168         XDDFPieChartData data;
 
  170             Constructor<XDDFPieChartData> constructor = XDDFPieChartData.class.getConstructor(CTPieChart.class);
 
  171             constructor.setAccessible(
true);
 
  172             data = constructor.newInstance(chart.getCTChart().getPlotArea().addNewPieChart());
 
  173         } 
catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException | IllegalArgumentException ex) {
 
  174             throw new ExcelExportException(
"Error while instantiating chart data.", ex);
 
  177         data.setVaryColors(
true);
 
  178         data.addSeries(cat, val);
 
  181         if (!chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).isSetDLbls()) {
 
  182             chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).addNewDLbls();
 
  185         chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDLbls().addNewShowVal().setVal(
true);
 
  186         chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDLbls().addNewShowSerName().setVal(
false);
 
  187         chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDLbls().addNewShowCatName().setVal(
true);
 
  188         chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDLbls().addNewShowPercent().setVal(
true);
 
  189         chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDLbls().addNewShowLegendKey().setVal(
false);
 
  193         return new ItemDimensions(rowStart, colStart, Math.max(tableDimensions.getRowEnd(), rowStart + rowSize) + rowPadding, chartColStart + colSize);