/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/
package org.apache.ofbiz.content.survey;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.ofbiz.base.location.FlexibleLocation;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.GeneralException;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.base.util.template.FreeMarkerWorker;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.condition.EntityCondition;
import org.apache.ofbiz.entity.condition.EntityOperator;
import org.apache.ofbiz.entity.transaction.TransactionUtil;
import org.apache.ofbiz.entity.util.EntityListIterator;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.entity.util.EntityUtil;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * Survey Wrapper - Class to render survey forms
 */
public class SurveyWrapper {

    public static final String module = SurveyWrapper.class.getName();

    protected Delegator delegator = null;
    protected String responseId = null;
    protected String partyId = null;
    protected String surveyId = null;
    protected Map<String, Object> templateContext = null;
    protected Map<String, Object> passThru = null;
    protected Map<String, Object> defaultValues = null;
    protected boolean edit = false;

    protected SurveyWrapper() {}

    public SurveyWrapper(Delegator delegator, String responseId, String partyId, String surveyId, Map<String, Object> passThru, Map<String, Object> defaultValues) {
        this.delegator = delegator;
        this.responseId = responseId;
        this.partyId = partyId;
        this.surveyId = surveyId;
        this.setPassThru(passThru);
        this.setDefaultValues(defaultValues);
        this.checkParameters();
    }

     public SurveyWrapper(Delegator delegator, String responseId, String partyId, String surveyId, Map<String, Object> passThru) {
         this(delegator, responseId, partyId, surveyId, passThru, null);
     }

    public SurveyWrapper(Delegator delegator, String surveyId) {
        this(delegator, null, null, surveyId, null);
    }

    protected void checkParameters() {
        if (delegator == null || surveyId == null) {
            throw new IllegalArgumentException("Missing one or more required parameters (delegator, surveyId)");
        }
    }

    /**
     * Sets the pass-thru values (hidden form fields)
     * @param passThru
     */
    public void setPassThru(Map<String, Object> passThru) {
        if (passThru != null) {
            this.passThru = new HashMap<String, Object>();
            this.passThru.putAll(passThru);
        }
    }

    /**
     * Sets the default values
     * @param defaultValues
     */
    public void setDefaultValues(Map<String, Object> defaultValues) {
        if (defaultValues != null) {
            this.defaultValues = new HashMap<String, Object>();
            this.defaultValues.putAll(defaultValues);
        }
    }

    /**
     * Adds an object to the FTL survey template context
     * @param name
     * @param value
     */
    public void addToTemplateContext(String name, Object value) {
        if (templateContext == null) {
            templateContext = new HashMap<String, Object>();
        }
        templateContext.put(name, value);
    }

    /**
     * Removes an object from the FTL survey template context
     * @param name
     */
    public void removeFromTemplateContext(String name) {
        if (templateContext != null)
            templateContext.remove(name);
    }

    /**
     * Renders the Survey
     * @return Writer object from the parsed Freemarker Template
     * @throws SurveyWrapperException
     */
    public Writer render(String templatePath) throws SurveyWrapperException {
        URL templateUrl = null;
        try {
            templateUrl = FlexibleLocation.resolveLocation(templatePath);
        } catch (MalformedURLException e) {
            throw new SurveyWrapperException(e);
        }
        if (templateUrl == null) {
            String errMsg = "Problem getting the template for Survey from URL: " + templatePath;
            Debug.logError(errMsg, module);
            throw new IllegalArgumentException(errMsg);
        }

        Writer writer = new StringWriter();
        this.render(templateUrl, writer);
        return writer;
    }

    /**
     * Renders the Survey
     * @param templateUrl the template URL
     * @param writer the write
     * @throws SurveyWrapperException
     */
    public void render(URL templateUrl, Writer writer) throws SurveyWrapperException {
        String responseId = this.getThisResponseId();
        GenericValue survey = this.getSurvey();
        List<GenericValue> surveyQuestionAndAppls = this.getSurveyQuestionAndAppls();
        Map<String, Object> results = this.getResults(surveyQuestionAndAppls);
        Map<String, Object> currentAnswers = null;
        if (responseId != null && canUpdate()) {
            currentAnswers = this.getResponseAnswers(responseId);
        } else {
            currentAnswers = this.getResponseAnswers(null);
        }

        Map<String, Object> sqaaWithColIdListByMultiRespId = new HashMap<String, Object>();
        for (GenericValue surveyQuestionAndAppl : surveyQuestionAndAppls) {
            String surveyMultiRespColId = surveyQuestionAndAppl.getString("surveyMultiRespColId");
            if (UtilValidate.isNotEmpty(surveyMultiRespColId)) {
                String surveyMultiRespId = surveyQuestionAndAppl.getString("surveyMultiRespId");
                UtilMisc.addToListInMap(surveyQuestionAndAppl, sqaaWithColIdListByMultiRespId, surveyMultiRespId);
            }
        }

        if (templateContext == null) {
            templateContext = new HashMap<String, Object>();
        }

        templateContext.put("partyId", partyId);
        templateContext.put("survey", survey);
        templateContext.put("surveyResults", results);
        templateContext.put("surveyQuestionAndAppls", surveyQuestionAndAppls);
        templateContext.put("sqaaWithColIdListByMultiRespId", sqaaWithColIdListByMultiRespId);
        templateContext.put("alreadyShownSqaaPkWithColId", new HashSet());
        templateContext.put("surveyAnswers", currentAnswers);
        templateContext.put("surveyResponseId", responseId);
        templateContext.put("sequenceSort", UtilMisc.toList("sequenceNum"));
        templateContext.put("additionalFields", passThru);
        templateContext.put("defaultValues", defaultValues);
        templateContext.put("delegator", this.delegator);
        templateContext.put("locale", Locale.getDefault());

        Template template = this.getTemplate(templateUrl);
        try {
            FreeMarkerWorker.renderTemplate(template, templateContext, writer);
        } catch (TemplateException e) {
            Debug.logError(e, "Error rendering Survey with template at [" + templateUrl.toExternalForm() + "]", module);
        } catch (IOException e) {
            Debug.logError(e, "Error rendering Survey with template at [" + templateUrl.toExternalForm() + "]", module);
        }
    }

    // returns the FTL Template object
    // Note: the template will not be cached
    protected Template getTemplate(URL templateUrl) {
        Configuration config = FreeMarkerWorker.getDefaultOfbizConfig();

        Template template = null;
        try {
            InputStream templateStream = templateUrl.openStream();
            InputStreamReader templateReader = new InputStreamReader(templateStream);
            template = new Template(templateUrl.toExternalForm(), templateReader, config);
        } catch (IOException e) {
            Debug.logError(e, "Unable to get template from URL :" + templateUrl.toExternalForm(), module);
        }
        return template;
    }

    public void setEdit(boolean edit) {
        this.edit = edit;
    }

    // returns the GenericValue object for the current Survey
    public GenericValue getSurvey() {
        GenericValue survey = null;
        try {
            survey = EntityQuery.use(delegator).from("Survey").where("surveyId", surveyId).cache().queryOne();
        } catch (GenericEntityException e) {
            Debug.logError(e, "Unable to get Survey : " + surveyId, module);
        }
        return survey;
    }

    public String getSurveyName() {
        GenericValue survey = this.getSurvey();
        if (survey != null) {
            return survey.getString("surveyName");
        }
        return "";
    }

    // true if we can update this survey
    public boolean canUpdate() {
        if (this.edit) {
            return true;
        }

        GenericValue survey = this.getSurvey();
        if (!"Y".equals(survey.getString("allowMultiple")) && !"Y".equals(survey.getString("allowUpdate"))) {
            return false;
        }
        return true;
    }

    public boolean canRespond() {
        String responseId = this.getThisResponseId();
        if (responseId == null) {
            return true;
        } else {
            GenericValue survey = this.getSurvey();
            if ("Y".equals(survey.getString("allowMultiple"))) {
                return true;
            }
        }
        return false;
    }

    // returns a list of SurveyQuestions (in order by sequence number) for the current Survey
    public List<GenericValue> getSurveyQuestionAndAppls() {
        List<GenericValue> questions = new LinkedList<GenericValue>();

        try {
            questions = EntityQuery.use(delegator).from("SurveyQuestionAndAppl")
                    .where("surveyId", surveyId)
                    .orderBy("sequenceNum", "surveyMultiRespColId")
                    .filterByDate().cache().queryList();
        } catch (GenericEntityException e) {
            Debug.logError(e, "Unable to get questions for survey : " + surveyId, module);
        }

        return questions;
    }

    // returns the most current SurveyResponse ID for a survey; null if no party is found
    protected String getThisResponseId() {
        if (responseId != null) {
            return responseId;
        }

        if (partyId == null) {
            return null;
        }

        String responseId = null;
        List<GenericValue> responses = null;
        try {
            responses = EntityQuery.use(delegator).from("SurveyResponse")
                    .where("surveyId", surveyId, "partyId", partyId)
                    .orderBy("-lastModifiedDate")
                    .queryList();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
        }

        if (UtilValidate.isNotEmpty(responses)) {
            GenericValue response = EntityUtil.getFirst(responses);
            responseId = response.getString("surveyResponseId");
            if (responses.size() > 1) {
                Debug.logWarning("More then one response found for survey : " + surveyId + " by party : " + partyId + " using most current", module);
            }
        }

        return responseId;
    }

    protected void setThisResponseId(String responseId) {
        this.responseId = responseId;
    }

    public long getNumberResponses() throws SurveyWrapperException {
        long responses = 0;
        try {
            responses = EntityQuery.use(delegator).from("SurveyResponse").where("surveyId", surveyId).queryCount();
        } catch (GenericEntityException e) {
            throw new SurveyWrapperException(e);
        }
        return responses;
    }

    public List<GenericValue> getSurveyResponses(GenericValue question) throws SurveyWrapperException {
        List<GenericValue> responses = null;
        try {
            responses = EntityQuery.use(delegator).from("SurveyResponse").where("surveyQuestionId", question.get("surveyQuestionId")).queryList();
        } catch (GenericEntityException e) {
            throw new SurveyWrapperException(e);
        }
        return responses;
    }

    // returns a Map of answers keyed on SurveyQuestion ID from the most current SurveyResponse ID
    public Map<String, Object> getResponseAnswers(String responseId) throws SurveyWrapperException {
        Map<String, Object> answerMap = new HashMap<String, Object>();

        if (responseId != null) {
            List<GenericValue> answers = null;
            try {
                answers = EntityQuery.use(delegator).from("SurveyResponseAnswer").where("surveyResponseId", responseId).queryList();
            } catch (GenericEntityException e) {
                Debug.logError(e, module);
            }

            if (UtilValidate.isNotEmpty(answers)) {
                for (GenericValue answer : answers) {
                    answerMap.put(answer.getString("surveyQuestionId"), answer);
                }
            }
        }

        // get the pass-thru (posted form data)
        if (UtilValidate.isNotEmpty(passThru)) {
            for (String key : passThru.keySet()) {
                if (key.toUpperCase().startsWith("ANSWERS_")) {
                    int splitIndex = key.indexOf('_');
                    String questionId = key.substring(splitIndex+1);
                    Map<String, Object> thisAnswer = new HashMap<String, Object>();
                    String answer = (String) passThru.remove(key);
                    thisAnswer.put("booleanResponse", answer);
                    thisAnswer.put("currencyResponse", answer);
                    thisAnswer.put("floatResponse", answer);
                    thisAnswer.put("numericResponse", answer);
                    thisAnswer.put("textResponse", answer);
                    thisAnswer.put("surveyOptionSeqId", answer);
                    // this is okay since only one will be looked at
                    answerMap.put(questionId, thisAnswer);
                }
            }
        }

        return answerMap;
    }

    public List<GenericValue> getQuestionResponses(GenericValue question, int startIndex, int number) throws SurveyWrapperException {
        List<GenericValue> resp = null;
        boolean beganTransaction = false;
        try {
            beganTransaction = TransactionUtil.begin();

            int maxRows = startIndex + number;
            EntityListIterator eli = this.getEli(question, maxRows);
            if (startIndex > 0 && number > 0) {
                resp = eli.getPartialList(startIndex, number);
            } else {
                resp = eli.getCompleteList();
            }

            eli.close();
        } catch (GenericEntityException e) {
            try {
                // only rollback the transaction if we started one...
                TransactionUtil.rollback(beganTransaction, "Error getting survey question responses", e);
            } catch (GenericEntityException e2) {
                Debug.logError(e2, "Could not rollback transaction: " + e2.toString(), module);
            }

            throw new SurveyWrapperException(e);
        } finally {
            try {
                // only commit the transaction if we started one...
                TransactionUtil.commit(beganTransaction);
            } catch (GenericEntityException e) {
                throw new SurveyWrapperException(e);
            }
        }
        return resp;
    }

    public Map<String, Object> getResults(List<GenericValue> questions) throws SurveyWrapperException {
        Map<String, Object> questionResults = new HashMap<String, Object>();
        if (questions != null) {
            for (GenericValue question : questions) {
                Map<String, Object> results = getResultInfo(question);
                if (results != null) {
                    questionResults.put(question.getString("surveyQuestionId"), results);
                }
            }
        }
        return questionResults;
    }

    // returns a map of question reqsults
    public Map<String, Object> getResultInfo(GenericValue question) throws SurveyWrapperException {
        Map<String, Object> resultMap = new HashMap<String, Object>();

        // special keys in the result:
        // "_q_type"      - question type (SurveyQuestionTypeId)
        // "_a_type"      - answer type ("boolean", "option", "long", "double", "text")
        // "_total"       - number of total responses (all types)
        // "_tally"       - tally of all response values (number types)
        // "_average"     - average of all response values (number types)
        // "_yes_total"   - number of 'Y' (true) reponses (boolean type)
        // "_no_total"    - number of 'N' (false) responses (boolean type)
        // "_yes_percent" - number of 'Y' (true) reponses (boolean type)
        // "_no_percent"  - number of 'N' (false) responses (boolean type)
        // [optionId]     - Map containing '_total, _percent' keys (option type)

        String questionType = question.getString("surveyQuestionTypeId");
        resultMap.put("_q_type", questionType);

        // call the proper method based on the question type
        // note this will need to be updated as new types are added
        if ("OPTION".equals(questionType)) {
            Map<String, Object> thisResult = getOptionResult(question);
            if (thisResult != null) {
                Long questionTotal = (Long) thisResult.remove("_total");
                if (questionTotal == null) {
                    questionTotal = Long.valueOf(0);
                }
                // set the total responses
                resultMap.put("_total", questionTotal);

                // create the map of option info ("_total", "_percent")
                for (String optId : thisResult.keySet()) {
                    Map<String, Object> optMap = new HashMap<String, Object>();
                    Long optTotal = (Long) thisResult.get(optId);
                    if (optTotal == null) {
                        optTotal = Long.valueOf(0);
                    }
                    Long percent = Long.valueOf((long)(((double)optTotal.longValue() / (double)questionTotal.longValue()) * 100));
                    optMap.put("_total", optTotal);
                    optMap.put("_percent", percent);
                    resultMap.put(optId, optMap);
                }
                resultMap.put("_a_type", "option");
            }
        } else if ("BOOLEAN".equals(questionType)) {
            long[] thisResult = getBooleanResult(question);
            long yesPercent = thisResult[1] > 0 ? (long)(((double)thisResult[1] / (double)thisResult[0]) * 100) : 0;
            long noPercent = thisResult[2] > 0 ? (long)(((double)thisResult[2] / (double)thisResult[0]) * 100) : 0;

            resultMap.put("_total", Long.valueOf(thisResult[0]));
            resultMap.put("_yes_total", Long.valueOf(thisResult[1]));
            resultMap.put("_no_total", Long.valueOf(thisResult[2]));
            resultMap.put("_yes_percent", Long.valueOf(yesPercent));
            resultMap.put("_no_percent", Long.valueOf(noPercent));
            resultMap.put("_a_type", "boolean");
        } else if ("NUMBER_LONG".equals(questionType)) {
            double[] thisResult = getNumberResult(question, 1);
            resultMap.put("_total", Long.valueOf((long)thisResult[0]));
            resultMap.put("_tally", Long.valueOf((long)thisResult[1]));
            resultMap.put("_average", Long.valueOf((long)thisResult[2]));
            resultMap.put("_a_type", "long");
        } else if ("NUMBER_CURRENCY".equals(questionType)) {
            double[] thisResult = getNumberResult(question, 2);
            resultMap.put("_total", Long.valueOf((long)thisResult[0]));
            resultMap.put("_tally", Double.valueOf(thisResult[1]));
            resultMap.put("_average", Double.valueOf(thisResult[2]));
            resultMap.put("_a_type", "double");
        } else if ("NUMBER_FLOAT".equals(questionType)) {
            double[] thisResult = getNumberResult(question, 3);
            resultMap.put("_total", Long.valueOf((long)thisResult[0]));
            resultMap.put("_tally", Double.valueOf(thisResult[1]));
            resultMap.put("_average", Double.valueOf(thisResult[2]));
            resultMap.put("_a_type", "double");
        } else if ("SEPERATOR_LINE".equals(questionType) || "SEPERATOR_TEXT".equals(questionType)) {
            // not really a question; ingore completely
            return null;
        } else {
            // default is text
            resultMap.put("_total", Long.valueOf(getTextResult(question)));
            resultMap.put("_a_type", "text");
        }

        return resultMap;
    }

    private long[] getBooleanResult(GenericValue question) throws SurveyWrapperException {
        boolean beganTransaction = false;
        try {
            beganTransaction = TransactionUtil.begin();

            long[] result = { 0, 0, 0 };
            // index 0 = total responses
            // index 1 = total yes
            // index 2 = total no

            EntityListIterator eli = this.getEli(question, -1);

            if (eli != null) {
                GenericValue value;
                while (((value = eli.next()) != null)) {
                    if ("Y".equalsIgnoreCase(value.getString("booleanResponse"))) {
                        result[1]++;
                    } else {
                        result[2]++;
                    }
                    result[0]++; // increment the count
                }

                eli.close();
            }

            return result;
        } catch (GenericEntityException e) {
            try {
                // only rollback the transaction if we started one...
                TransactionUtil.rollback(beganTransaction, "Error getting survey question responses Boolean result", e);
            } catch (GenericEntityException e2) {
                Debug.logError(e2, "Could not rollback transaction: " + e2.toString(), module);
            }

            throw new SurveyWrapperException(e);
        } finally {
            try {
                // only commit the transaction if we started one...
                TransactionUtil.commit(beganTransaction);
            } catch (GenericEntityException e) {
                throw new SurveyWrapperException(e);
            }
        }
    }

    private double[] getNumberResult(GenericValue question, int type) throws SurveyWrapperException {
        double[] result = { 0, 0, 0 };
        // index 0 = total responses
        // index 1 = tally
        // index 2 = average

        boolean beganTransaction = false;
        try {
            beganTransaction = TransactionUtil.begin();

            EntityListIterator eli = this.getEli(question, -1);

            if (eli != null) {
                GenericValue value;
                while (((value = eli.next()) != null)) {
                    switch (type) {
                        case 1:
                            Long n = value.getLong("numericResponse");
                            if (UtilValidate.isNotEmpty(n)) {
                                result[1] += n.longValue();
                            }
                            break;
                        case 2:
                            Double c = value.getDouble("currencyResponse");
                            if (UtilValidate.isNotEmpty(c)) {
                                result[1] += (((double) Math.round((c.doubleValue() - c.doubleValue()) * 100)) / 100);
                            }
                            break;
                        case 3:
                            Double f = value.getDouble("floatResponse");
                            if (UtilValidate.isNotEmpty(f)) {
                                result[1] += f.doubleValue();
                            }
                            break;
                    }
                    result[0]++; // increment the count
                }

                eli.close();
            }
        } catch (GenericEntityException e) {
            try {
                // only rollback the transaction if we started one...
                TransactionUtil.rollback(beganTransaction, "Error getting survey question responses Number result", e);
            } catch (GenericEntityException e2) {
                Debug.logError(e2, "Could not rollback transaction: " + e2.toString(), module);
            }

            throw new SurveyWrapperException(e);
        } finally {
            try {
                // only commit the transaction if we started one...
                TransactionUtil.commit(beganTransaction);
            } catch (GenericEntityException e) {
                throw new SurveyWrapperException(e);
            }
        }

        // average
        switch (type) {
            case 1:
                if (result[0] > 0)
                    result[2] = ((long) result[1]) / ((long) result[0]);
                break;
            case 2:
                if (result[0] > 0)
                    result[2] = (((double) Math.round((result[1] / result[0]) * 100)) / 100);
                break;
            case 3:
                if (result[0] > 0)
                    result[2] = result[1] / result[0];
                break;
        }

        return result;
    }

    private long getTextResult(GenericValue question) throws SurveyWrapperException {
        long result = 0;

        try {
            result = EntityQuery.use(delegator).from("SurveyResponseAndAnswer")
                    .where(makeEliCondition(question))
                    .queryCount();
        } catch (GenericEntityException e) {
            Debug.logError(e, module);
            throw new SurveyWrapperException("Unable to get responses", e);
        }

        return result;
    }

    private Map<String, Object> getOptionResult(GenericValue question) throws SurveyWrapperException {
        Map<String, Object> result = new HashMap<String, Object>();
        long total = 0;

        boolean beganTransaction = false;
        try {
            beganTransaction = TransactionUtil.begin();

            EntityListIterator eli = this.getEli(question, -1);
            if (eli != null) {
                GenericValue value;
                while (((value = eli.next()) != null)) {
                    String optionId = value.getString("surveyOptionSeqId");
                    if (UtilValidate.isNotEmpty(optionId)) {
                        Long optCount = (Long) result.remove(optionId);
                        if (optCount == null) {
                            optCount = Long.valueOf(1);
                        } else {
                            optCount = Long.valueOf(1 + optCount.longValue());
                        }
                        result.put(optionId, optCount);
                        total++; // increment the count
                    }
                }

                eli.close();
            }
        } catch (GenericEntityException e) {
            try {
                // only rollback the transaction if we started one...
                TransactionUtil.rollback(beganTransaction, "Error getting survey question responses Option result", e);
            } catch (GenericEntityException e2) {
                Debug.logError(e2, "Could not rollback transaction: " + e2.toString(), module);
            }

            throw new SurveyWrapperException(e);
        } finally {
            try {
                // only commit the transaction if we started one...
                TransactionUtil.commit(beganTransaction);
            } catch (GenericEntityException e) {
                throw new SurveyWrapperException(e);
            }
        }

        result.put("_total", Long.valueOf(total));
        return result;
    }

    private EntityCondition makeEliCondition(GenericValue question) {
        return EntityCondition.makeCondition(UtilMisc.toList(EntityCondition.makeCondition("surveyQuestionId",
                EntityOperator.EQUALS, question.getString("surveyQuestionId")),
                EntityCondition.makeCondition("surveyId", EntityOperator.EQUALS, surveyId)), EntityOperator.AND);
    }

    private EntityListIterator getEli(GenericValue question, int maxRows) throws GenericEntityException {
        return EntityQuery.use(delegator).from("SurveyResponseAndAnswer")
                .where(makeEliCondition(question))
                .cursorScrollInsensitive()
                .maxRows(maxRows)
                .queryIterator();
    }

    @SuppressWarnings("serial")
    protected class SurveyWrapperException extends GeneralException {

        public SurveyWrapperException() {
            super();
        }

        public SurveyWrapperException(String str) {
            super(str);
        }

        public SurveyWrapperException(String str, Throwable nested) {
            super(str, nested);
        }

        public SurveyWrapperException(Throwable nested) {
            super(nested);
        }
    }
}
