package org.sigmah.server.servlet.exporter.template;
/*
* #%L
* Sigmah
* %%
* Copyright (C) 2010 - 2016 URD
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.util.CellRangeAddress;
import org.sigmah.shared.dto.pivot.content.PivotTableData;
import org.sigmah.server.servlet.exporter.data.IndicatorEntryData;
import org.sigmah.server.servlet.exporter.utils.ExcelUtils;
import org.sigmah.server.servlet.exporter.utils.ExportConstants;
import org.sigmah.server.servlet.exporter.utils.ExportConstants.MultiItemText;
import org.sigmah.shared.dto.IndicatorDTO;
import org.sigmah.shared.dto.IndicatorGroup;
/**
* @author sherzod (v1.3)
*/
public class IndicatorEntryExcelTemplate implements ExportTemplate {
private final IndicatorEntryData data;
private final HSSFWorkbook wb;
private HSSFRow row = null;
private HSSFCell cell = null;
private final ExcelUtils utils;
private CellRangeAddress region;
private final float defHeight = ExportConstants.TITLE_ROW_HEIGHT;
public IndicatorEntryExcelTemplate(final IndicatorEntryData data) {
this(data, new HSSFWorkbook());
}
public IndicatorEntryExcelTemplate(final IndicatorEntryData data, final HSSFWorkbook wb) {
this.data = data;
this.wb = wb;
final HSSFSheet sheet = wb.createSheet(data.getLocalizedVersion("flexibleElementIndicatorsList"));
utils = new ExcelUtils(wb);
int rowIndex = -1;
int cellIndex = 0;
// empty row
utils.putEmptyRow(sheet, ++rowIndex, 8.65f);
// title
utils.putMainTitle(sheet, ++rowIndex, data.getLocalizedVersion("flexibleElementIndicatorsList").toUpperCase(), data.getNumbOfCols());
// empty row
utils.putEmptyRow(sheet, ++rowIndex, ExportConstants.EMPTY_ROW_HEIGHT);
// column headers
row = sheet.createRow(++rowIndex);
row.setHeightInPoints(ExportConstants.TITLE_ROW_HEIGHT);
cellIndex = 0;
utils.putHeader(row, ++cellIndex, data.getLocalizedVersion("name"));
utils.putHeader(row, ++cellIndex, data.getLocalizedVersion("code"));
utils.putHeader(row, ++cellIndex, data.getLocalizedVersion("targetValue"));
utils.putHeader(row, ++cellIndex, data.getLocalizedVersion("value"));
// empty row
utils.putEmptyRow(sheet, ++rowIndex, 8.65f);
// freeze pane
sheet.createFreezePane(0, rowIndex);
for (final IndicatorGroup group : data.getIndicators().getGroups()) {
row = sheet.createRow(++rowIndex);
row.setHeightInPoints(ExportConstants.TITLE_ROW_HEIGHT);
putGroupCell(sheet, rowIndex, group.getName());
for (final IndicatorDTO indicator : group.getIndicators()) {
// indicator's detail sheet
createDetailSheet(indicator);
row = sheet.createRow(++rowIndex);
row.setHeightInPoints(ExportConstants.TITLE_ROW_HEIGHT);
// ind name
utils.createLinkCell(row.createCell(1), indicator.getName(), ExportConstants.INDICATOR_SHEET_PREFIX + indicator.getName(), true);
// code
utils.putBorderedBasicCell(sheet, rowIndex, 2, indicator.getCode());
// target
putRightAlignedCell(sheet, rowIndex, 3, indicator.getObjective());
// current value
putRightAlignedCell(sheet, rowIndex, 4, data.getFormattedValue(indicator));
}
}
sheet.setColumnWidth(0, 256 * 2);
sheet.setColumnWidth(1, 256 * 45);
sheet.setColumnWidth(2, 256 * 27);
sheet.setColumnWidth(3, 256 * 27);
sheet.setColumnWidth(4, 256 * 27);
}
private void createDetailSheet(final IndicatorDTO indicator) {
final boolean isQualitative = indicator.getAggregation() == IndicatorDTO.AGGREGATE_MULTINOMIAL;
final HSSFSheet sheetEx = wb.createSheet(utils.normalizeAsLink(ExportConstants.INDICATOR_SHEET_PREFIX + indicator.getName()));
int rowIndex = -1;
final List<PivotTableData.Axis> leaves = data.getEntryMap().get(indicator.getId()).getRootColumn().getLeaves();
int numbOfLeaves = leaves.size();
int numbOfCols = 4;
// back to list link
row = sheetEx.createRow(++rowIndex);
utils.createLinkCell(row.createCell(1), data.getLocalizedVersion("goToIndicatorsList"), data.getLocalizedVersion("flexibleElementIndicatorsList"), false);
sheetEx.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, numbOfCols));
// title
utils.putMainTitle(sheetEx, ++rowIndex, indicator.getName(), numbOfCols);
// empty row
utils.putEmptyRow(sheetEx, ++rowIndex, ExportConstants.EMPTY_ROW_HEIGHT);
sheetEx.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, numbOfCols));
// put details
putBasicInfo(sheetEx, ++rowIndex, data.getLocalizedVersion("code"), indicator.getCode(), numbOfCols);
putBasicInfo(sheetEx, ++rowIndex, data.getLocalizedVersion("group"), data.getGroupMap().get(indicator.getGroupId()), numbOfCols);
// type
String type = null;
;
if (isQualitative) {
// qualitative
type = data.getLocalizedVersion("qualitative");
} else {
// quantitative
type = data.getLocalizedVersion("quantitative");
}
putBasicInfo(sheetEx, ++rowIndex, data.getLocalizedVersion("type"), type, numbOfCols);
// conditional
if (isQualitative) {
// qualitative
// possible values
row = sheetEx.createRow(++rowIndex);
// key
cell = utils.putHeader(row, 1, data.getLocalizedVersion("possibleValues"));
cell.getCellStyle().setAlignment(CellStyle.ALIGN_RIGHT);
// value
final MultiItemText itemText = data.formatPossibleValues(indicator.getLabels());
utils.putBorderedBasicCell(sheetEx, rowIndex, 2, itemText.text);
row.setHeightInPoints(itemText.lineCount * defHeight);
region = new CellRangeAddress(rowIndex, rowIndex, 2, numbOfCols);
sheetEx.addMergedRegion(utils.getBorderedRegion(region, sheetEx, wb));
} else {
// quantitative
// aggregation method
String aggrMethod = null;
if (indicator.getAggregation() == IndicatorDTO.AGGREGATE_AVG)
aggrMethod = data.getLocalizedVersion("average");
else
aggrMethod = data.getLocalizedVersion("sum");
putBasicInfo(sheetEx, ++rowIndex, data.getLocalizedVersion("aggregationMethod"), aggrMethod, numbOfCols);
// units
putBasicInfo(sheetEx, ++rowIndex, data.getLocalizedVersion("units"), indicator.getUnits(), numbOfCols);
// target value
putBasicInfo(sheetEx, ++rowIndex, data.getLocalizedVersion("targetValue"), indicator.getObjective(), numbOfCols);
}
// source of ver
putBasicInfo(sheetEx, ++rowIndex, data.getLocalizedVersion("sourceOfVerification"), indicator.getSourceOfVerification(), numbOfCols);
row.setHeightInPoints(utils.calculateLineCount(indicator.getSourceOfVerification(), 3 * 18) * defHeight);
// comment
putBasicInfo(sheetEx, ++rowIndex, data.getLocalizedVersion("indicatorComments"), indicator.getDescription(), numbOfCols);
row.setHeightInPoints(utils.calculateLineCount(indicator.getDescription(), 3 * 18) * defHeight);
// value
putBasicInfo(sheetEx, ++rowIndex, data.getLocalizedVersion("value"), data.getFormattedValue(indicator), numbOfCols);
// empty row
utils.putEmptyRow(sheetEx, ++rowIndex, ExportConstants.EMPTY_ROW_HEIGHT);
sheetEx.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, numbOfCols));
// data entry
// header
row = sheetEx.createRow(++rowIndex);
row.setHeightInPoints(defHeight);
int cellIndex = 0;
utils.putHeader(row, ++cellIndex, data.getLocalizedVersion("sideAndMonth"));
Map<String, Integer> columnIndexMap = new HashMap<String, Integer>();
for (PivotTableData.Axis axis : leaves) {
utils.putHeader(row, ++cellIndex, axis.getLabel());
columnIndexMap.put(axis.getLabel(), cellIndex);
}
// rows
for (PivotTableData.Axis axis : data.getEntryMap().get(indicator.getId()).getRootRow().getChildren()) {
row = sheetEx.createRow(++rowIndex);
row.setHeightInPoints(defHeight);
utils.putHeader(row, 1, axis.getLabel());
// populate empty cells
for (int i = 0; i < numbOfLeaves; i++) {
cell = utils.putBorderedBasicCell(sheetEx, rowIndex, i + 2, "");
}
// insert values
for (Map.Entry<PivotTableData.Axis, PivotTableData.Cell> entry : axis.getCells().entrySet()) {
cellIndex = columnIndexMap.get(entry.getKey().getLabel());
Object value = null;
boolean rightAligned = false;
if (isQualitative) {
value = data.getLabelByIndex(indicator.getLabels(), entry.getValue().getValue());
} else {
value = new Long(Math.round(entry.getValue().getValue()));
rightAligned = true;
}
putValueCell(sheetEx, rowIndex, cellIndex, value, rightAligned);
}
}
// col width
sheetEx.setColumnWidth(0, 256 * 2);
sheetEx.autoSizeColumn(1);
for (int i = 2; i < 2 + numbOfLeaves; i++) {
sheetEx.setColumnWidth(i, 256 * 16);
}
}
private void putBasicInfo(HSSFSheet sheet, int rowIndex, String key, Object value, int numbOfCols) {
row = sheet.createRow(rowIndex);
row.setHeightInPoints(defHeight);
// key
cell = utils.putHeader(row, 1, key);
cell.getCellStyle().setAlignment(CellStyle.ALIGN_RIGHT);
// value
utils.putBorderedBasicCell(sheet, rowIndex, 2, value);
region = new CellRangeAddress(rowIndex, rowIndex, 2, numbOfCols);
sheet.addMergedRegion(utils.getBorderedRegion(region, sheet, wb));
}
private void putRightAlignedCell(HSSFSheet sheet, int rowIndex, int cellIndex, Object value) {
cell = utils.putBorderedBasicCell(sheet, rowIndex, cellIndex, value);
cell.getCellStyle().setAlignment(CellStyle.ALIGN_RIGHT);
}
private void putValueCell(HSSFSheet sheet, int rowIndex, int cellIndex, Object value, boolean rightAligned) {
cell = utils.putBorderedBasicCell(sheet, rowIndex, cellIndex, value);
if (rightAligned)
cell.getCellStyle().setAlignment(CellStyle.ALIGN_RIGHT);
}
private void putGroupCell(HSSFSheet sheet, int rowIndex, String name) {
cell = sheet.getRow(rowIndex).createCell(1);
cell.setCellValue(name);
CellRangeAddress region = new CellRangeAddress(rowIndex, rowIndex, 1, data.getNumbOfCols());
sheet.addMergedRegion(utils.getBorderedRegion(region, sheet, wb));
cell.setCellStyle(utils.getGroupStyle(wb));
}
@Override
public void write(OutputStream output) throws Throwable {
wb.write(output);
}
}