var quickFS_INTERFACE_CONVERT = function() {
    var DATA;

    const COLUMN_TYPE_FEATURE = "0";
    const COLUMN_TYPE_TEMPLATE_QUESTION = "1";
    const COLUMN_TYPE_CORE_DATA = "2";
    const COLUMN_TYPE_KEY_PERFORMANCE_INDICATOR = "3";
    const COLUMN_TYPE_STATUS = "4";
//    const COLUMN_TYPE_PLACEHOLDER = "5";
//    const COLUMN_TYPE_BOOKABLE_STATUS_SYSTEMS = "6";
//    const COLUMN_TYPE_EXPORT_FORMAT = "7";
//    const COLUMN_TYPE_RFI_PROCESS = "8";
    const COLUMN_TYPE_RFI_TEMPLATE_QUESTION = "9";
//    const COLUMN_TYPE_LINE_ITEM_NUMBER = "10";
//    const COLUMN_TYPE_COMPANY_LOCATION_1 = "11";
//    const COLUMN_TYPE_COMPANY_LOCATION_2 = "12";

    const CONTRACT_STATUS_0 = "NOT_INTERESTED";
    const CONTRACT_STATUS_1 = "OPEN";
    const CONTRACT_STATUS_2 = "IN_PROCESS";
    const CONTRACT_STATUS_3 = "RELEASED";
    const CONTRACT_STATUS_4 = "ACCEPTED_CONTRACT";
    const CONTRACT_STATUS_5 = "REJECTED";
    const CONTRACT_STATUS_6 = "NEGOTIATION";
    const CONTRACT_STATUS_7 = "IN_NEGOTIATION";
    const CONTRACT_STATUS_8 = "RELEASED_NEGOTIATION";
    const CONTRACT_STATUS_9 = "REJECTED_NEGOTIATION";
    const CONTRACT_STATUS_10 = "IMPORTED_WITH_ERRORS";
    const CONTRACT_STATUS_11 = "FIRST_ACCEPTED";
    const CONTRACT_STATUS_12 = "SECOND_ACCEPTED";
    const CONTRACT_STATUS_13 = "FIRST_REJECTED";
    const CONTRACT_STATUS_14 = "SECOND_REJECTED";
    const CONTRACT_STATUS_15 = "NO_AGREEMENT";
    const CONTRACT_STATUS_16 = "COUNTER_OFFER";

    const PERMISSION_TYPE_0 = "PROJECT_MANAGER";
    const PERMISSION_TYPE_1 = "BUYER";
    const PERMISSION_TYPE_2 = "BUYER_ASSISTANT";
    const PERMISSION_TYPE_3 = "BUYER_READ_ONLY";
    const PERMISSION_TYPE_4 = "CHIEF_TRAVEL_MANAGER_OPERATIVE";
    const PERMISSION_TYPE_5 = "CHIEF_TRAVEL_MANAGER_PLACING";
    const PERMISSION_TYPE_6 = "TRAVEL_MANAGER_OPERATIVE";
    const PERMISSION_TYPE_7 = "TRAVEL_MANAGER_PLACING";
    const PERMISSION_TYPE_8 = "TRAVEL_MANAGER_READ_ONLY";
    const PERMISSION_TYPE_9 = "REPRESESANTIVE_PARENT_ORGANIZATION";
    const PERMISSION_TYPE_10 = "SUPPLIER";
    const PERMISSION_TYPE_11 = "SUPPLIER_ASSISTANT";
    const PERMISSION_TYPE_12 = "SUPPLIER_READ_ONLY";
    const PERMISSION_TYPE_13 = "NaN";

    return {
        "init":init,
        "getDefinition":getDefinition,
        "updateTenderMap":updateTenderMap,
        "updateTenderQuestionMap":updateTenderQuestionMap,
        "getUserRoleMap":getUserRoleMap,
        "updatePage":updatePage,
        "updatePageRow":updatePageRow,
        "getTenderOrganizationMap":getTenderOrganizationMap,
        "updateTenderQuestionAnswerMap":updateTenderQuestionAnswerMap,
        "getTenderFeatureAnswerMap":getTenderFeatureAnswerMap,
        "getQuestions":getQuestions,
        "getQuestion":getQuestion
    };

    // --------------------------------------------------------------------------------------------------
    // --------------------------------------------  public  --------------------------------------------
    // --------------------------------------------------------------------------------------------------

    // ---------------------- init object ----------------------

    function init(quickFS) {
        DATA = quickFS.DATA;
    }

    // ---------------------- definition stuff ----------------------

    function getDefinition(definitionBase) {
        var s = new Date();

        var definition = {};
        definition.columns = [];

        var colId = "";
        var definitionColumns = definitionBase.tenderColumnData;
        for (var i = 0; i < definitionColumns.length; i++) {
            var definitionColumn = definitionColumns[i];
            if (colId !== definitionColumn.colId) {
                colId = definitionColumn.colId;
                var columnType = definitionColumn.columnSettingType;
                switch (columnType) {
                case COLUMN_TYPE_FEATURE:
                case COLUMN_TYPE_TEMPLATE_QUESTION:
                case COLUMN_TYPE_RFI_TEMPLATE_QUESTION:
                    var column = getColumnDefinitionByQuestionId(definitionColumn);
                    definition.columns.push(column);
                    break;
                case COLUMN_TYPE_KEY_PERFORMANCE_INDICATOR:
                    var column = getColumnDefinitionKpi(definitionColumn, definitionColumns);
                    definition.columns.push(column);
                    break;
                case COLUMN_TYPE_CORE_DATA:
                case COLUMN_TYPE_STATUS:
                    var column = getColumnDefinitionByMessage(definitionColumn);
                    definition.columns.push(column);
                    break;
                default:
                    var column = getColumnDefinitionDefault(definitionColumn);
                    definition.columns.push(column);
                    break;
                }
            }
        }
        util.log.duration(s, "quickFS: convert definition");
        if (JSON.stringify(definition) !== "{}") return definition;
    }

    function updateTenderMap(tenderMap, tenderId, tenderData) {
        var s = new Date();

        if (!tenderMap) {
            tenderMap = {};
        }
        tenderMap[tenderId] = tenderData;

        util.log.duration(s, "quickFS: convert tenderMap");

        if (JSON.stringify(tenderMap) !== "{}") return tenderMap;
    }

    function updateTenderQuestionMap(tenderQuestionMap, tenderId, tenderQuestionData) {
        var s = new Date();

        if (!tenderQuestionMap) {
            tenderQuestionMap = {};
        }
        if (!tenderQuestionMap.hasOwnProperty(tenderId)) {
            tenderQuestionMap[tenderId] = {};
        }

        for (var i = 0; i < tenderQuestionData.length; i++) {
            var question = tenderQuestionData[i];
            if (!tenderQuestionMap[tenderId][question.questId]) {
                tenderQuestionMap[tenderId][question.questId] = {};
            }
            if (!tenderQuestionMap[tenderId][question.questId][question.processStepFormId]) {
                tenderQuestionMap[tenderId][question.questId][question.processStepFormId] = {};
            }
            tenderQuestionMap[tenderId][question.questId][question.processStepFormId][question.propId] = question;
        }

        util.log.duration(s, "quickFS: convert tenderQuestionMap");

        if (JSON.stringify(tenderQuestionMap) !== "{}") return tenderQuestionMap;
    }

    // ---------------------- user stuff ----------------------

    function getUserRoleMap(userData) {
        var s = new Date();

        var userMap = {};
        for (var i = 0; i < userData.length; i++) {
            var role = userData[i];
            userMap[role.roleName] = role;
        }

        util.log.duration(s, "quickFS: convert userMap");

        if (JSON.stringify(userMap) !== "{}") return userMap;
    }

    // ---------------------- page stuff ----------------------

    function updatePage(page) {
        var s = new Date();

        if (!page) {
            page = {};
        }
        DATA.pageBase.tenderOrganizationMap.forEach(function(organization, organizationId) {
            page = updatePageRow(page, DATA.filter.tenderId, organizationId, organization);
        }, DATA.pageBase.tenderOrganizationMap);

        util.log.duration(s, "quickFS: convert page");

        if (JSON.stringify(page) !== "{}") return page;
    }

    function updatePageRow(page, tenderId, organizationId, organization) {
        if (!page.rows) {
            page.rows = new Map();
        }
        var row = page.rows.get(organizationId);
        if (!row) {
            row = {};
            page.rows.set(organizationId, row);
        }
        row[tenderId] = {};
        row[tenderId].columns = {};
        if (!organization) {
            organization = DATA.pageBase.tenderOrganizationMap.get(organizationId);
        }
        addPageRowColumns(tenderId, row[tenderId].columns, tenderId, organization);

        return page;
    }

    function getTenderOrganizationMap(tenderOrganizationData) {
        var s = new Date();

        var tenderOrganizationMap = new Map();
        for (var i = 0; i < tenderOrganizationData.length; i++) {
            var organization = tenderOrganizationData[i];
            tenderOrganizationMap.set(organization.company_id, organization);
        }

        util.log.duration(s, "quickFS: convert tenderOrganizationMap");

        return tenderOrganizationMap;
    }

    function updateTenderQuestionAnswerMap(tenderQuestionAnswerMap, tenderId, tenderQuestionAnswers) {
        if (!tenderQuestionAnswerMap) {
            tenderQuestionAnswerMap = {};
        }

        for (var i = 0; i < tenderQuestionAnswers.length; i++) {
            var tenderQuestionAnswer = tenderQuestionAnswers[i];

            if (!tenderQuestionAnswerMap.hasOwnProperty(tenderId)) {
                tenderQuestionAnswerMap[tenderId] = {};
            }
            if (!tenderQuestionAnswerMap[tenderId].hasOwnProperty(tenderQuestionAnswer.serviceProviderId)) {
                tenderQuestionAnswerMap[tenderId][tenderQuestionAnswer.serviceProviderId] = {};
            }
            if (!tenderQuestionAnswerMap[tenderId][tenderQuestionAnswer.serviceProviderId].hasOwnProperty(tenderQuestionAnswer.templateQuestionId)) {
                tenderQuestionAnswerMap[tenderId][tenderQuestionAnswer.serviceProviderId][tenderQuestionAnswer.templateQuestionId] = {};
            }
            if (!tenderQuestionAnswerMap[tenderId][tenderQuestionAnswer.serviceProviderId][tenderQuestionAnswer.templateQuestionId].hasOwnProperty(tenderQuestionAnswer.processStepFormId)) {
                tenderQuestionAnswerMap[tenderId][tenderQuestionAnswer.serviceProviderId][tenderQuestionAnswer.templateQuestionId][tenderQuestionAnswer.processStepFormId] = {};
            }
            tenderQuestionAnswerMap[tenderId]
                                   [tenderQuestionAnswer.serviceProviderId]
                                   [tenderQuestionAnswer.templateQuestionId]
                                   [tenderQuestionAnswer.processStepFormId]
                                   [tenderQuestionAnswer.rowIndex] = tenderQuestionAnswer;

            // add a map entry to get answer by DER_ID, ignoring the processStepFormId
            var question = getQuestion(tenderId, tenderQuestionAnswer.templateQuestionId);
            if (question && question.questDER_ID) {
                if (!tenderQuestionAnswerMap[tenderId][tenderQuestionAnswer.serviceProviderId].hasOwnProperty(question.questDER_ID)) {
                    tenderQuestionAnswerMap[tenderId][tenderQuestionAnswer.serviceProviderId][question.questDER_ID] = {};
                }
                if (!tenderQuestionAnswerMap[tenderId][tenderQuestionAnswer.serviceProviderId][question.questDER_ID].hasOwnProperty(tenderQuestionAnswer.rowIndex)) {
                    tenderQuestionAnswerMap[tenderId][tenderQuestionAnswer.serviceProviderId][question.questDER_ID][tenderQuestionAnswer.rowIndex] = [];
                }
                tenderQuestionAnswerMap[tenderId]
                                       [tenderQuestionAnswer.serviceProviderId]
                                       [question.questDER_ID]
                                       [tenderQuestionAnswer.rowIndex].push(tenderQuestionAnswer);
            }

        }
        return tenderQuestionAnswerMap;
    }

    function getTenderFeatureAnswerMap(tenderFeatureAnswers) {
        var tenderFeatureAnswerMap = {};
        for (var i = 0; i < tenderFeatureAnswers.length; i++) {
            var tenderFeatureAnswer = tenderFeatureAnswers[i];
            if (!tenderFeatureAnswerMap.hasOwnProperty(tenderFeatureAnswer.serviceProviderId)) {
                tenderFeatureAnswerMap[tenderFeatureAnswer.serviceProviderId] = {};
            }
            tenderFeatureAnswerMap[tenderFeatureAnswer.serviceProviderId][tenderFeatureAnswer.questId] = tenderFeatureAnswer;
        }
        return tenderFeatureAnswerMap;
    }

    // ---------------------------------------------------------------------------------------------------
    // --------------------------------------------  private  --------------------------------------------
    // ---------------------------------------------------------------------------------------------------

    function getColumnDefinitionDefault(definitionColumn) {
        var column = {};
        column.id = definitionColumn.colId;
        column.type = definitionColumn.columnSettingType;
        column.questionId = definitionColumn.elExpression;
        column.caption = definitionColumn.columnSettingType + " - " + definitionColumn.label + " - " + definitionColumn.elExpression;
        return column;
    }

    function getColumnDefinitionByQuestionId(definitionColumn) {
        var processStepFormId = definitionColumn.processStepFormId;
        var questionId = definitionColumn.templateQuestionId;

        var column = {};
        column.id = definitionColumn.label;
        column.type = definitionColumn.columnSettingType;
        column.processStepFormId = processStepFormId;
        column.questionId = questionId;
        column.caption = getQuestionCaption(processStepFormId, questionId);
        return column;
    }

    function getQuestionCaption(processStepFormId, questionId) {
        var definitionColumnQuestion = getDefinitionColumnQuestion(questionId);
        return definitionColumnQuestion.questName ? definitionColumnQuestion.questName : "?" + questionId + "?";
    }

    function getColumnDefinitionByMessage(definitionColumn) {
        var column = {};
        column.id = definitionColumn.label;
        column.type = definitionColumn.columnSettingType;
        column.label = definitionColumn.label.split(".")[1].replace("}","");
        column.caption = util.message.get(column.label);
        return column;
    }

    function getColumnDefinitionKpi(definitionColumn, definitionColumns) {
        var processStepFormQuestions = getKpiProcessStepFormQuestionIds(definitionColumn.colId, definitionColumns);

        var column = {};
        column.id = "kpi" + definitionColumn.kpId;
        column.calculationType = definitionColumn.keyPerformanceCalculationType;
        column.functionType = definitionColumn.keyPerformanceFunctionType;
        column.type = definitionColumn.columnSettingType;
        column.questionId = "";
        column.processStepFormQuestions = processStepFormQuestions;
        column.caption = definitionColumn.kpName;
        return column;
    }

    function getKpiProcessStepFormQuestionIds(colId, definitionColumns) {
        var processStepFormQuestions = []
        for (var i = 0; i < definitionColumns.length; i++) {
            var definitionColumn = definitionColumns[i];
            if (definitionColumn.colId === colId) {
                processStepFormQuestions.push({ tenderId: definitionColumn.tenderId,
                                                processStepFormId: definitionColumn.processStepFormId,
                                                questionId: definitionColumn.templateQuestionId
                                              });
            }
        }
        return processStepFormQuestions;
    }

    // ---------------------- page stuff ----------------------

    function addPageRowColumns(tenderId, rowColumns, tenderId, organization) {
        var definitionColumns = DATA.definition.columns;
        for (var i = 0; i < definitionColumns.length; i++) {
            var definitionColumn = definitionColumns[i];
            var columnType = definitionColumn.type;
            switch (columnType) {
            case COLUMN_TYPE_FEATURE:
                addFeatureAnswer(rowColumns, organization, definitionColumn);
                break;
            case COLUMN_TYPE_TEMPLATE_QUESTION:
            case COLUMN_TYPE_RFI_TEMPLATE_QUESTION:
                addContractAnswer(rowColumns, tenderId, organization, definitionColumn);
                break;
            case COLUMN_TYPE_KEY_PERFORMANCE_INDICATOR:
                addValuesKpi(rowColumns, tenderId, organization, definitionColumn);
                break;
            case COLUMN_TYPE_CORE_DATA:
            case COLUMN_TYPE_STATUS:
                addValueMessage(rowColumns, tenderId, organization, definitionColumn);
                break;
            default:
                break;
            }
        }
    }

    function addFeatureAnswer(rowColumns, organization, definitionColumn) {
        var value = getFeatureAnswerValue(organization.company_id, definitionColumn.processStepFormId, definitionColumn.questionId);

        var column = {};
        column.id = definitionColumn.id;
        column.depictedValue = value;
        rowColumns[column.id] = column;
    }

    function addContractAnswer(rowColumns, tenderId, organization, definitionColumn) {
        var valueMap = {};
        var allRowsEmpty = getRowsValue(valueMap, tenderId, organization.company_id, definitionColumn.questionId, definitionColumn.processStepFormId);

        //var organization = DATA.pageBase.tenderOrganizationMap.get(organization.company_id);
        var question = getQuestion(tenderId, definitionColumn.questionId);

        var column = {};
        column.id = definitionColumn.id;
        column.value = "";
        column.depictedValue = "";
        column.answerId = 0;
        column.readOnly = isReadOnly(tenderId, organization, question);
        if (Object.keys(valueMap).length == 1) {        // value is not null
            column.value = valueMap[Object.keys(valueMap)[0]][0].value;
            column.depictedValue = valueMap[Object.keys(valueMap)[0]][0].depictedValue;
            column.answerId = valueMap[Object.keys(valueMap)[0]][0].id;
        }
        column.organizationId = organization.company_id;
        column.processStepFormId = definitionColumn.processStepFormId;
        column.questionId = definitionColumn.questionId;
        column.tenderId = tenderId;
        rowColumns[column.id] = column;
    }

    function isVisible(question) {
        return (question.questFsEditable == "1") || !isSimple(question);
    }

    function isReadOnly(tenderId, organization, question) {
        var readOnly;
        var tenderData = DATA.definitionBase.tenderMap[tenderId][0];
        var tenderColumnData = DATA.definitionBase.tenderColumnData[0];

        if (tenderId != DATA.tenderId) {
            readOnly = true;
        } else if (isSimple(question)) {
            readOnly = (question.questDisplayOnly == "1") || (tenderColumnData.tmsRestrictive == "1") && Date.parse(tenderColumnData.tmsEndDate) <= new Date();
        } else if (isCancellation(question)) {
            var projectRole = getProjectRole(tenderData);
            var buyerReadOnly = projectRole == PERMISSION_TYPE_0 || projectRole == PERMISSION_TYPE_1 || projectRole == PERMISSION_TYPE_2;
            var travelManagerReadOnly = projectRole == PERMISSION_TYPE_4 || projectRole == PERMISSION_TYPE_5 || projectRole == PERMISSION_TYPE_6 || projectRole == PERMISSION_TYPE_7;
            var noReadOnly = isGroupsWithoutDualCoreRestrictions(projectRole);

            var editCancellationLRA = false;
            var firstAcceptReject = buyerReadOnly || travelManagerReadOnly;
            if (firstAcceptReject) {
                editCancellationLRA = organization.contract_status != 4 && organization.contract_status != 5 &&
                                      (organization.closeStatusBuyer == "0" || noReadOnly);
            }

            if (question.questType == FIELD_TYPE_CANCELLATION_PARAMETERS) {
                var milestoneDisabled = (tenderColumnData.tmsRestrictive == "1") && Date.parse(tenderColumnData.tmsEndDate) <= new Date();
                readOnly = !editCancellationLRA || milestoneDisabled;
            } else if (question.questType == FIELD_TYPE_LRA) {
                readOnly = !editCancellationLRA;
            } else if (question.questType == FIELD_TYPE_BREAKFAST) {
                readOnly = (question.questDisplayOnly == "1") || (tenderColumnData.tmsRestrictive == "1") && Date.parse(tenderColumnData.tmsEndDate) <= new Date() || !editCancellationLRA;
            }
        }

        return readOnly;
    }

    function isMilestoneDisabled(tenderColumnData) {
        return (tenderColumnData.tmsRestrictive == "1") && Date.parse(tenderColumnData.tmsEndDate) <= new Date();
    }

    function isGroupsWithoutDualCoreRestrictions(projectRole) {
        return projectRole == PERMISSION_TYPE_0 || projectRole == PERMISSION_TYPE_1 || projectRole == PERMISSION_TYPE_4 || projectRole == PERMISSION_TYPE_5;
    }

    function getProjectRole(tenderData) {
        var projectRole = PERMISSION_TYPE_13;
        if (tenderData.leadingBusinessUnitId) {
            if (tenderData.tender_project_id <= 0) {
                projectRole = PERMISSION_TYPE_0;
            } else {
                for (var userRoleName in DATA.userRoleMap) {
                    var userRole = DATA.userRoleMap[userRoleName];
                    var pr;
                    switch (userRole.ugType) {
                    case "0":      // BUYER
                        pr = eval("PERMISSION_TYPE_" + userRole.ugBuyerStatus);
                        break;
                    case "1":      // TRAVEL_MANAGER
                        pr = eval("PERMISSION_TYPE_" + userRole.ugTravelManagerStatus);
                        break;
                    case "2":      // SERVICE_PROVIDER
                        pr = eval("PERMISSION_TYPE_" + userRole.ugServiceProviderStatus);
                        break;
                    }
                    if (pr) {
                        projectRole = pr;
                        break;
                    }
                }
            }
        }
        return projectRole;
    }

    function isSimple(question) {
        return (question.questType == FIELD_TYPE_STRING   || question.questType == FIELD_TYPE_TEXT ||
                question.questType == FIELD_TYPE_CHECKBOX || question.questType == FIELD_TYPE_RADIO)
               && question.questDimension == "0" && question.questFsEditable == "1";
    }

    function isCancellation(question) {
        return (question.questType == FIELD_TYPE_CANCELLATION_PARAMETERS ||
                question.questType == FIELD_TYPE_LRA                     ||
                question.questType == FIELD_TYPE_BREAKFAST)
               && question.questDimension == "0";
    }

    function addValuesKpi(rowColumns, tenderId, organization, definitionColumn) {
        var valueMap = getValuesByQuestions(tenderId, organization.company_id, definitionColumn.processStepFormQuestions);

        var column = {};
        column.id = definitionColumn.id;
        column.valueMap = valueMap;
        rowColumns[column.id] = column;
    }

    function getValuesByQuestions(tenderId, organizationId, processStepFormQuestions) {
        var valueMap = {};
        for (var i = 0; i < processStepFormQuestions.length; i++) {
            var processStepFormQuestionId = processStepFormQuestions[i];
            var definitionColumnTenderId = processStepFormQuestionId.tenderId;
            var definitionColumnQuestionId = processStepFormQuestionId.questionId;
            var definitionColumnProcessStepFormId = processStepFormQuestionId.processStepFormId;

            var allRowsEmpty = getRowsValue(valueMap, tenderId, organizationId, definitionColumnQuestionId, definitionColumnProcessStepFormId);
        }
        return valueMap;
    }

    function addValueMessage(rowColumns, tenderId, organization, definitionColumn) {
        if (organization.hasOwnProperty(definitionColumn.label) || definitionColumn.label === "purchase_season") {
            var column = {};
            column.id = definitionColumn.id;
            column.depictedValue = organization[definitionColumn.label];
            if (definitionColumn.label === "contract_status" ||
                definitionColumn.label === "dual_control_contract_status") {
                column.depictedValue = util.message.get(eval("CONTRACT_STATUS_" + column.depictedValue));
            } else if (definitionColumn.label === "purchase_season") {
                column.depictedValue = DATA.definitionBase.tenderMap[tenderId][0].purchase_season;
            }
//            var tenderColumnData = DATA.definitionBase.tenderColumnData[0];
//            column.readOnly = isMilestoneDisabled(tenderColumnData);
            rowColumns[column.id] = column;
        }
    }

    function getRowsValue(valueMap, tenderId, organizationId, definitionColumnQuestionId, definitionColumnProcessStepFormId) {
        var allRowsEmpty;
        var definitionColumnQuestion = getDefinitionColumnQuestion(definitionColumnQuestionId);

        // get all answers for a tenderId, organizationId and the questionId and processStepFormId of the columnDefinition
        // this should work for the requested tender
        var answerRows = getTenderQuestionAnswerRowsByQuestionId(tenderId, organizationId, definitionColumnQuestionId, definitionColumnProcessStepFormId);
        if (answerRows) {
            allRowsEmpty = getAnswerRowsValues(valueMap, definitionColumnQuestion, answerRows);
        } else {
            // try to find a different processStepFormId for the given questionId and than using it to get answers
            // this may be the case within tenders of the previous years when the form has been revised
            var processStepFormIds = getProcessStepFormIdsByQuestionId(tenderId, definitionColumnQuestionId);
            if (processStepFormIds) {
                for (processStepFormId in processStepFormIds) {
                    answerRows = getTenderQuestionAnswerRowsByQuestionId(tenderId, organizationId, definitionColumnQuestionId, processStepFormId);
                    if (answerRows) {
                        allRowsEmpty = getAnswerRowsValues(valueMap, definitionColumnQuestion, answerRows);
                        if (!allRowsEmpty) {
                            break;
                        }
                    }
                }
            }
        }
        if (!answerRows) {
            // last chance, try to find answers by the DER_ID of the given questionId
            // this may be the case within tenders of the previous years when the form and buildingBlock have been revised
            var answerRowsArray = getTenderQuestionAnswerRowsArrayByDerId(tenderId, organizationId, definitionColumnQuestion.questDER_ID);
            if (answerRowsArray) {
                for (var answerRowsIndex in answerRowsArray) {
                    answerRows = answerRowsArray[answerRowsIndex];
                    allRowsEmpty = getAnswerRowsValues(valueMap, definitionColumnQuestion, answerRows);
                    if (!allRowsEmpty) {
                        break;
                    }
                }
            }
        }

        return allRowsEmpty;
    }

    function getTenderQuestionAnswerRowsByQuestionId(tenderId, organizationId, questionId, processStepFormId) {
        var orgaNodes = DATA.pageBase.tenderQuestionAnswerMap[tenderId];
        var questNodes = orgaNodes ? orgaNodes[organizationId] : undefined;
        var formNodes = questNodes ? questNodes[questionId] : undefined;
        var answerRows = formNodes ? formNodes[processStepFormId] : undefined;
        return answerRows;
    }

    function getTenderQuestionAnswerRowsArrayByDerId(tenderId, organizationId, derId) {
        var orgaNodes = DATA.pageBase.tenderQuestionAnswerMap[tenderId];
        var questNodes = orgaNodes ? orgaNodes[organizationId] : undefined;
        var answerRowsArray = questNodes ? questNodes[derId] : undefined;
        return answerRowsArray;
    }

    function getProcessStepFormIdsByQuestionId(tenderId, questionId) {
        var questNodes = DATA.definitionBase.tenderQuestionMap[tenderId];
        var formNodes = questNodes ? questNodes[questionId] : undefined;
        return formNodes;
    }

    function getQuestions(tenderId, questionId) {
        var formNodes = getProcessStepFormIdsByQuestionId(tenderId, questionId);
        var questions = (formNodes && Object.keys(formNodes).length > 0) ?
                           formNodes[Object.keys(formNodes)[0]] : undefined;
        return questions;
    }

    function getQuestion(tenderId, questionId) {
        var questions = getQuestions(tenderId, questionId);
        var question = (questions && Object.keys(questions).length > 0) ?
                           questions[Object.keys(questions)[0]] : undefined;
        return question;
    }

    function getDefinitionColumnQuestion(questionId) {
        var definitionColumnQuestion = getQuestion(DATA.filter.tenderId, questionId);
        return definitionColumnQuestion;
    }

    function getAnswerRowsValues(valueMap, definitionColumnQuestion, answerRows) {
        var allRowsEmpty = true;
        for (var rowIndex in answerRows) {
            var answerNode = answerRows[rowIndex];
            var value = answerNode.value;
            var depictedValue = getAnswerDepictedValue(definitionColumnQuestion, answerNode);

            if (value !== "") {
                allRowsEmpty = false;
            }

            var values = valueMap[rowIndex];
            if (!values) {
                values = [];
            }
            valueMap[rowIndex] = values;

            if (values.length == 0 || values.some(e => e.id !== answerNode.id)) {
                var answerMap = {};
                answerMap.id = answerNode.id;
                answerMap.value = value;
                answerMap.depictedValue = depictedValue;
                values.push(answerMap);
            }
        }
        return allRowsEmpty;
    }

    function getAnswerDepictedValue(question, answerNode) {
        var answerDepictedValue = "";

        if (answerNode) {
            switch (question.questType) {
            case FIELD_TYPE_LRA:
                answerDepictedValue = (answerNode.depictedValue === "true") ? util.message.get("lra") : util.message.get("non_lra");
                break;
            case FIELD_TYPE_YESNO:
            case FIELD_TYPE_CHECKBOX:
            case FIELD_TYPE_TABLE_CONDITIONAL:
                answerDepictedValue = (answerNode.depictedValue === "true") ? util.message.get("yes") : util.message.get("no");
                break;
            case FIELD_TYPE_BREAKFAST:
                answerDepictedValue = util.message.get(answerNode.depictedValue);
                break;
            default:
                answerDepictedValue = answerNode.depictedValue;
                break;
            }
        }

        return answerDepictedValue;
    }

    function getFeatureAnswerValue(organizationId, processStepFormId, questionId) {
        var answerValue = "";
        var definitionColumnQuestion = getDefinitionColumnQuestion(questionId);
        var answerNode = DATA.pageBase.tenderFeatureAnswerMap[organizationId][questionId];

        if (answerNode) {
            switch (definitionColumnQuestion.featType) {
            case "YESNO":
                answerValue = (answerNode.value === "true") ? util.message.get("yes") : util.message.get("no");
                break;
            default:
                answerValue = answerNode.value;
                break;
            }
        }

        return answerValue;
    }

}
