org.waterforpeople.mapping.dataexport.SurveyFormExporter.java Source code

Java tutorial

Introduction

Here is the source code for org.waterforpeople.mapping.dataexport.SurveyFormExporter.java

Source

/*
 *  Copyright (C) 2010-2015 Stichting Akvo (Akvo Foundation)
 *
 *  This file is part of Akvo FLOW.
 *
 *  Akvo FLOW is free software: you can redistribute it and modify it under the terms of
 *  the GNU Affero General Public License (AGPL) as published by the Free Software Foundation,
 *  either version 3 of the License or any later version.
 *
 *  Akvo FLOW 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 Affero General Public License included below for more details.
 *
 *  The full license text can also be seen at <http://www.gnu.org/licenses/agpl.html>.
 */

package org.waterforpeople.mapping.dataexport;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
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.util.CellRangeAddress;
import org.waterforpeople.mapping.app.gwt.client.survey.QuestionDto;
import org.waterforpeople.mapping.app.gwt.client.survey.QuestionGroupDto;
import org.waterforpeople.mapping.app.gwt.client.survey.QuestionOptionDto;
import org.waterforpeople.mapping.app.gwt.client.survey.SurveyDto;
import org.waterforpeople.mapping.app.gwt.client.survey.TranslationDto;
import org.waterforpeople.mapping.dataexport.service.BulkDataServiceClient;

import com.gallatinsystems.framework.dataexport.applet.DataExporter;

/**
 * Data exporter to write excel files containing the survey questions
 *
 * @author Christopher Fagiani
 */
public class SurveyFormExporter implements DataExporter {

    private static final Logger log = Logger.getLogger(SurveyFormExporter.class);

    private static final int COL_WIDTH = 10000;
    private static final String LANG_DELIM = " / ";
    private static final String DEP_HEAD = "Only answer if you responded ";
    private static final String DEP_HEAD_TO = " to ";
    private static final String BLANK = "_________________________";
    private static final String SMALL_BLANK = "______";
    private static final String QUESTION_HEADER = "Question";
    private static final String RESPONSE_HEADER = "Response";
    private static final String SURVEY_ID_KEY = "surveyId";
    private Map<Long, Long> idToNumberMap;
    private List<QuestionGroupDto> groupList;
    private String surveyTitle;
    private Map<QuestionGroupDto, List<QuestionDto>> questionMap;

    @Override
    public void export(Map<String, String> criteria, File fileName, String serverBase,
            Map<String, String> options) {
        try {
            String surveyId = criteria.get(SURVEY_ID_KEY);
            String apiKey = criteria.get("apiKey");
            populateQuestionMap(surveyId, serverBase, apiKey);
            List<SurveyDto> surveys = BulkDataServiceClient.fetchSurvey(Long.parseLong(surveyId), serverBase,
                    apiKey);
            if (surveys == null || surveys.isEmpty()) {
                surveyTitle = "";
            } else {
                SurveyDto surveyDto = surveys.get(0);
                surveyTitle = String.format("%s (v. %s)", surveyDto.getName(), surveyDto.getVersion());
            }

            writeSurvey(surveyTitle, fileName, groupList, questionMap);
        } catch (Exception e) {
            log.error("Could not write survey", e);
        }
    }

    /**
     * Calls the server to fetch all question groups for the survey and then will iteratee over all
     * the questions for the group and call loadQuestionDetails for each one to get the fully
     * hydrated object. This will populate a number of member variables to store the results.
     */
    private void populateQuestionMap(String surveyId, String serverBase, String apiKey) throws Exception {
        groupList = BulkDataServiceClient.fetchQuestionGroups(serverBase, surveyId, apiKey);
        questionMap = new HashMap<QuestionGroupDto, List<QuestionDto>>();
        idToNumberMap = new HashMap<Long, Long>();
        if (groupList != null) {
            Long count = 1L;
            for (QuestionGroupDto group : groupList) {
                List<QuestionDto> questions = BulkDataServiceClient.fetchQuestions(serverBase, group.getKeyId(),
                        apiKey);
                if (questions != null) {
                    List<QuestionDto> fullQuestions = new ArrayList<QuestionDto>();
                    for (QuestionDto q : questions) {
                        QuestionDto fullQ = BulkDataServiceClient.loadQuestionDetails(serverBase, q.getKeyId(),
                                apiKey);
                        if (fullQ != null) {
                            fullQuestions.add(fullQ);
                            idToNumberMap.put(fullQ.getKeyId(), count++);
                        }
                    }
                    questionMap.put(group, fullQuestions);
                }
            }
        }
    }

    /**
     * Writes the survey as an XLS document
     */
    private void writeSurvey(String title, File fileName, List<QuestionGroupDto> groupList,
            Map<QuestionGroupDto, List<QuestionDto>> questions) throws Exception {
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet();

        sheet.setColumnWidth(0, COL_WIDTH);
        sheet.setColumnWidth(1, COL_WIDTH);
        HSSFCellStyle headerStyle = wb.createCellStyle();
        headerStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        HSSFFont headerFont = wb.createFont();
        headerFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        headerStyle.setFont(headerFont);

        HSSFCellStyle questionStyle = wb.createCellStyle();
        questionStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_TOP);
        questionStyle.setWrapText(true);

        HSSFCellStyle depStyle = wb.createCellStyle();
        depStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        HSSFFont depFont = wb.createFont();
        depFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        depFont.setItalic(true);
        depStyle.setFont(depFont);

        int curRow = 0;
        HSSFRow row = sheet.createRow(curRow++);
        sheet.addMergedRegion(new CellRangeAddress(curRow - 1, curRow - 1, 0, 1));
        createCell(row, 0, title, headerStyle);
        row = sheet.createRow(curRow++);
        createCell(row, 0, QUESTION_HEADER, headerStyle);
        createCell(row, 1, RESPONSE_HEADER, headerStyle);

        Long count = 1L;
        if (questions != null) {
            for (int i = 0; i < groupList.size(); i++) {
                HSSFRow groupHeaderRow = sheet.createRow(curRow++);
                sheet.addMergedRegion(new CellRangeAddress(curRow - 1, curRow - 1, 0, 1));
                createCell(groupHeaderRow, 0, groupList.get(i).getDisplayName(), headerStyle);

                for (QuestionDto q : questions.get(groupList.get(i))) {
                    int questionStartRow = curRow;
                    HSSFRow tempRow = sheet.createRow(curRow++);
                    if (q.getQuestionDependency() != null) {
                        // if there is a dependency, add a row about not
                        // answering unless the dependency is satisfied
                        sheet.addMergedRegion(new CellRangeAddress(curRow - 1, curRow - 1, 0, 1));
                        Long qNum = idToNumberMap.get(q.getQuestionDependency().getQuestionId());
                        createCell(tempRow, 0,
                                DEP_HEAD + q.getQuestionDependency().getAnswerValue() + DEP_HEAD_TO + "Q" + qNum,
                                depStyle);
                        tempRow = sheet.createRow(curRow++);
                        questionStartRow = curRow;
                    }
                    createCell(tempRow, 0, (count++) + ". " + formText(q.getText(), q.getTranslationMap()),
                            questionStyle);
                    if (q.getOptionContainerDto() != null && q.getOptionContainerDto().getOptionsList() != null) {
                        for (QuestionOptionDto opt : q.getOptionContainerDto().getOptionsList()) {
                            tempRow = sheet.createRow(curRow++);
                            createCell(tempRow, 1, formText(opt.getText(), opt.getTranslationMap()) + SMALL_BLANK,
                                    null);
                        }
                        sheet.addMergedRegion(new CellRangeAddress(questionStartRow, curRow - 1, 0, 0));
                    } else {
                        createCell(tempRow, 1, BLANK, null);
                    }
                }
            }
        }

        FileOutputStream fileOut = new FileOutputStream(fileName);
        wb.write(fileOut);
        fileOut.close();
    }

    /**
     * creates a cell in the row passed in and sets the style and value (if non-null)
     */
    private HSSFCell createCell(HSSFRow row, int col, String value, HSSFCellStyle style) {
        HSSFCell cell = row.createCell(col);
        if (style != null) {
            cell.setCellStyle(style);
        }
        if (value != null) {
            cell.setCellValue(value);
        }
        return cell;
    }

    /**
     * forms a string that has all languages in the translation map delimited by the LANG_DELIM
     */
    private String formText(String text, Map<String, TranslationDto> translationMap) {

        StringBuilder buff = new StringBuilder();
        buff.append(text);
        if (translationMap != null) {
            TreeMap<String, TranslationDto> sortedMap = null;
            if (translationMap instanceof TreeMap) {
                sortedMap = (TreeMap<String, TranslationDto>) translationMap;
            } else {
                sortedMap = new TreeMap<String, TranslationDto>(translationMap);
            }
            for (Entry<String, TranslationDto> trans : sortedMap.entrySet()) {
                if (trans.getValue() != null && trans.getValue().getText() != null) {
                    if (!trans.getValue().getText().trim().equalsIgnoreCase("null")) {
                        buff.append(LANG_DELIM);
                        buff.append(trans.getValue().getText());
                    }
                }
            }
        }
        return buff.toString();
    }
}