##############################################################################
#
# Copyright (c) 2002-2011 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# 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 2
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
import unittest
import os
import random

from DateTime import DateTime
from Products.CMFCore.utils import _checkPermission
from string import zfill
from string import split
from string import replace
from re import search

from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from Products.ERP5Type.tests.ERP5TypeTestCase import _getConversionServerDict
from Products.ERP5Type.tests.backportUnittest import skip
from Products.ERP5Type.tests.utils import reindex
from Products.DCWorkflow.DCWorkflow import ValidationFailed
from AccessControl import getSecurityManager
from AccessControl.SecurityManagement import newSecurityManager
from Products.ERP5Type.tests.Sequence import SequenceList
from Products.ERP5Form.PreferenceTool import Priority

from Products.ERP5Type.tests.utils import FileUpload
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase,\
                                                       _getConversionServerDict
from Products.ERP5OOo.tests.testIngestion import FILENAME_REGULAR_EXPRESSION
from Products.ERP5OOo.tests.testIngestion import REFERENCE_REGULAR_EXPRESSION

def makeFilePath(name):
  return os.path.join(os.path.dirname(__file__), 'test_data', name)

def makeFileUpload(name):
  path = makeFilePath(name)
  return FileUpload(path, name)

class TestQuestionnaire(ERP5TypeTestCase):
  username = 'username'
  answer_type_list = ['float_value','integer_value','string_value']
  clear_module_list = []
  before_close_clear_module_list = []
  users = dict(assignor = None, auditor = None, author = None)
  
  def getTitle(self):
    return "Test Questionnaire"
  
  def getBusinessTemplateList(self):
    """
    Tuple of Business Templates we need to install
    """
    return ('erp5_base',
            'erp5_credential',
            'erp5_deferred_style',
            'erp5_ingestion',
            'erp5_ingestion_mysql_innodb_catalog',
            'erp5_web',
            'erp5_dms',
            'erp5_ods_style',
            'erp5_odt_style',
            'erp5_workflow',
            'erp5_survey')

  def afterSetUp(self):
    """
    This is ran before anything, used to set the environment
    """
    # here, you can create the categories and objects your test will depend on
    self.portal = self.getPortal()
    self.assertTrue(self.portal is not None)

    #Create users to interact with the questionnaire (ran only once)
    # let's create the users
    self.person_module = self.portal.getDefaultModule(portal_type='Person')
    self.organisation_module = self.portal.getDefaultModule(portal_type='Organisation')

    self.organisation = self._newOrganisation()
    person_remove_list = []
    
    self.user_dict = {
     'assignor': dict(title ='Assignor', function = '', first_name='Assi', last_name='Gnor'),
     'auditor' : dict(title ='Auditor', function = '', first_name='Audi', last_name='Tor'),
     'author'  : dict(title ='Author', function = '', first_name='Au', last_name='Thor'),
     'owner'   : dict(title ='Owner', function = '', first_name='Ow', last_name='Ner'),
    }

    
    #for i in range(0,3):
    #  person = self.createSimpleUser(**user_list[i])
    #  for (prop, value) in property_dict_list[i].iteritems(): 
    #    person.setProperty(prop,value)
    #  person.setCareerSubordinationValue(organisation)
    #  #person_remove_list.append(person.getId())
    self.before_close_clear_module_list.append(self.person_module)
    self.before_close_clear_module_list.append(person_remove_list)
    self.before_close_clear_module_list.append(self.organisation_module)
    self.before_close_clear_module_list.append([self.organisation.getId()])
    
    self.setDefaultSitePreference()
    self.tic()

    self.question_module = self.portal.getDefaultModule(portal_type='Boolean Question')
    self.assertTrue(self.question_module is not None)
    self.questionnaire_module = self.portal.getDefaultModule(portal_type='Questionnaire')
    self.assertTrue(self.questionnaire_module is not None)
    self.person_module = self.portal.getDefaultModule(portal_type='Person')
    self.assertTrue(self.person_module is not None)
    self.organisation_module = self.portal.getDefaultModule(portal_type='Organisation')
    self.assertTrue(self.organisation_module is not None)
    self.answer_set_module = self.portal.getDefaultModule(portal_type='Answer Set')
    self.assertTrue(self.answer_set_module is not None)
    self.correction_module = self.portal.getDefaultModule(portal_type='Correction')
    self.assertTrue(self.correction_module is not None)
    self.document_module = self.portal.getDefaultModule(portal_type='Spreadsheet')
    self.assertTrue(self.document_module is not None)
    self.standard_category_module =  self.portal.standard_category_module #self.portal.portal_catalog(portal_type='Standard Category Module')[0] #Standard Category Module is not Base Category's default module
    self.assertTrue(self.standard_category_module is not None)
    
  def setDefaultSitePreference(self):
    default_pref = self.portal.portal_preferences.default_site_preference
    conversion_dict = _getConversionServerDict()
    default_pref.setPreferredOoodocServerAddress(conversion_dict['hostname'])
    default_pref.setPreferredOoodocServerPortNumber(conversion_dict['port'])
    if self.portal.portal_workflow.isTransitionPossible(default_pref, 'enable'):
      default_pref.enable()
    return default_pref

  def beforeTearDown(self):
    i = 0
    n = len(self.clear_module_list)/2
    # clear modules if necessary
    for i in range(0,n):
      self.clear_module_list[2*i].manage_delObjects(list(self.clear_module_list[2*i+1]))
    self.clear_module_list = []
    self.tic()

#  def beforeClose(self):
#    i = 0
#    n = len(self.before_close_clear_module_list)/2
#    # clear modules if necessary
#    for i in range(0,n):
#      self.before_close_clear_module_list[2*i].manage_delObjects(list(self.before_close_clear_module_list[2*i+1]))
#    self.before_close_clear_module_list = []
#    self.tic()

  def createUserAndLogin(self, name='auditor', role_list = ['Auditor']):
    """login with Assignee, Assignor & Author roles."""
    role_list += ['Assignor']
    self.login()
    uf = self.getPortal().acl_users
    user = uf.getUserById(name)
    if user is None:
      title = self.user_dict[name]['title']
      first_name = self.user_dict[name]['first_name']
      last_name = self.user_dict[name]['last_name']
      function = self.user_dict[name]['function']
      person = self.createSimpleUser(title, name, function)
      person.setFirstName(first_name)
      person.setLastName(last_name)
      uf._doAddUser(name, '', role_list, [])
      #user = uf.getUserById(name)
      self.tic()
    else:
      person = self.portal.portal_catalog(portal_type="Person", reference=name)[0]
    self.logout()
    self.login(name)
    self.portal.REQUEST.other.update(dict(AUTHENTICATED_USER=getSecurityManager().getUser(),))
    return person
    #newSecurityManager(None, user.__of__(uf))
    #return user.ERP5Site_getAuthenticatedMemberPersonValue()

  def userLogin(self, name='auditor'):
    """login with username"""
    self.login(name)
    return self.portal.portal_catalog(portal_type="Person", reference=name)[0]

  def _newQuestion(self, portal_type = 'Boolean Question', title_suffix = '', value_property_id='string_value'):
    # Helper function to create a new Question
    if portal_type == 'Boolean Question' :
      question = self.question_module.newContent( portal_type = portal_type,
                                title       = 'Some ' + portal_type + ' Title' + title_suffix, 
                                comment     = 'Some Comment',
                                description = 'Some Description',
                                max_grade   =  10,
                                true_text   = 'Sure',
                                false_text  = 'Absolutely not',
                                batch_mode  = True
                              )
    elif portal_type == 'Statement':
      question = self.question_module.newContent( portal_type = portal_type,
                                title       = 'Some ' + portal_type + ' Title' + title_suffix, 
                                comment     = 'Some Comment',
                                description = 'Some Description',
                                batch_mode  =  True
                              )
    elif portal_type == 'Document Question':
      question = self.question_module.newContent( portal_type = portal_type,
                                title       = 'Some ' + portal_type + ' Title' + title_suffix, 
                                comment     = 'Some Comment',
                                description = 'Some Description',
                                answer_portal_type = 'Spreadsheet',
                                max_grade   =  10,
                                batch_mode  =  True
                              )
    elif portal_type in ('Selection Question', 'Multi Selection Question'):
      question = self.question_module.newContent( portal_type = portal_type,
                                title       = 'Some ' + portal_type + ' Title' + title_suffix, 
                                comment     = 'Some Comment',
                                description = 'Some Description',
                                max_grade   =  10,
                                value_property_id = value_property_id,
                                batch_mode  =  True
                              )
    else:
      question = self.question_module.newContent( portal_type = portal_type,
                                title       = 'Some ' + portal_type + ' Title' + title_suffix, 
                                comment     = 'Some Comment',
                                description = 'Some Description',
                                max_grade   =  10,
                                batch_mode  =  True
                              )
    return question

  def _getQuestionPortalTypeList(self, include_statement = True, everything = True, multiple_choice = False):
    l =  []
    if everything:
      l = ['Boolean Question','Float Question','Integer Question', 'String Question', 'Text Question', 'Multi Selection Question', 'Selection Question','Document Question']
    else :
      if multiple_choice:
        l = ['Multi Selection Question', 'Selection Question']
      else :
        l = ['Boolean Question','Float Question','Integer Question', 'String Question', 'Text Question','Document Question']
    if include_statement:
      l.append('Statement')
    return l
    

  def _CreateQuestion(self, portal_type = 'Statement'):
    """
    Use case:
        - creating a question of Portal Type portal_type
    """
    self.createUserAndLogin(name = 'assignor', role_list = ['Assignor'])
    question_number = len(self.question_module.objectValues())

    question = self._newQuestion(portal_type = portal_type)
    self.assertTrue(question is not None) 
    self.assertEquals(question.getPortalType(), portal_type) 
    self.assertEquals(question.getTitle(), 'Some ' + portal_type + ' Title')
    self.assertEquals(question.getComment(), 'Some Comment')
    self.assertEquals(question.getDescription(), 'Some Description')
    if portal_type != 'Statement':
      self.assertEquals(question.getMaxGrade(), 10)
    if portal_type == 'Boolean Question':
      self.assertEquals(question.getTrueText(), 'Sure')
      self.assertEquals(question.getFalseText(), 'Absolutely not')
    elif portal_type == 'Document Question':
      self.assertEquals(question.getAnswerPortalType(), 'Spreadsheet')
     
    self.assertEquals(len(self.question_module.objectValues()), question_number + 1)
    self.assertEquals(len(question.objectValues()), 0)
      
    # Check that the question is inserted in the question module
    self.assertEquals(question.getParentValue().getRelativeUrl(), self.question_module.getRelativeUrl())
      
    # the question should be in draft state
    self.assertEquals(question.getValidationState(), 'draft')
    
  def test_01_StatementCreation(self):
    self._CreateQuestion(portal_type = 'Statement')

  def test_02_BooleanQuestionCreation(self):
    self._CreateQuestion(portal_type = 'Boolean Question')

  def test_03_DocumentQuestionCreation(self):
    self._CreateQuestion(portal_type = 'Document Question')

  def test_04_FloatQuestionCreation(self):
    self._CreateQuestion(portal_type = 'Float Question')

  def test_05_IntegerQuestionCreation(self):
    self._CreateQuestion(portal_type = 'Integer Question')

  def test_06_MultiSelectionQuestionCreation(self):
    self._CreateQuestion(portal_type = 'Multi Selection Question') 

  def test_07_SelectionQuestionCreation(self):
    self._CreateQuestion(portal_type = 'Selection Question')

  def test_08_StringQuestionCreation(self):
    self._CreateQuestion(portal_type = 'String Question')

  def test_09_TextQuestionCreation(self):
    self._CreateQuestion(portal_type = 'Text Question')

  def _addPossibleAnswer(self, question = None, string_value = 'some_string_answer', integer_value = 10, float_value = 10.5):
    value_property_id = question.getValuePropertyId()
    if value_property_id == 'float_value':
      title = 'Some Possible Answer (' + value_property_id + ':' + str(float_value) +')'
      possible_answer = question.newContent(portal_type = 'Possible Answer',
                          title       = title,
                          description = 'Some Description',
                          float_value = float_value,
                          batch_mode  = True
                          )
    elif value_property_id == 'integer_value':
      title = 'Some Possible Answer (' + value_property_id + ':' + str(integer_value) +')'
      possible_answer = question.newContent(portal_type = 'Possible Answer',
                          title       = title,
                          description = 'Some Description',
                          integer_value = integer_value,
                          batch_mode  = True
                          )
    elif value_property_id == 'string_value':
      title = 'Some Possible Answer (' + value_property_id + ':' + string_value +')'
      possible_answer = question.newContent(portal_type = 'Possible Answer',
                          title       = title,
                          string_value= string_value,
                          description = 'Some Description',
                          batch_mode  = True
                          )

    return possible_answer

  def _CreatePossibleAnswer(self, portal_type = 'Selection Question', value_property_id = 'float_value'):
    """
    Use case:
        - creating a possible answer with value_property_id answer value
    """
    self.createUserAndLogin(name = 'assignor', role_list = ['Assignor'])

    question = self._newQuestion(portal_type = portal_type, value_property_id = value_property_id)
    self.assertTrue(question is not None)

    possible_answer = self._addPossibleAnswer(question = question)
    self.assertTrue(possible_answer is not None)
    self.assertEquals(possible_answer.getPortalType(),'Possible Answer')
    self.assertEquals(question.getValuePropertyId(), value_property_id)
    self.assertEquals(possible_answer.getDescription(),  'Some Description')
    if value_property_id == 'float_value':
      self.assertEquals(possible_answer.getTitle(),'Some Possible Answer (float_value:10.5)')
      self.assertEquals(possible_answer.getFloatValue() , 10.5)
    elif value_property_id == 'integer_value':
      self.assertEquals(possible_answer.getTitle(),'Some Possible Answer (integer_value:10)')
      self.assertEquals(possible_answer.getIntegerValue(), 10)
    elif value_property_id == 'string_value':
      self.assertEquals(possible_answer.getTitle(),'Some Possible Answer (string_value:some_string_answer)')
      self.assertEquals(possible_answer.getStringValue(),'some_string_answer')
    self.assertEquals(len(possible_answer.objectValues()), 0)
    self.assertEquals(possible_answer.getParentValue().getRelativeUrl(), question.getRelativeUrl())     
    self.assertEquals(len(question.objectValues()), 1)

  def test_10_MultiSelectionPossibleFloatAnswerCreation(self):
    self._CreatePossibleAnswer(portal_type = 'Multi Selection Question',  value_property_id = 'float_value')

  def test_11_SelectionPossibleFloatAnswerCreation(self):
    self._CreatePossibleAnswer(portal_type = 'Selection Question', value_property_id = 'float_value')

  def test_12_MultiSelectionPossibleStringAnswerCreation(self):
    self._CreatePossibleAnswer(portal_type = 'Multi Selection Question', value_property_id = 'string_value')

  def test_13_SelectionPossibleStringAnswerCreation(self):
    self._CreatePossibleAnswer(portal_type = 'Selection Question', value_property_id = 'string_value')

  def test_14_MultiSelectionPossibleIntegerAnswerCreation(self):
    self._CreatePossibleAnswer(portal_type = 'Multi Selection Question', value_property_id = 'integer_value')

  def test_15_SelectionPossibleIntegerAnswerCreation(self):
    self._CreatePossibleAnswer(portal_type = 'Selection Question', value_property_id = 'integer_value')

  def _newQuestionnaire(self):
    # Helper function to create a new Questionnaire
    questionnaire = self.questionnaire_module.newContent( portal_type = 'Questionnaire',
                                title       = 'Some Questionnaire Title',
                                comment     = 'Some Comment',
                                description = 'Some Description',
                                batch_mode  = True
                              )
    return questionnaire

  def test_16_QuestionnaireCreation(self):
    """
    Use case:
        - creating a questionnaire
    """
    self.createUserAndLogin(name = 'assignor', role_list = ['Assignor'])
    questionnaire_number = len(self.questionnaire_module.objectValues())

    start_time = DateTime()
    questionnaire = self._newQuestionnaire()
    stop_time = DateTime()
    self.assertTrue(questionnaire is not None)
    self.assertEquals(questionnaire.getPortalType(), 'Questionnaire')
    self.assertEquals(questionnaire.getComment(), 'Some Comment')
    self.assertEquals(questionnaire.getValidationState(), 'draft')
    self.assertTrue(questionnaire.getModificationDate() is not None and questionnaire.getModificationDate() >= start_time and questionnaire.getModificationDate() <= stop_time)
    self.assertEquals(questionnaire.getStateBaseCategory(), 'current_state')
    self.assertEquals(questionnaire.getDescription(), 'Some Description')
    self.assertEquals(questionnaire.getTitle(), 'Some Questionnaire Title')
    self.assertEquals(len(questionnaire.getResourceList()), 0)
    self.assertTrue(questionnaire.getSource() is None)
    
    self.assertEquals(len(questionnaire.objectValues()), 0)
    self.assertEquals(len(self.questionnaire_module.objectValues()), questionnaire_number + 1)
    self.assertEquals(questionnaire.getParentValue().getRelativeUrl(), self.questionnaire_module.getRelativeUrl())


  def _newQuestionnaireVariable(self, questionnaire = None):
    # Helper function to create a new Variable in a Questionnaire
    variable = questionnaire.newContent( portal_type = 'Variable',
                                title       = 'Some Variable Title',
                                comment     = 'Some Comment',
                                description = 'Some Description',
                                initial_value = 'python: 1',
                                automatic_update = 1,
                                batch_mode  = True
                              )
    return variable

  def test_17_QuestionnaireVariableCreation(self):
    """
    Use case:
        - creating a variable in a questionnaire
    """
    self.createUserAndLogin(name = 'assignor', role_list = ['Assignor'])

    questionnaire = self._newQuestionnaire()
    self.assertTrue(questionnaire is not None)

    variable = self._newQuestionnaireVariable(questionnaire = questionnaire)
    self.assertTrue(variable is not None)

    self.assertTrue(variable.getPortalType() == 'Variable')
    self.assertTrue(variable.getComment() == 'Some Comment')
    self.assertEquals(variable.getInitialValue(), 1)
    self.assertEquals(variable.getAutomaticUpdate(), 1)
    self.assertTrue(variable.getDescription() ==  'Some Description')
    self.assertTrue(variable.getTitle() == 'Some Variable Title')
    
    self.assertEquals(len(questionnaire.objectValues()), 1)
    self.assertEquals(len(variable.objectValues()), 0)
    self.assertEquals(variable.getParentValue().getRelativeUrl(), questionnaire.getRelativeUrl())

  def _newQuestionState(self, questionnaire = None, question = None):
    # Helper function to create a new Question State in a Questionnaire
    question_state = questionnaire.newContent( portal_type = 'Question State',
                                title       = 'Some Question State Title',
                                description = 'Some Description',
                                batch_mode  = True
                              )
    question_state.setResourceValue(question)
    return question_state

  def _CreateQuestionState(self, question_type = 'Boolean Question'):
    """
    Use case:
        - creating a question state in a questionnaire with a question of type question
        - setting it as initial question state for its parent questionnaire
    """
    self.createUserAndLogin(name = 'assignor', role_list = ['Assignor'])

    questionnaire = self._newQuestionnaire()
    self.assertTrue(questionnaire is not None)

    question = self._newQuestion(portal_type = question_type)
    self.assertTrue(question is not None)

    question_state = self._newQuestionState(questionnaire = questionnaire, question = question)
    self.assertTrue(question_state is not None)

    questionnaire.setSourceValue(question_state)
    self.assertEquals(questionnaire.getSourceValue().getRelativeUrl(), question_state.getRelativeUrl())

    self.assertEquals(question_state.getPortalType(), 'Question State')
    self.assertEquals(question_state.getDescription(), 'Some Description')
    self.assertEquals(question_state.getResourceValue().getRelativeUrl(), question.getRelativeUrl())
    self.assertEquals(question.getTitle(), question_state.getResourceTitle())
    
    self.assertEquals(len(questionnaire.objectValues()), 1)
    self.assertEquals(len(question_state.objectValues()), 0)
    self.assertEquals(question_state.getParentValue().getRelativeUrl(), questionnaire.getRelativeUrl())

  def test_18_StatementStateCreation(self):
    self._CreateQuestionState(question_type = 'Statement')

  def test_19_BooleanQuestionStateCreation(self):
    self._CreateQuestionState(question_type = 'Boolean Question')

  def test_20_DocumentQuestionStateCreation(self):
    self._CreateQuestionState(question_type = 'Document Question')

  def test_21_FloatQuestionStateCreation(self):
    self._CreateQuestionState(question_type = 'Float Question')

  def test_22_IntegerQuestionStateCreation(self):
    self._CreateQuestionState(question_type = 'Integer Question')

  def test_23_MultiSelectionQuestionStateCreation(self):
    self._CreateQuestionState(question_type = 'Multi Selection Question') 

  def test_24_SelectionQuestionStateCreation(self):
    self._CreateQuestionState(question_type = 'Selection Question')

  def test_25_StringQuestionStateCreation(self):
    self._CreateQuestionState(question_type = 'String Question')

  def test_26_TextQuestionStateCreation(self):
    self._CreateQuestionState(question_type = 'Text Question')

  def _newAnswerTransition(self, question_state = None, destination_question_state = None, condition = 'True', after_script_id = '', before_script_id = ''):
    # Helper function to create a new Answer Transition in a Question State
    answer_transition = question_state.newContent( portal_type = 'Answer Transition',
                                title       = 'Some Answer Transition Title',
                                description = 'Some Description',
                                guard_expression = 'python: ' + condition,
                                before_script_id = before_script_id,
                                after_script_id = after_script_id,
                                batch_mode  = True
                              )
    answer_transition.setDestinationValue(destination_question_state)
    return answer_transition

  def test_27_AnswerTransitionCreation(self):
    """
    Use case:
        - creating an answer transition in a question state
    """
    self.createUserAndLogin(name = 'assignor', role_list = ['Assignor'])

    questionnaire = self._newQuestionnaire()
    self.assertTrue(questionnaire is not None)

    question = self._newQuestion()
    self.assertTrue(question is not None)

    destination_question = self._newQuestion(portal_type = 'Selection Question')
    self.assertTrue(destination_question is not None)

    question_state = self._newQuestionState(questionnaire = questionnaire, question = question)
    self.assertTrue(question_state is not None)

    destination_question_state = self._newQuestionState(questionnaire = questionnaire, question = destination_question)
    self.assertTrue(destination_question_state is not None)

    answer_transition = self._newAnswerTransition(question_state = question_state, destination_question_state = destination_question_state, condition = 'False', after_script_id = 'after_script_id', before_script_id = 'before_script_id')
    self.assertTrue(answer_transition is not None)

    self.assertEquals(answer_transition.getPortalType(), 'Answer Transition')
    self.assertEquals(answer_transition.getTitle(), 'Some Answer Transition Title')
    self.assertEquals(answer_transition.getDescription(), 'Some Description')
    self.assertEquals(answer_transition.getGuardExpression(),False)
    self.assertEquals(answer_transition.getBeforeScriptId(),'before_script_id')
    self.assertEquals(answer_transition.getAfterScriptId(),'after_script_id')

    self.assertEquals(answer_transition.getDestinationValue().getRelativeUrl(), destination_question_state.getRelativeUrl())
    
    self.assertEquals(len(questionnaire.objectValues()), 2)
    self.assertEquals(len(question_state.objectValues()), 1)
    self.assertEquals(len(destination_question_state.objectValues()), 0)
    self.assertEquals(len(answer_transition.objectValues()), 0)
    self.assertEquals(answer_transition.getParentValue().getRelativeUrl(), question_state.getRelativeUrl())

  def _newTransitionVariable(self, answer_transition = None, causality = None):
    # Helper function to create a new Transition Variable in a Question State
    transition_variable = answer_transition.newContent( portal_type = 'Transition Variable',
                                title       = 'Some Transition Variable Title',
                                description = 'Some Description',
                                comment = 'Some Comment',
                                initial_value = 'python: False',
                                batch_mode  = True
                              )
    transition_variable.setCausalityValue(causality.getRelativeUrl())
    return transition_variable

  def test_28_TransitionVariableCreation(self):
    """
    Use case:
        - creating an Transition Variable in a question state
    """
    self.createUserAndLogin(name = 'assignor', role_list = ['Assignor'])

    questionnaire = self._newQuestionnaire()
    self.assertTrue(questionnaire is not None)

    variable = self._newQuestionnaireVariable(questionnaire = questionnaire)
    self.assertTrue(variable is not None)

    question = self._newQuestion()
    self.assertTrue(question is not None)

    destination_question = self._newQuestion(portal_type = 'Selection Question')
    self.assertTrue(destination_question is not None)

    question_state = self._newQuestionState(questionnaire = questionnaire, question = question)
    self.assertTrue(question_state is not None)

    destination_question_state = self._newQuestionState(questionnaire = questionnaire, question = destination_question)
    self.assertTrue(destination_question_state is not None)

    answer_transition = self._newAnswerTransition(question_state = question_state, destination_question_state = destination_question_state)
    self.assertTrue(answer_transition is not None)

    transition_variable = self._newTransitionVariable(answer_transition = answer_transition, causality = variable)
    self.assertTrue(transition_variable is not None)

    self.assertEquals(transition_variable.getPortalType(), 'Transition Variable')
    self.assertEquals(transition_variable.getTitle(), 'Some Transition Variable Title')
    self.assertEquals(transition_variable.getDescription(), 'Some Description')
    self.assertEquals(transition_variable.getInitialValue(),False)
    self.assertEquals(transition_variable.getComment(),'Some Comment')
    self.assertEquals(transition_variable.getCausalityValue().getRelativeUrl(),variable.getRelativeUrl())
    
    self.assertEquals(len(questionnaire.objectValues()), 3)
    self.assertEquals(len(question_state.objectValues()), 1)
    self.assertEquals(len(destination_question_state.objectValues()), 0)
    self.assertEquals(len(answer_transition.objectValues()), 1)
    self.assertEquals(len(transition_variable.objectValues()), 0)
    self.assertEquals(transition_variable.getParentValue().getRelativeUrl(), answer_transition.getRelativeUrl())

  def _newAnswerSet(self, person = None, questionnaire = None, pattern_list = []):
    # Helper function to create a new Answer Set in a Questionnaire
    answer_set = self.answer_set_module.newContent( portal_type = 'Answer Set',
                                title       = 'Some Answer Set Title',
                                description = 'Some Description',
                                start_date = DateTime('2000/10/10 10:10:00 GMT+2'),
                                stop_date = DateTime('2011/11/11 11:11:11 GMT+2'),
                                pattern_list = pattern_list,
                                batch_mode  = True
                              )
    answer_set.setCausalityValue(questionnaire)
    answer_set.setSourceValue(person)
    answer_set.AnswerSet_getReference()
    answer_set.setTitle(answer_set.getReference())
    return answer_set

  def _newOrganisation(self, title = 'Some Organisation Title'):
    # Helper function to create an organisation
    organisation = self.organisation_module.newContent( portal_type = 'Organisation',
                                title       = title,
                                batch_mode  = True
                              )

    return organisation

  def _newPerson(self, organisation = None, first_name = 'First Name', last_name = 'Last Name'):
    # Helper function to create a Person
    person = self.person_module.newContent( portal_type = 'Person',
                                first_name       = first_name,
                                last_name = last_name,
                                batch_mode  = True
                              )
    person.setCareerSubordinationValue(organisation)
    return person

  def _checkReferenceAndTitle(self, answer_set, reference, complete = False):
    if complete:
      self.assertEquals(answer_set.getTitle(), reference)
      self.assertEquals(answer_set.getReference(), reference)
    else:
      splitted_reference = reference.split('-')  
      self.assertEquals(answer_set.getTitle().split('-')[0:-1], splitted_reference)
      self.assertEquals(answer_set.getReference().split('-')[0:-1], splitted_reference)

  def test_29_AnswerSetCreation(self):
    """
    Use case:
        - creating an Answer Set
    """
    self.createUserAndLogin(name = 'assignor', role_list = ['Assignor'])

    questionnaire = self._newQuestionnaire()
    self.assertTrue(questionnaire is not None)

    organisation = self._newOrganisation()
    self.assertTrue(organisation is not None)

    person = self._newPerson(organisation = organisation)
    self.assertTrue(person is not None)

    self.createUserAndLogin(name = 'author', role_list = ['Author'])

    answer_set = self._newAnswerSet(person = person, questionnaire = questionnaire, pattern_list = ['organisation_type/hospital'])
    self.assertTrue(answer_set is not None)

    reference = 'A-' + organisation.getTitle() + '-' + person.getFirstName() + '-' + person.getLastName()

    self.assertEquals(answer_set.getPortalType(), 'Answer Set')
    self.assertEquals(answer_set.getDescription(), 'Some Description')
    self.assertEquals(answer_set.getStartDate(), DateTime('2000/10/10 10:10:00 GMT+2'))
    self.assertEquals(answer_set.getStopDate(), DateTime('2011/11/11 11:11:11 GMT+2'))
    self.assertEquals(answer_set.getPatternList(), ['organisation_type/hospital'])
    self.assertEquals(answer_set.getVersion(), '001')
    self._checkReferenceAndTitle(answer_set, reference)
    self.assertEquals(answer_set.getCausalityValue().getRelativeUrl(),questionnaire.getRelativeUrl())
    self.assertEquals(answer_set.getSourceValue().getRelativeUrl(),person.getRelativeUrl())
    self.assertEquals(answer_set.getValidationState(),'draft')
    self.assertEquals(answer_set.getGrade(),0)
    self.assertEquals(answer_set.AnswerSet_calculateMaxGrade(),0)
    self.assertEquals(len(answer_set.objectValues()), 0)
    self.assertEquals(answer_set.getParentValue().getRelativeUrl(), self.answer_set_module.getRelativeUrl())

  def _newCorrection(self, title = None, portal_type = 'Correction', person = None, question_list = [], category_list = [], grade_reduction = 10, is_general_value = True):
    # Helper function to create a new Correction in the Correction Module
    if title is None:
      title       = 'Some '+ portal_type + ' Title'
    if portal_type == 'Correction':
      correction = self.correction_module.newContent( portal_type = portal_type,
                                title       = title,
                                description = 'Some Description',
                                is_general_value = is_general_value,
                                grade_reduction = grade_reduction,
                                batch_mode  = True
                              )
    else:
      correction = self.correction_module.newContent( portal_type = portal_type,
                                title       = title,
                                description = 'Some Description',
                                is_general_value = is_general_value,
                                grade_reduction = grade_reduction,
                                correction_category_list = category_list,
                                batch_mode  = True
                              )
    correction.setAggregateValueList(question_list)
    correction.setSourceValue(person)

    return correction

  def _CreateCorrection(self, portal_type = 'Correction'):
    """
    Use case:
        - creating an Correction
    """
    self.createUserAndLogin(name = 'assignor', role_list = ['Assignor'])

    question = self._newQuestion()
    self.assertTrue(question is not None)

    other_question = self._newQuestion(portal_type = 'Selection Question')
    self.assertTrue(other_question is not None)

    person = self._newPerson()
    self.assertTrue(person is not None)

    correction = self._newCorrection(portal_type = portal_type, person = person,  question_list = [question, other_question], category_list = ['Function','Role'])
    self.assertTrue(correction is not None)

    self.assertEquals(correction.getPortalType(), portal_type)
    self.assertEquals(correction.getTitle(), 'Some ' + portal_type + ' Title')
    self.assertEquals(correction.getDescription(), 'Some Description')
    self.assertEquals(correction.getIsGeneralValue(), True)
    self.assertEquals(correction.getGradeReduction(), 10)
    if portal_type == 'Category Correction':
      self.assertEquals(correction.getCorrectionCategoryList(), ['Function','Role'])
    
    self.assertEquals(correction.getAggregateValueList()[0].getRelativeUrl(), question.getRelativeUrl())
    self.assertEquals(correction.getAggregateValueList()[1].getRelativeUrl(), other_question.getRelativeUrl())
    self.assertEquals(correction.getSourceValue().getRelativeUrl(), person.getRelativeUrl())
   
    self.assertEquals(len(correction.objectValues()), 0)
    self.assertEquals(correction.getParentValue().getRelativeUrl(), self.correction_module.getRelativeUrl())


  def test_30_CorrectionCreation(self):
    self._CreateCorrection()

  def test_31_CategoryCorrectionCreation(self):
    self._CreateCorrection(portal_type = 'Category Correction')

  def _newCorrectionLine(self, parent = None, correction = None, grade_reduction = 5, default_grade_reduction = True):
    # Helper function to create a new Correction Line
    correction_line = parent.newContent( portal_type = 'Correction Line',
                                comment = 'Some Comment',
                                grade_reduction = grade_reduction,
                                batch_mode  = True
                              )
    correction_line.setGradeReduction(correction.getGradeReduction())
    correction_line.setSourceValue(correction)
    if not default_grade_reduction:
      correction_line.setGradeReduction(grade_reduction)
    return correction_line

  def _newDocument(self, portal_type = 'Spreadsheet'):
    # Helper function to create a new Document
    document = self.document_module.newContent(portal_type = portal_type,
                                batch_mode = True
                              )

    return document

  def _newAnswer(self, answer_set = None, question = None, document = None, empty = False):
    # Helper function to create a new Answer in an Answer Set
    kw = { 'portal_type' : 'Answer',
           'batch_mode' : True,
         }
    if question is not None:
      kw['resource'] = question.getRelativeUrl()
    if not empty:
      kw.update ({ 'comment' : 'Some Comment',
                   'int_index' : 10,
                   'no_answer_reason' : 'do_not_know',
                   'start_date' : DateTime('2000/10/10 10:10:00 GMT+2'),
                   'stop_date' : DateTime('2011/11/11 11:11:11 GMT+2'),
                  })
      if question is not None:
        kw['rank'] = question.getMaxGrade()
        value_property_id = question.getValuePropertyId()
        if value_property_id == 'aggregate' and document is not None:
          kw['aggregate'] = document.getRelativeUrl()
        else:
          values   = { 'boolean_value' : 1,
                       'float_value' : 3.14,
                       'integer_value' : 4,
                       'string_value' : 'Some String Value',
                       'text_value' : 'Some Text Value',
                       'list_value' : ['Some','List','Values'],
                     }

    answer = answer_set.newContent(**kw)
    return answer

  def _CreateCorrectionLine(self, parent_type = 'Answer Set'):
    """
    Use case:
        - creating an Correction Line
    """
    self.createUserAndLogin(name = 'assignor', role_list = ['Assignor'])

    correction = self._newCorrection(portal_type = 'Correction', person = None,  question_list = [], category_list = ['Function','Role'])
    self.assertTrue(correction is not None)

    self.createUserAndLogin(name = 'author', role_list = ['Author'])
    answer_set = self._newAnswerSet(person = None, questionnaire = None, pattern_list = ['organisation_type/hospital'])
    self.assertTrue(answer_set is not None)


    if parent_type == 'Answer Set':
      parent = answer_set
    else:
      answer = self._newAnswer(answer_set = answer_set)
      parent = answer
      self.assertTrue(answer is not None)
    
    self.userLogin(name = 'assignor')
    correction_line = self._newCorrectionLine(parent = parent, correction = correction)
    self.assertTrue(correction_line is not None)

    self.assertEquals(correction_line.getPortalType(), 'Correction Line')
    self.assertEquals(correction_line.getTitle(), 'Some Correction Title')
    self.assertEquals(correction_line.getComment(), 'Some Comment')
    self.assertEquals(correction_line.getGradeReduction(), 10)

    self.assertEquals(correction_line.getSourceValue().getRelativeUrl(), correction.getRelativeUrl())

    self.assertEquals(len(correction_line.objectValues()), 0)
    self.assertEquals(len(answer_set.objectValues()), 1)
    self.assertEquals(correction_line.getParentValue().getRelativeUrl(), parent.getRelativeUrl())


  def test_32_AnswerSetCorrectionLineCreation(self):
    self._CreateCorrectionLine()

  def _CreateAnswer(self):
    """
    Use case:
        - creating an Answer
    """
    self.createUserAndLogin(name = 'assignor', role_list = ['Assignor'])
    question = self._newQuestion()
    self.assertTrue(question is not None)

    self.createUserAndLogin(name = 'author', role_list = ['Author'])
    answer_set = self._newAnswerSet(person = None, questionnaire = None, pattern_list = ['organisation_type/hospital'])
    self.assertTrue(answer_set is not None)

    document = self._newDocument()
    self.assertTrue(document is not None)

    self.userLogin(name = 'assignor')
    answer = self._newAnswer(answer_set = answer_set, question = question, document = document)
    self.assertTrue(answer is not None)

    self.assertEquals(answer.getPortalType(), 'Answer')
    self.assertEquals(answer.getComment(), 'Some Comment')
    self.assertEquals(answer.getIntIndex(), 10)
    self.assertEquals(answer.Answer_getValuePropertyId(), 'boolean_value')
    self.assertEquals(answer.getNoAnswerReason(), 'do_not_know')
    self.assertEquals(answer.getBooleanValue(), 0)
    self.assertEquals(answer.Answer_getValueText(), 'Absolutely not')

    self.assertEquals(answer.getStartDate(), DateTime('2000/10/10 10:10:00 GMT+2'))
    self.assertEquals(answer.getStopDate(), DateTime('2011/11/11 11:11:11 GMT+2'))

    self.assertEquals(answer.getGrade(), 10)

    self.assertEquals(answer.getResourceValue().getRelativeUrl(), question.getRelativeUrl())

    self.assertEquals(len(answer.objectValues()), 0)
    self.assertEquals(len(answer_set.objectValues()), 1)
    self.assertEquals(answer.getParentValue().getRelativeUrl(), answer_set.getRelativeUrl())

  def test_33_AnswerCreation(self):
    self._CreateAnswer()

  def test_34_AnswerCorrectionLineCreation(self):
    self._CreateCorrectionLine(parent_type = 'Answer')

  def _findArchivedAnswerSet(self, reference, version = 1):
    answer_sets = self.answer_set_module.objectValues()
    found = False
    archived_answer_set = None
    for answer_set in answer_sets:
      found = answer_set.getReference() == reference and answer_set.getValidationState() == 'archived' and int(answer_set.getVersion()) == version
      if found:
        archived_answer_set = answer_set
        break
    return archived_answer_set

  def _checkRequestedAnswerSet(self, answer_set = None, reference = 'A----1', version = '001'):
    version_number = int(version)
    new_version_number = version_number + 1
    new_version = '%s' % zfill(new_version_number, 3)
    self.assertEquals(answer_set.getVersion(), new_version)

    archived_answer_set = self._findArchivedAnswerSet(reference, version_number)
    self.assertTrue(archived_answer_set is not None)
    self._checkReferenceAndTitle(archived_answer_set, reference, True)
    self.assertEquals(archived_answer_set.getVersion(), version)
    self.assertEquals(archived_answer_set.getSourceValue().getRelativeUrl(), answer_set.getSourceValue().getRelativeUrl())
    self.assertEquals(archived_answer_set.getCausalityValue().getRelativeUrl(), answer_set.getCausalityValue().getRelativeUrl())
    self.assertEquals(archived_answer_set.getDescription(), answer_set.getDescription())
    self.assertEquals(archived_answer_set.getStartDate(), answer_set.getStartDate())
    self.assertEquals(archived_answer_set.getStopDate(), answer_set.getStopDate())
    self.assertEquals(archived_answer_set.getPatternList(), answer_set.getPatternList())


  def test_35_AnswerSetWorkflow(self):
    """
    Use case:
        - create 2 Answer Sets
        - First Answer Set is deleted directly
        - The second one follows the following transitions (in order to test every transition possible):
          draft -> submitted -> released -> requested -> submitted -> requested -> submitted -> archived -> deleted
    """
    self.createUserAndLogin(role_list = ['Assignor'], name='assignor')
    questionnaire = self._newQuestionnaire()
    self.assertTrue(questionnaire is not None)

    organisation = self._newOrganisation()
    self.assertTrue(organisation is not None)

    person = self._newPerson(organisation = organisation)
    self.assertTrue(person is not None)

    self.createUserAndLogin(role_list = ['Author'], name='owner')
    answer_set = self._newAnswerSet(questionnaire = questionnaire, person = person)
    self.assertTrue(answer_set is not None)
    self.assertEquals(answer_set.getValidationState(), 'draft')

    self.userLogin(name = 'assignor')
    answer_set.delete()
    self.assertEquals(answer_set.getValidationState(), 'deleted')

    self.userLogin(name = 'owner')
    other_answer_set = self._newAnswerSet(questionnaire = questionnaire, person = person)
    self.assertTrue(other_answer_set is not None)

    self.assertEquals(other_answer_set.getValidationState(), 'draft')

    other_answer_set.submit()
    self.assertEquals(other_answer_set.getValidationState(), 'submitted')

    self.userLogin(name = 'assignor')
    other_answer_set.release()
    reference = other_answer_set.getReference()
    self.assertEquals(other_answer_set.getValidationState(), 'released')
    other_answer_set.request()
    self.assertEquals(other_answer_set.getValidationState(), 'requested')
    version = other_answer_set.getVersion()
    self._checkRequestedAnswerSet(answer_set = other_answer_set, reference = reference)


    self.userLogin(name = 'owner')
    other_answer_set.submit()
    self.assertEquals(other_answer_set.getValidationState(), 'submitted')

    self.userLogin(name = 'assignor')
    reference = other_answer_set.getReference()
    other_answer_set.request()
    self.assertEquals(other_answer_set.getValidationState(), 'requested')
    self._checkRequestedAnswerSet(answer_set = other_answer_set, reference = reference, version = '002')
    
    self.userLogin(name = 'owner')
    other_answer_set.submit()
    self.assertEquals(other_answer_set.getValidationState(), 'submitted')

    self.userLogin(name = 'assignor')
    other_answer_set.archive()
    self.assertEquals(other_answer_set.getValidationState(), 'archived')

    other_answer_set.delete()
    self.assertEquals(other_answer_set.getValidationState(), 'deleted')

  def _createQuestionAndAdd(self, questionnaire = None, portal_type = 'Boolean Question', question_state_list = [], title_suffix = ''):
    question = self._newQuestion(portal_type = portal_type, title_suffix = title_suffix)
    self.assertTrue(question is not None)
    
    question_state = self._newQuestionState(questionnaire = questionnaire, question = question)
    self.assertTrue(question_state is not None)

    n = len(question_state_list)

    if n != 0 :
      answer_transition = self._newAnswerTransition(question_state = question_state, destination_question_state = question_state_list[n-1])
      self.assertTrue(answer_transition is not None)

    return (question, question_state)


  def _answerQuestion(self, question = None, answer_set = None, int_index = 1, no_answer_given = False):
    portal_type = question.getPortalType()
    no_answer_reason = 'do_not_know'
    comment = 'Some Comment'
    start_date = DateTime()
    if portal_type == 'Boolean Question':
      if no_answer_given:
        return answer_set.BooleanQuestion_answerQuestion(no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
      else :
        return answer_set.BooleanQuestion_answerQuestion(boolean_answer = 1, no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
    elif portal_type == 'Document Question':
      if no_answer_given:
        return answer_set.DocumentQuestion_answerQuestion(no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
      else :
        filename = 'sample_attachment.ods'
        file_object = makeFileUpload(filename)
        return answer_set.DocumentQuestion_answerQuestion(file = file_object, no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True, simulation_mode = True)
    elif portal_type == 'Float Question':
      if no_answer_given:
        return answer_set.FloatQuestion_answerQuestion(no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
      else :
        return answer_set.FloatQuestion_answerQuestion(float_answer = 3.14159265, no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
    elif portal_type == 'Integer Question':
      if no_answer_given:
        return answer_set.IntegerQuestion_answerQuestion(no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
      else :   
        return answer_set.IntegerQuestion_answerQuestion(integer_answer = 34, no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
    elif portal_type == 'Statement':
      return answer_set.Statement_answerQuestion(int_index = int_index, batch_mode = True)  
    elif portal_type == 'String Question':
      if no_answer_given:
        return answer_set.StringQuestion_answerQuestion(no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
      else :    
        return answer_set.StringQuestion_answerQuestion(string_answer = 'some_string_answer', no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
    elif portal_type == 'Text Question':
      if no_answer_given:
        return answer_set.TextQuestion_answerQuestion(no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
      else :       
        return answer_set.TextQuestion_answerQuestion(text_answer = 'some_text_answer', no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
    elif portal_type == 'Selection Question':
      if no_answer_given:
        return answer_set.SelectionQuestion_answerQuestion(no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
      else :
        answer = question.objectValues()[0]
        value_property_id = answer.getValuePropertyId()
        if value_property_id == 'float_value':
          selection_answer = answer.getFloatValue()
        elif value_property_id == 'integer_value':
          selection_answer = answer.getIntegerValue()
        else:
          selection_answer = answer.getStringValue()
        return answer_set.SelectionQuestion_answerQuestion(selection_answer = selection_answer, other_answer = 'Some Other Answer', no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
    elif portal_type == 'Multi Selection Question':
      if no_answer_given:
        return answer_set.MultiSelectionQuestion_answerQuestion(no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
      else :
        multiselection_answer = []
        answer = question.objectValues()[0]
        value_property_id = answer.getValuePropertyId()
        if value_property_id == 'float_value':
          multiselection_answer.append(answer.getFloatValue())
          multiselection_answer.append(question.objectValues()[1].getFloatValue())
        elif value_property_id == 'integer_value':
          multiselection_answer.append(answer.getIntegerValue())
          multiselection_answer.append(question.objectValues()[1].getIntegerValue())
        else:
          multiselection_answer.append(answer.getStringValue())
          multiselection_answer.append(question.objectValues()[1].getStringValue())
        return answer_set.MultiSelectionQuestion_answerQuestion(multiselection_answer = multiselection_answer, other_answer = 'Some Other Answer', no_answer_reason = no_answer_reason, comment = comment, start_date = start_date, int_index = int_index, batch_mode = True)
  
  def _checkCategory(self, category, parent_category, id = 'category', title = 'Category', short_title = 'Short Title', int_index = 0, reference = 'CAT', codification = 'CAT', description = 'Category Description'):
    self.assertEquals(category['id'], id)
    self.assertEquals(category['title'], title)
    self.assertEquals(category['short_title'], short_title)
    self.assertEquals(category['description'], description)    
    self.assertEquals(str(category['int_index']), str(int_index))
    self.assertEquals(category['reference'], reference)
    self.assertEquals(category['codification'], codification)
    self.assertEquals(category['parent'], parent_category)

  def _checkAnswer(self, answer = None, question = None, no_answer_given = False):
    portal_type = question.getPortalType()
    if portal_type == 'Boolean Question':
      if no_answer_given:
        self.assertEquals(answer.getBooleanValue(), 0)
      else:
        self.assertEquals(answer.getBooleanValue(), 1)
    elif portal_type == 'Document Question':
      aggregate = answer.getAggregateValue()
      if no_answer_given:
        self.assertTrue(aggregate is None or not aggregate or aggregate.getExternalProcessingState() == 'empty')
        self.assertEquals(answer.getValueText(), 'No Document')
      else:
        self.assertEquals(aggregate.getFilename(), 'sample_attachment.ods')
        categories = answer.getCategoryDict(simulation_mode = True)
        self.assertEquals(len(categories),2)
        self.assertTrue('base_category' in categories)
        self.assertTrue('base_category_2' in categories)
        base_category = categories['base_category']
        self.assertTrue('base_category/category' in base_category)
        self.assertTrue('base_category/category/child_category' in base_category)
        base_category_2 = categories['base_category_2']
        self.assertEquals(len(base_category_2),0)
        self.assertEquals(len(base_category),2)
        self._checkCategory(base_category['base_category/category'],'base_category')
        self._checkCategory(base_category['base_category/category/child_category'], 'base_category/category', id = 'child_category', title = 'Child Category', reference = 'CHILD', codification = 'CHILD', description = 'Child Category Description')
    elif portal_type == 'Float Question':
      if no_answer_given:
        self.assertEquals(answer.getFloatValue(), 0)
        self.assertEquals(answer.getProperty(answer.Answer_getValuePropertyId()), 0)
        self.assertEquals(answer.Answer_getValueText(), '0.0')
      else:
        self.assertEquals(answer.getFloatValue(), 3.14159265)
        self.assertEquals(answer.getProperty(answer.Answer_getValuePropertyId()), 3.14159265)
        self.assertEquals(answer.Answer_getValueText(), '3.14159265')
    elif portal_type == 'Integer Question':
      if no_answer_given:
        self.assertEquals(answer.getIntegerValue(), 0)
        self.assertEquals(answer.getProperty(answer.Answer_getValuePropertyId()), 0)
        self.assertEquals(answer.Answer_getValueText(), '0')
      else:
        self.assertEquals(answer.getIntegerValue(), 34)
        self.assertEquals(answer.getProperty(answer.Answer_getValuePropertyId()), 34)
        self.assertEquals(answer.Answer_getValueText(), '34')
    elif portal_type == 'String Question':
      if no_answer_given:
        self.assertEquals(answer.getStringValue(), '')
        self.assertEquals(answer.getProperty(answer.Answer_getValuePropertyId()), '')
        self.assertEquals(answer.Answer_getValueText(), '')
      else:
        self.assertEquals(answer.getStringValue(), 'some_string_answer')
        self.assertEquals(answer.getProperty(answer.Answer_getValuePropertyId()), 'some_string_answer')
        self.assertEquals(answer.Answer_getValueText(), 'some_string_answer')
    elif portal_type == 'Text Question':
      if no_answer_given:
        self.assertEquals(answer.getTextValue(), '')
        self.assertEquals(answer.getProperty(answer.Answer_getValuePropertyId()), '')
        self.assertEquals(answer.Answer_getValueText(), '')
      else:
        self.assertEquals(answer.getTextValue(), 'some_text_answer')
        self.assertEquals(answer.getProperty(answer.Answer_getValuePropertyId()), 'some_text_answer')
        self.assertEquals(answer.Answer_getValueText(), 'some_text_answer')
    elif portal_type == 'Selection Question':
      if no_answer_given:
        self.assertEquals(answer.getFloatValue(), 0) 
        self.assertEquals(answer.getStringValue(), '')
        self.assertEquals(answer.getIntegerValue(), 0) 
      else:
        possible_answer = question.objectValues()[0]
        value_property_id = possible_answer.getValuePropertyId()
        self.assertEquals(answer.Answer_getValuePropertyId(), value_property_id) 
        if value_property_id == 'float_value':
          self.assertEquals(answer.getFloatValue(), possible_answer.getFloatValue()) 
          self.assertEquals(answer.getStringValue(), 'Some Other Answer') 
        elif value_property_id == 'integer_value':
          self.assertEquals(answer.getIntegerValue(), possible_answer.getIntegerValue())
          self.assertEquals(answer.getStringValue(), 'Some Other Answer') 
        else:
          self.assertEquals(answer.getStringValue(), possible_answer.getStringValue()) 
    elif portal_type == 'Multi Selection Question':
      if no_answer_given:
        self.assertEquals(0, len(answer.getListValueList()))
      else:
        value_property_id = question.getValuePropertyId()
        self.assertEquals(answer.Answer_getValuePropertyId(), 'list_value')
        self.assertEquals(answer.getStringValue(), 'Some Other Answer')
        i = 0
        n = len(question.objectValues())
        self.assertEquals(n, len(answer.getListValueList()))
        if value_property_id == 'float_value':
          for i in range(0,n):
            self.assertEquals(question.objectValues()[i].getFloatValue(),answer.getListValueList()[i])
            i += 1;
        elif value_property_id == 'integer_value':
          for i in range(0,n):
            self.assertEquals(question.objectValues()[i].getIntegerValue(),answer.getListValueList()[i])
            i += 1;
        else:
       	  for i in range(0,n):
            self.assertEquals(question.objectValues()[i].getStringValue(),answer.getListValueList()[i])
            i += 1;

  def _fillOut(self, question_list, answer_set, no_answer_given, url, answer_number = 0):
    for question in question_list:
      if question.getPortalType() != 'Statement' or len(answer_set.getAnswerHistoryList()) == 0:
        # check if the link is correct and contains the name of the question's portal type
        if search(question.getPortalType().replace(' ', ''), url) is None:
          self.fail(question.getPortalType() + " != " + url + '\n' + repr(map(lambda x: x.getTitle(), question_list)) + '\n' + repr(map(lambda x: x.getTitle(), answer_set.objectValues())))
        self.assertTrue(search(question.getPortalType().replace(' ', ''), url) is not None)
        
        batch = self._answerQuestion(question = question, answer_set = answer_set, no_answer_given = no_answer_given)
        url = batch['url']
        answer = batch['answer']  
        if question.getPortalType() != 'Statement':
          self.assertEquals(no_answer_given, batch['no_answer_given'])

          # has the answer set at least a new object ?
          new_answer_number = len(answer_set.objectValues())
          self.assertTrue(new_answer_number > answer_number)
          answer_number = new_answer_number

          self.assertEquals(answer.getResourceValue().getRelativeUrl(),question.getRelativeUrl())
          self.assertEquals(answer.getNoAnswerReason(),'do_not_know')
          self.assertEquals(answer.getComment(),'Some Comment')
          self.assertTrue(answer.getStartDate() is not None)
          self.assertTrue(answer.getStopDate() is not None)
          self._checkAnswer(answer = answer, question = question, no_answer_given = no_answer_given)
    return answer_number

  def _fillOutTest(self, questionnaire_context = True, no_answer_given = False, fill_out_again = False, edition = None):
    """
    Use case:
        - create a questionnaire with questions of every type possible
        - user fills out the questionnaire (using directly the fill out button in the questionnaire or in the answer set)
    """

    self.createUserAndLogin(role_list = ['Assignor'], name='assignor')
    answer_set_number = len(self.answer_set_module.objectValues())
    questionnaire = self._newQuestionnaire()
    organisation = self._newOrganisation()
    self.assertTrue(organisation is not None)

    question_list = []
    question_state_list = []
    i = 0
    for portal_type in self._getQuestionPortalTypeList(everything = False):
      question, question_state = self._createQuestionAndAdd(questionnaire = questionnaire, portal_type = portal_type, question_state_list = question_state_list, title_suffix = str(i))
      question_list.insert(0,question)
      question_state_list.append(question_state)
      i += 1

    for portal_type in self._getQuestionPortalTypeList(include_statement = False, everything = False, multiple_choice = True):
      for value_property_id in self.answer_type_list:      
        question, question_state = self._createQuestionAndAdd(questionnaire = questionnaire, portal_type = portal_type, question_state_list = question_state_list, title_suffix = str(i))
        question_list.insert(0,question)
        question_state_list.append(question_state)
        i += 1
        possible_answer = self._addPossibleAnswer(question = question)
        self.assertTrue(possible_answer is not None)
        possible_answer = self._addPossibleAnswer(question = question, string_value = 'some_string_answer_2', integer_value = 12, float_value = 3.14159265)
        self.assertTrue(possible_answer is not None)
     
    questionnaire.setSourceValue(question_state)
    questionnaire.validate()
    person = self.createUserAndLogin(role_list = ['Author'], name='author')
    
    person.setCareerSubordinationValue(organisation)
    if questionnaire_context:
      batch = questionnaire.Questionnaire_createAnswerSet(batch_mode = True)
      answer_set = batch['answer_set']
      int_index = 1
    else:        
      answer_set = self._newAnswerSet(person = person, questionnaire = questionnaire)
      batch = answer_set.AnswerSet_viewNextQuestionDialog(batch_mode = True)
    question = batch['question']
    url = batch['url']

    #  was something added to answer_set_module ?
    self.assertEquals(len(self.answer_set_module.objectValues()),answer_set_number + 1)
    
    reference = 'A-' + organisation.getTitle() + '-' + person.getFirstName() + '-' + person.getLastName()
    
    # let's see if the answer set created is how we expect it
    self._checkReferenceAndTitle(answer_set, reference)
    self.assertEquals(answer_set.getSourceValue().getRelativeUrl(), person.getRelativeUrl())
    self.assertEquals(answer_set.getCausalityValue().getRelativeUrl(), questionnaire.getRelativeUrl())
    self.assertEquals(answer_set.getVersion(), '001')
    self.assertEquals(len(answer_set.objectValues()), 0)
    self.assertEquals(answer_set.getValidationState(), 'draft')
    self.assertTrue(answer_set.getStartDate() is not None)

    # let's fill out the answer set
    if fill_out_again:
      n = len(question_list)/2
      remaining_question_list = question_list[n:]
      question_list = question_list[0:n]
    else:
      remaining_question_list = []

    answer_number = self._fillOut(question_list, answer_set, no_answer_given, url)
    
    if edition is not None:
      self.userLogin(name = 'assignor')
      questionnaire.update()
      if edition != 'nothing':
        if edition == 'first':
          answer_number = 0
          question, question_state = self._createQuestionAndAdd(questionnaire = questionnaire, portal_type = 'Boolean Question', question_state_list = question_state_list, title_suffix = str(i))
          questionnaire.setSourceValue(question_state)
          question_state_list.append(question_state)
          remaining_question_list.insert(0, question)
        elif edition == 'last':
          question, question_state = self._createQuestionAndAdd(questionnaire = questionnaire, portal_type = 'Boolean Question', question_state_list = [], title_suffix = str(i))
          self._newAnswerTransition(question_state = question_state_list[0], destination_question_state = question_state)
          question_state_list.insert(0, question_state)
          remaining_question_list.append(question)
        elif edition == 'middle':
          n = len(question_state_list)/4
          question, question_state = self._createQuestionAndAdd(questionnaire = questionnaire, portal_type = 'Boolean Question', question_state_list = [question_state_list[n-1]], title_suffix = str(i))
          question_state_list[n].objectValues()[0].setDestinationValue(question_state)
          question_state_list.insert(n, question_state)
          remaining_question_list.insert(n+1,question)
        else:
          even_question_state_list = question_state_list[::2]
          question_title_list = map(lambda x: x.getTitle(), question_list)
          question_list = []
          remaining_question_list = []
          previous_state = None
          answer_number = 0
          for state in even_question_state_list:
            if previous_state is not None:
              state.objectValues()[0].setDestinationValue(previous_state)
              first = False
            previous_state = state
            if state.getResourceTitle() in question_title_list:
              question_list.insert(0,state.getResourceValue())
              answer_number += 1 
            else:
              remaining_question_list.insert(0,state.getResourceValue())
              
      questionnaire.validate()
      self.userLogin(name = 'author')

    # let's fill out again
    if fill_out_again:
      batch = answer_set.AnswerSet_viewNextQuestionDialog(batch_mode = True)
      question = batch['question']
      url = batch['url']
      old_answer_set = answer_set
      answer_set = batch['answer_set']
      self._fillOut(remaining_question_list, answer_set, no_answer_given, url, answer_number)
      answer_list = answer_set.objectValues(portal_type = 'Answer')
      answer_question_title_list = map(lambda x: x.getResourceTitle(), answer_list)
      old_answer_list = old_answer_set.objectValues(portal_type = 'Answer')
      old_answer_question_title_list = map(lambda x: x.getResourceTitle(), old_answer_list)

      # Let's check that all the old answers are here and identical to their previous versions
      for question in question_list:
        try: 
          i = answer_question_title_list.index(question.getTitle())
          clone_answer = answer_list[i]
        except ValueError:
          self.fail(str(question.getTitle()) + ' not found in new answer set')
        try: 
          i = old_answer_question_title_list.index(question.getTitle())
          answer = old_answer_list[i]
        except ValueError:
          self.fail(str(question.getTitle()) + ' not found in old answer set')
        for prop in ['value_property_id', 'no_answer_reason','boolean_value','float_value','integer_value','string_value','list_value_list','grade','max_grade','text_value','comment']:
            self.assertEquals(answer.getProperty(prop), clone_answer.getProperty(prop))
    return answer_set
    
  def test_36_FillOutInQuestionnaire(self):
    self._fillOutTest()

  def test_37_FillOutInAnswerSet(self):
    self._fillOutTest(questionnaire_context = False)

  def test_38_lazyFillOutInQuestionnaire(self):
    self._fillOutTest(no_answer_given = True)

  def test_39_lazyFillOutInAnswerSet(self):
    self._fillOutTest(questionnaire_context = False, no_answer_given = True)

  def _addCorrectionLineAndCheckGrade(self, answer = None, answer_set = None, portal_type = 'Correction', correction = None, answer_grade = 0, grade = 0):
    grade_reduction = random.randint(1,100)
    if answer is None: 
      parent = answer_set
      answer_grade = 0
    else:
      parent = answer

    if correction is None:
      correction = self._newCorrection(portal_type = portal_type, grade_reduction = grade_reduction)
      correction_line = self._newCorrectionLine(parent = parent, correction = correction)
    else:
      correction_line = self._newCorrectionLine(parent = parent, correction = correction, grade_reduction = grade_reduction, default_grade_reduction = False)
    self.tic()
    grade -= grade_reduction
    self.assertEquals(answer_set.getGrade(), grade)
    if answer is not None: 
      answer_grade -= grade_reduction
      self.assertEquals(answer.getGrade(), answer_grade)
    return correction_line, answer_grade, grade

  def _deleteCorrectionLineAndCheckGrade(self, correction_line, answer = None, answer_set = None, answer_grade = 0, grade = 0):
    if answer is None:
      parent = answer_set
      answer_grade = 0
    else:
      parent = answer
    grade_reduction = correction_line.getGradeReduction()
    parent.deleteContent(correction_line.getId())
    grade += grade_reduction
    self.assertEquals(answer_set.getGrade(), grade)
    if answer is not None:
      answer_grade += grade_reduction
      self.assertEquals(answer.getGrade(), answer_grade)
    return answer_grade, grade

  def _testEachTypeOfCorrection(self,answer = None, answer_set = None, correction = None, answer_grade = 0, grade = 0):
    correction_line_list = []
    correction_line, answer_grade, grade = self._addCorrectionLineAndCheckGrade(answer = answer, answer_set = answer_set, correction = correction, answer_grade = answer_grade, grade = grade)
    correction_line_list.append(correction_line)
    correction_line, answer_grade, grade = self._addCorrectionLineAndCheckGrade(answer = answer, answer_set = answer_set, answer_grade = answer_grade, grade = grade)
    correction_line_list.append(correction_line)
    correction_line, answer_grade, grade =  self._addCorrectionLineAndCheckGrade(answer = answer, answer_set = answer_set, portal_type = 'Category Correction', answer_grade = answer_grade, grade = grade)
    correction_line_list.append(correction_line)
    return self._deleteCorrectionLineAndCheckGrade(correction_line = correction_line_list[1], answer = answer, answer_set = answer_set, answer_grade = answer_grade, grade = grade)
    
  def test_40_Grade(self):
    """
    Use case:
        - fill out test
        - check the grades are maximum
        - check the answer set grade is maximum
        - add correction lines to the answer set and check that the grade is still correct
        - delete correction lines from the answer set and check that grade is still correct
        - add correction lines to the answers and check that the grade is still correct
        - delete correction lines from the answers and check that grade is still correct
    """

    # filling out an answet set
    answer_set = self._fillOutTest()
    self.tic()
    # check that grades are maximum (no corrections have been provided yet)
    answers = answer_set.objectValues()
    answer_set_grade = answer_set.getGrade()
    grade = 0
    for answer in answers:
      answer_grade = answer.getGrade()
      self.assertEquals(answer_grade, answer.getResourceValue().getMaxGrade())
      grade += answer_grade

    # check the answer set grade is maximum
    self.assertEquals(answer_set_grade, grade)
    self.assertEquals(answer_set.AnswerSet_calculateMaxGrade(), grade)
    max_grade = grade

    # add 3 correction lines to the answer set and delete one of them: 1 is a correction line associated with correction with a non-default grade reduction, the others are related to a newly created Correction and Category Correction respectively with default grade reduction
    self.createUserAndLogin(role_list = ['Assignor'], name='assignor')
    
    correction = self._newCorrection(grade_reduction = random.randint(1,100))
    for answer in answers:
      answer_grade, grade = self._testEachTypeOfCorrection(answer_set = answer_set, correction = correction, grade = grade)
    # let's check that max grade is still correct
    self.assertEquals(answer_set.AnswerSet_calculateMaxGrade(), max_grade)

    # add 3 correction lines to each answer and delete one of them: 1 is a correction line associated with correction with a non-default grade reduction, the others are related to a newly created Correction and Category Correction respectively with default grade reduction

    for answer in answers:
      answer_grade, grade = self._testEachTypeOfCorrection(answer = answer, answer_set = answer_set, correction = correction, answer_grade = answer.getGrade(), grade = grade)

    self.createUserAndLogin(name = 'auditor')
    # let's check that max grade is still correct
    self.assertEquals(answer_set.AnswerSet_calculateMaxGrade(), max_grade)

  def _count(self, obj_list = [], correct_list = [], incorrect_list = [], property_name = 'relative_url'):
    counter = 0
    error_counter = 0
  
    for obj in obj_list:
      url = obj.getProperty(property_name)
      if url in correct_list:
        counter += 1
      elif url in incorrect_list:
        error_counter += 1
    return dict(correct = counter, error = error_counter)

  def _checkCorrectionLine(self, correction_line = None, title = '', comment = '', correction = None):
    self.assertEquals(correction_line.getTitle(), title)
    self.assertEquals(correction_line.getComment(), comment)
    self.assertEquals(correction_line.getSourceValue().getRelativeUrl(), correction.getRelativeUrl())

  def test_41_FastInput(self):
    """
    Use case:
        - create two questions
        - create a general correction, a correction and a category correction linked to the first question, a correction and a category correction linked to the second question
        - create related correction lines
        - create an answer set and an answer
        - use fast input
        - check if the generated listbox content is correct
    """

    question_remove_list = []
    answer_set_remove_list = []
    correction_remove_list = []

    assignor = self.createUserAndLogin(role_list = ['Assignor'], name = 'assignor')
    question = self._newQuestion()
    question_remove_list.append(question.getId())

    author = self.createUserAndLogin(role_list = ['Author'], name = 'author')
    answer_set = self._newAnswerSet(person = author)
    answer_set_remove_list.append(answer_set.getId())

    answer = self._newAnswer(answer_set = answer_set, question = question)
    
    self.userLogin(name='assignor')
    other_question = self._newQuestion(portal_type = 'String Question')
    question_remove_list.append(other_question.getId())
    
    correction = self._newCorrection(question_list = [question], is_general_value = False)
    correction_remove_list.append(correction.getId())

    category_correction = self._newCorrection(portal_type = 'Category Correction', question_list = [question], is_general_value = False)
    correction_remove_list.append(category_correction.getId())

    general_correction = self._newCorrection(title = 'General Correction')
    correction_remove_list.append(general_correction.getId())

    other_correction = self._newCorrection(title = 'Some Other Correction', question_list = [other_question], is_general_value = False)
    correction_remove_list.append(other_correction.getId())

    other_category_correction = self._newCorrection(title = 'Some Other Category Correction', portal_type = 'Category Correction', question_list = [other_question], is_general_value = False)
    correction_remove_list.append(other_category_correction.getId())
    self.tic()
    
    self.clear_module_list = [self.question_module, question_remove_list, self.answer_set_module, answer_set_remove_list, self.correction_module, correction_remove_list]

    # Let's use fast input
    batch = answer.Answer_initializeFastInput(batch_mode = True)

    # check if fast input was correctly initialized

    # general_correction, category_correction ,correction should appear, the 2 others shouldn't
    counter = self._count(obj_list = batch,
      correct_list = [general_correction.getRelativeUrl(),category_correction.getRelativeUrl(),correction.getRelativeUrl()],
      incorrect_list = [other_category_correction.getRelativeUrl(),other_correction.getRelativeUrl()]
      )

    self.assertEquals(counter['correct'],3)
    self.assertEquals(counter['error'],0)

    # let's create two correction lines with this fast input: one with general_correction_line, one with no correction line template
    # let's try to create one with the box 'add' unchecked
    listbox = [dict(comment = 'Test that should appear', listbox_key = general_correction.getRelativeUrl(), selected = 1),
               dict(comment = 'Test that should not appear', listbox_key = correction.getRelativeUrl(), selected = 0)]

    editable_listbox = [
      dict(comment = 'Brand new comment', listbox_key = '001', source_description = 'Brand new description', source_title = 'Brand new correction'),
      dict(comment = 'Should not appear', listbox_key = '002', source_description = 'Should not appear', source_title = '')
    ]

    batch = answer.Answer_generateCorrectionLines(listbox=listbox, editable_listbox=editable_listbox, batch_mode = True)
    # there should be 5 items in the batch: 
    self.assertEquals(len(batch), 3)
    
    self._checkCorrectionLine(correction_line = batch[0], title = general_correction.getTitle(), comment = 'Test that should appear', correction = general_correction)

    self.assertEquals(batch[1].getTitle(), 'Brand new correction')
    self.assertEquals(batch[1].getDescription(), 'Brand new description')

    self._checkCorrectionLine(correction_line = batch[2], title = 'Brand new correction', comment = 'Brand new comment', correction = batch[1])

  def invalid_category_spreadsheet_handler(message):
    # action taken when an invalid spreadsheet is provided.
    # we *raise* a Redirect, because we don't want the transaction to succeed
    # note, we could make a dialog parameter to allow import invalid spreadsheet:
    raise 'Redirect', '%s/view?portal_status_message=%s' % (
                         context.absolute_url(),
                         message)

  def _editAnswer(self, answer = None, no_answer_given = False):
    portal_type = answer.getResourceValue().getPortalType()
    value_property_id = answer.Answer_getValuePropertyId()
    no_answer_reason = 'do_not_know'
    comment = 'Some Comment'
    filename = 'sample_attachment.ods'
    file_object = makeFileUpload(filename)
    if no_answer_given:
      answer.Answer_edit(form_id='Answer_view', answer_reason = no_answer_reason, comment = comment, batch_mode = True)
    else :
      if portal_type == 'Selection Question':
        list_value_list = []
        string_value = 'Some Other Answer'
        if value_property_id == 'float_value':
          selection_value = 10.5
        elif value_property_id == 'integer_value':
          selection_value = 10
        elif value_property_id == 'string_value':
          selection_value = 'some_string_answer'
      elif portal_type == 'Multi Selection Question':
          selection_value = ''
          string_value = 'Some Other Answer'
          question_value_property_id = answer.getResourceValue().getValuePropertyId()
          if question_value_property_id == 'float_value':
            list_value_list = [10.5,20.5]
          elif question_value_property_id == 'integer_value':
            list_value_list = [10,20]
          elif question_value_property_id == 'string_value':
            list_value_list = ['some_string_answer','some_other_string_answer']
      else:
        string_value = 'some_string_answer'
        list_value_list = []
        selection_value = ''
      answer.Answer_edit(form_id='Answer_view', no_answer_reason = no_answer_reason, comment = comment, boolean_value = 1, string_value = string_value, integer_value = 34, float_value = 3.14159265, text_value = 'some_text_answer', file = file_object, list_value_list = list_value_list, selection_value = selection_value, simulation_mode = True, batch_mode = True)

  def _testEditAnswer(self, portal_type = 'Boolean Question', value_property_id = 'float_value', no_answer_given = False):
    # Editing an answer (uses Answer_edit instead of Base_edit, so needs testing)
    self.createUserAndLogin(role_list = ['Author'], name = 'author')
    question = self._newQuestion(portal_type = portal_type, value_property_id = value_property_id)
    answer_set = self._newAnswerSet()
    answer = self._newAnswer(answer_set = answer_set, question = question, empty = True)
    if portal_type == 'Selection Question' or portal_type == 'Multi Selection Question':
      self._addPossibleAnswer(question = question)
      self._addPossibleAnswer(question = question, string_value = 'some_other_string_answer', integer_value = 20, float_value = 20.5)
        
    self._editAnswer(answer = answer, no_answer_given = no_answer_given)
    self._checkAnswer(answer = answer, question = question, no_answer_given = no_answer_given)

  def test_42_editBooleanAnswer(self):
    self._testEditAnswer(portal_type = 'Boolean Question')

  def test_43_editDocumentAnswer(self):
    self._testEditAnswer(portal_type = 'Document Question')

  def test_44_editFloatAnswer(self):
    self._testEditAnswer(portal_type = 'Float Question')

  def test_45_editIntegerAnswer(self):
    self._testEditAnswer(portal_type = 'Integer Question')

  def test_46_editMultiSelectionFloatAnswer(self):
    self._testEditAnswer(portal_type = 'Multi Selection Question')

  def test_47_editMultiSelectionIntegerAnswer(self):
    self._testEditAnswer(portal_type = 'Multi Selection Question', value_property_id = 'integer_value')

  def test_48_editMultiSelectionStringAnswer(self):
    self._testEditAnswer(portal_type = 'Multi Selection Question', value_property_id = 'string_value')

  def test_49_editSelectionFloatAnswer(self):
    self._testEditAnswer(portal_type = 'Selection Question')

  def test_50_editSelectionIntegerAnswer(self):
    self._testEditAnswer(portal_type = 'Selection Question', value_property_id = 'integer_value')

  def test_51_editSelectionStringAnswer(self):
    self._testEditAnswer(portal_type = 'Selection Question', value_property_id = 'string_value')

  def test_52_editStringAnswer(self):
    self._testEditAnswer(portal_type = 'String Question')

  def test_53_editTextAnswer(self):
    self._testEditAnswer(portal_type = 'Text Question')

  def test_54_lazyEditBooleanAnswer(self):
    self._testEditAnswer(portal_type = 'Boolean Question', no_answer_given = True)

  def test_55_lazyEditDocumentAnswer(self):
    self._testEditAnswer(portal_type = 'Document Question', no_answer_given = True)

  def test_56_lazyEditFloatAnswer(self):
    self._testEditAnswer(portal_type = 'Float Question', no_answer_given = True)

  def test_57_lazyEditIntegerAnswer(self):
    self._testEditAnswer(portal_type = 'Integer Question', no_answer_given = True)

  def test_58_lazyEditMultiSelectionFloatAnswer(self):
    self._testEditAnswer(portal_type = 'Multi Selection Question', no_answer_given = True)

  def test_59_lazyEditMultiSelectionIntegerAnswer(self):
    self._testEditAnswer(portal_type = 'Multi Selection Question', no_answer_given = True, value_property_id = 'integer_value')

  def test_60_lazyEditMultiSelectionStringAnswer(self):
    self._testEditAnswer(portal_type = 'Multi Selection Question', no_answer_given = True, value_property_id = 'string_value')

  def test_61_lazyEditSelectionFloatAnswer(self):
    self._testEditAnswer(portal_type = 'Selection Question', no_answer_given = True)

  def test_62_lazyEditSelectionIntegerAnswer(self):
    self._testEditAnswer(portal_type = 'Selection Question', no_answer_given = True, value_property_id = 'integer_value')

  def test_63_lazyEditSelectionStringAnswer(self):
    self._testEditAnswer(portal_type = 'Selection Question', no_answer_given = True, value_property_id = 'string_value')

  def test_64_lazyEditStringAnswer(self):
    self._testEditAnswer(portal_type = 'String Question', no_answer_given = True)

  def test_65_lazyEditTextAnswer(self):
    self._testEditAnswer(portal_type = 'Text Question', no_answer_given = True)

  def _initializeAnswerSet(self, person = None, questionnaire = None):
    answer_set = questionnaire.Questionnaire_createAnswerSet(batch_mode = True)['answer_set']
    answer_set.setSourceValue(person)
    return answer_set

  def test_66_ExampleAnswers(self):
    """
     use case:
       - creates an organisation and a person
       - creates 2 questions (no need to test for every portal type, since it's only using the question's relative url and title)
       - creates a questionnaire
       - creates two answer sets (one is become an example answer set, the other one is not)
       - creates two anwsers
       - call the function to list example answers on one of the answers
    """
    self.createUserAndLogin(role_list = ['Assignor'], name = 'assignor')
    organisation = self._newOrganisation()
    person = self._newPerson(organisation = organisation)

    example_organisation = self._newOrganisation()
    example_person = self._newPerson(organisation = example_organisation, first_name = 'Example Person First Name')

    question = self._newQuestion()
    other_question = self._newQuestion(portal_type = 'String Question')

    questionnaire = self._newQuestionnaire()
    question_state = self._newQuestionState(questionnaire = questionnaire, question = question)
    self._newQuestionState(questionnaire = questionnaire, question = other_question)
    
    questionnaire.setSourceValue(question_state)
    questionnaire.validate()

    self.createUserAndLogin(role_list = ['Author'], name = 'author')
    answer_set = self._initializeAnswerSet(person = person, questionnaire = questionnaire)
    example_answer_set = self._initializeAnswerSet(person = example_person, questionnaire = questionnaire)
    example_answer_set.setTitle('Example Organisation')

    self.userLogin(name = 'assignor')
    questionnaire.setResourceValueList([example_answer_set])

    self.userLogin(name = 'author')
    self._newAnswer(answer_set = answer_set, question = question)
    self._newAnswer(answer_set = answer_set, question = other_question)
    example_answer = self._newAnswer(answer_set = example_answer_set, question = question)

    # let's see what example answers we have
    example_answer_list = answer_set.AnswerSet_getRelatedExampleAnswers()
    self.assertEquals(len(example_answer_list),1)
    example = example_answer_list[0]
    self.assertEquals(example.getProperty('title'),example_answer.getValueText())
    self.assertEquals(example.getProperty('organisation'),'Example Organisation')
    # remove portal path and trailing '/' from example_url
    example_url = '/'.join(example.getProperty('url').split('/')[2:])[:-1]
    self.assertEquals(example_url, example_answer.getRelativeUrl())

  def _newCategory(self, parent, portal_type = 'Category', id = 'standard_category', title = ''):
    if title == '':
      title = 'Some ' + portal_type + ' Title'
    if portal_type == 'Category':
      category = parent.newContent(portal_type= portal_type,
                                id          = id,
                                title       = title,
                                short_title = 'Some Short Title',
                                description = 'Some Description',
                                reference   = 'Some Reference',
                                codification= 'code',
                                int_index   =  10,
                                batch_mode  = True
                              )
    else:
      category = parent.newContent(portal_type = portal_type,
                                id          =  id,
                                title       = title,
                                description = 'Some Description',
                                acquisition_object_id_list = ['some_acquisition_object_id'],
                                acquisition_base_category_list = ['some_acquisition_base_category'],
                                acquisition_portal_type_list  = 'python:["some_acquisition_portal_type"]',
                                fallback_base_category_list  = ['some_fallback_base_category'],
                                acquisition_copy_value = True,
                                acquisition_mask_value = True,
                                acquisition_append_value = True,
                                category_type_list = ['line'],
                                batch_mode  = True
                              )
    return category

  def _CategoryCreation(self, child = False, grand_child = False):
    self.createUserAndLogin(role_list = ['Assignor'], name = 'assignor')
    parent = self.standard_category_module
    new_child_count = len(self.standard_category_module.objectValues()) + 1
    category = self._newCategory(parent, portal_type = 'Base Category')
    self.assertEquals(category.getPortalType(), 'Base Category')
    self.assertTrue(category is not None)
    self.assertEquals(category.getId(), 'standard_category')
    self.assertEquals(category.getTitle(), 'Some Base Category Title')
    self.assertEquals(category.getDescription(), 'Some Description')
    self.assertEquals(len(category.getAcquisitionObjectIdList()), 1)
    self.assertEquals(category.getAcquisitionObjectIdList()[0], 'some_acquisition_object_id')
    self.assertEquals(len(category.getAcquisitionBaseCategoryList()), 1)
    self.assertEquals(category.getAcquisitionBaseCategoryList()[0], 'some_acquisition_base_category')
    self.assertEquals(len(category.getAcquisitionPortalTypeList()), 1)
    self.assertEquals(category.getAcquisitionPortalTypeList()[0], 'some_acquisition_portal_type')
    self.assertEquals(len(category.getFallbackBaseCategoryList()), 1)
    self.assertEquals(category.getFallbackBaseCategoryList()[0], 'some_fallback_base_category')
    self.assertTrue(category.getAcquisitionCopyValue())
    self.assertTrue(category.getAcquisitionMaskValue())
    self.assertTrue(category.getAcquisitionAppendValue())
    self.assertEquals(len(category.getCategoryTypeList()), 1)
    self.assertEquals(category.getCategoryTypeList()[0], 'line')

    self.assertEquals(len(parent.objectValues()), new_child_count)
    self.assertEquals(category.getParent().getRelativeUrl(),parent.getRelativeUrl())
    if child:
      child = self._newCategory(category, id = 'child_category', portal_type = 'Category')
      self.assertEquals(len(category.objectValues()),1)
      self.assertEquals(child.getParent().getRelativeUrl(),category.getRelativeUrl())
      self.assertEquals(child.getId(), 'child_category')
      self.assertEquals(child.getTitle(), 'Some Category Title')
      self.assertEquals(child.getDescription(), 'Some Description')
      self.assertEquals(child.getReference(), 'Some Reference')
      self.assertEquals(child.getCodification(), 'code')
      self.assertEquals(child.getIntIndex(), 10)
      self.assertEquals(len(child.objectValues()),0)
      if grand_child:
        grand_child = self._newCategory(child, id = 'grand_child_category', portal_type = 'Category')
        self.assertEquals(len(child.objectValues()),1)
        self.assertEquals(grand_child.getParent().getRelativeUrl(),child.getRelativeUrl())
        
    self.clear_module_list = [self.standard_category_module, [category.getId()]]

  def test_67_StandardBaseCategoryCreation(self):
    self._CategoryCreation()

  def test_68_StandardCategoryCreation(self):
    self._CategoryCreation(child = True)

  def test_69_GrandChildStandardCategoryCreation(self):
    self._CategoryCreation(child = True, grand_child = True)

  def _setCategories(self):
    question = self._newQuestion(portal_type = 'Document Question')
    questionnaire = self._newQuestionnaire()
    answer_set = self._newAnswerSet(questionnaire = questionnaire)
    answer = self._newAnswer(answer_set = answer_set, question = question)
    standard_category_in_module = self._newCategory(self.standard_category_module, portal_type = 'Base Category', title = 'Standard Category')
    self._newCategory(standard_category_in_module, id = 'standard_child', title = 'Standard Child')
    answer._setCategoryDict({'standard_category': 
                             {'standard_category/not_standard_child': {'parent': 'standard_category',
                                                                            'int_index': '10',
                                                                            'reference': 'Some Reference',
                                                                            'codification': 'code',
                                                                            'title': 'Not Standard Child',
                                                                            'line_index': 4,
                                                                            'short_title': 'Some Short Title',
                                                                            'path': 'standard_category/not_standard_child',
                                                                            'id': 'not_standard_child',
                                                                            'description': 'Some Description'},
                              'standard_category/standard_child': {'parent': 'standard_category',
                                                                            'int_index': '10',
                                                                            'reference': 'Some Reference',
                                                                            'codification': 'code',
                                                                            'title': 'Standard Child',
                                                                            'line_index': 3,
                                                                            'short_title': 'Some Short Title',
                                                                            'path': 'standard_category/standard_child',
                                                                            'id': 'standard_child',
                                                                            'description': 'Some Description'}},
                            'not_standard_category':
                             {'not_standard_category/not_standard_category_child': {'parent': 'not_standard_category',
                                                                            'int_index': '10',
                                                                            'reference': 'Some Reference',
                                                                            'codification': 'code',
                                                                            'title': 'Another not Standard Child',
                                                                            'line_index': 3,
                                                                            'short_title': 'Some Short Title',
                                                                            'path': 'not_standard_category/not_standard_category_child',
                                                                            'id': 'not_standard_category_child',
                                                                            'description': 'Some Description'}}})

    self.clear_module_list = [self.standard_category_module, [standard_category_in_module.getId()]]
    return answer, answer_set

  def _testExportCategories(self, export_type = ''):
    self.createUserAndLogin(role_list = ['Assignor'], name = 'assignor')
    answer, answer_set = self._setCategories()

    if export_type == 'standard_count':
      table = self.standard_category_module.ERP5Survey_constructCategoryTableToExport(export_type = export_type, category_list = ['standard_category'], batch_mode = True, simulation_mode = True)
      table_size = 1
      expected_id_list = [['standard_child']]
      expected_title_list = [['Standard Child']]
      expected_category_property_list = ['Id', 'Int Index', 'Reference', 'Codification', 'Title', 'Short Title', 'Description','Usage']
      expected_table_list = ['Standard Category']
      expected_highlighted = [[False]]
    else:
      table_size = 2
      expected_id_list = [['not_standard_child','standard_child'],['not_standard_category_child']]
      expected_title_list = [['Not Standard Child', 'Standard Child'],['Another not Standard Child']]
      expected_category_property_list = ['Id', 'Int Index', 'Reference', 'Codification', 'Title', 'Short Title', 'Description']
      expected_table_list = ['Standard Category','Not Standard Category']
      if export_type == 'standard':
        expected_highlighted = [[False,True],[False]]
      elif export_type == '':
        expected_highlighted = [[False,False],[False]]
      elif export_type == 'modified' :
        reference = answer_set.getReference()
        answer_set.submit()
        answer_set.request()
        archived_answer_set = self._findArchivedAnswerSet(reference)

        self.assertTrue(archived_answer_set is not None)
        answer._setCategoryDict({'standard_category': 
                             {'standard_category/not_standard_child': {'parent': 'standard_category',
                                                                            'int_index': '10',
                                                                            'reference': 'Some Reference',
                                                                            'codification': 'code',
                                                                            'title': 'Not Standard Child',
                                                                            'line_index': 4,
                                                                            'short_title': 'Some Short Title',
                                                                            'path': 'standard_category/not_standard_child',
                                                                            'id': 'not_standard_child',
                                                                            'description': 'Some Description'},
                              'standard_category/standard_child': {'parent': 'standard_category',
                                                                            'int_index': '10',
                                                                            'reference': 'Some Reference',
                                                                            'codification': 'code',
                                                                            'title': 'Standard Child',
                                                                            'line_index': 3,
                                                                            'short_title': 'Some Short Title',
                                                                            'path': 'standard_category/standard_child',
                                                                            'id': 'standard_child',
                                                                            'description': 'Some Description'},
                              'standard_category/modified_category': {'parent': 'standard_category',
                                                                            'int_index': '10',
                                                                            'reference': 'Some Reference',
                                                                            'codification': 'code',
                                                                            'title': 'Modified Child',
                                                                            'line_index': 5,
                                                                            'short_title': 'Some Short Title',
                                                                            'path': 'standard_category/modified_category',
                                                                            'id': 'modified_category',
                                                                            'description': 'Some Description'}},
                            'not_standard_category':
                             {'not_standard_category/not_standard_category_child': {'parent': 'not_standard_category',
                                                                            'int_index': '10',
                                                                            'reference': 'Some Reference',
                                                                            'codification': 'code',
                                                                            'title': 'Another not Standard Child',
                                                                            'line_index': 3,
                                                                            'short_title': 'Some Short Title',
                                                                            'path': 'not_standard_category/not_standard_category_child',
                                                                            'id': 'not_standard_category_child',
                                                                            'description': 'Some Description'}}})
        #self._newCategory(standard_category, id = 'modified_category', title = 'Modified Category')
        expected_id_list[0].insert(0,'modified_category')
        expected_title_list[0].insert(0,'Modified Child')
        expected_highlighted = [[True,False,False],[False]]
      table = answer.ERP5Survey_constructCategoryTableToExport(export_type = export_type, category_list = ['standard_category', 'not_standard_category'], batch_mode = True, simulation_mode = True)
        
    # Dictionary content is checked
    self.assertEquals(len(table),table_size)
    for i in range(0,table_size):
      base_category_table = table[i]
      header_row = base_category_table['header_row']
      
      self.assertTrue('header_row' in base_category_table)
      self.assertTrue('name' in base_category_table)
      self.assertTrue('row_list' in base_category_table)
      self.assertTrue('path_cell_list' in header_row)
      self.assertTrue('category_property_list' in header_row)
      
      # Checking header row
      self.assertEquals(len(header_row['path_cell_list']),8)
      self.assertEquals(len(header_row['category_property_list']),len(expected_category_property_list))
      self.assertEquals(header_row['path_cell_list'],['Path', '', '', '', '', '', '', ''])
      self.assertEquals(header_row['category_property_list'],expected_category_property_list)

      # Checking name
      self.assertEquals(base_category_table['name'],expected_table_list[i])

      # Checking rows
      for j in range(0,len(base_category_table['row_list'])):
        row = base_category_table['row_list'][j]
   
        self.assertTrue('path_cell_list' in row)
        self.assertTrue('highlighted' in row)
        self.assertTrue('category_first_property_list' in row)
        self.assertTrue('category_second_property_list' in row)
        self.assertTrue('category_reference_list' in row)
        #if row['highlighted'] != expected_highlighted[i][j]:
          #self.fail(str(row['highlighted']) + ' ' +  expected_title_list[i][j] + ' ' + row['category_first_property_list'][0]  + ' ' + repr(table))
        self.assertEquals(row['highlighted'], expected_highlighted[i][j])
        self.assertEquals(len(row['path_cell_list']), 8)
        self.assertEquals(row['path_cell_list'], ['*', '', '', '', '', '', '', ''])
        self.assertEquals(row['category_reference_list'], ['Some Reference', 'code'])

        # Checking properties
        category_first_property_list = row['category_first_property_list']
        self.assertEquals(category_first_property_list[0], expected_id_list[i][j])
        self.assertEquals(str(category_first_property_list[1]),'10')

        category_second_property_list = row['category_second_property_list']
        self.assertEquals(category_second_property_list[0], expected_title_list[i][j])
        self.assertEquals(category_second_property_list[1], 'Some Short Title')
        self.assertEquals(category_second_property_list[2], 'Some Description')

  def test_70_exportAnswerSetCategories(self):
    self._testExportCategories()

  @skip("We currently do not use this functionality, \
         once we use it this tes has to be rewritten")
  def test_71_exportAnswerSetCategoriesStandardHighlighted(self):
    self._testExportCategories(export_type = 'standard')

  @skip("We currently do not use this functionality, \
        once we use it this tes has to be rewritten")
  def test_72_exportAnswerSetCategoriesModificationsHighlighted(self):
    self._testExportCategories(export_type = 'modified')

  def test_73_exportCategoriesAndCountUsage(self):
    self._testExportCategories(export_type = 'standard_count')

  def _checkCounters(self, values, expected_values):
    for key in values.keys():
      print key
      self.assertTrue(key in expected_values.keys())
      self.assertEquals(values[key][0], expected_values[key][0])
      self.assertEquals(values[key][1], expected_values[key][1])

  @skip("We currently do not use this functionality, \
         once we use it this tes has to be rewritten")
  def test_74_countIds(self):
    self.createUserAndLogin(role_list = ['Assignor'], name = 'assignor')
    answer, answer_set = self._setCategories()
    result = answer.Answer_countBaseCategoryIds(simulation_mode = True)
    self.assertEquals(len(result.keys()),6)
  
    expected_result  = {'TOTAL': (3,1), 'standard_category' : (2,1), 'standard_category/standard_child' : (1,1), 'not_standard_category' : (1,0), 'standard_category/not_standard_child' : (1,0), 'not_standard_category/not_standard_category_child' : (1,0)}
    
    self._checkCounters(result,expected_result)

  def _checkProperties(self, object_list, expected_property_list):
    for property_list in expected_property_list:
      found = False
      for obj in object_list:
        if obj.getProperty('title') == property_list['category_title']:
          found = True
          for property_name in property_list.keys():
            self.assertEquals(obj.getProperty(property_name), property_list[property_name])
      self.assertTrue(found)

  def _checkCategoryList(self, full_tree = False):
    self.createUserAndLogin(role_list = ['Assignor'], name = 'assignor')
    answer, answer_set = self._setCategories()
    result = answer.Answer_listCategories(sort_on = [('category_relative_url', 'ascending')], full_tree = full_tree, simulation_mode = True)
    if full_tree: 
      expected_result  = [dict(category_relative_url = 'not_standard_category', category_title = 'Not Standard Category', id_count = 1, standard_id_count = 0),
                          dict(category_relative_url = 'not_standard_category/not_standard_category_child', category_title = 'Another not Standard Child', id_count = 1, standard_id_count = 0),
                          dict(category_relative_url = 'standard_category', category_title = 'Standard Category', id_count = 2, standard_id_count = 1),
                          dict(category_relative_url = 'standard_category/not_standard_child', category_title = 'Not Standard Child', id_count = 1, standard_id_count = 0),
                          dict(category_relative_url = 'standard_category/standard_child', category_title = 'Standard Child', id_count = 1, standard_id_count = 1)]
    else:
      expected_result  = [dict(category_relative_url = 'not_standard_category', category_title = 'Not Standard Category', id_count = 1, standard_id_count = 0),
                          dict(category_relative_url = 'standard_category', category_title = 'Standard Category', id_count = 2, standard_id_count = 1)]

    self.assertEquals(len(result),len(expected_result))
    self._checkProperties(result, expected_result)
    
  #def test_75_checkBaseCategoryList(self):
  #  self._checkCategoryList() 

  #def test_76_checkFullCategoryList(self):
  #  self._checkCategoryList(full_tree = True)

  def _createQuestionnaireAndAssertDraftState(self):
    questionnaire = self._newQuestionnaire()
    self.assertTrue(questionnaire is not None)
    self.assertEquals(questionnaire.getValidationState(), 'draft')
    return questionnaire

  def _validateQuestionnaireAndAssert(self, questionnaire):
    start_time = DateTime()
    questionnaire.validate()
    stop_time = DateTime()
    self.assertEquals(questionnaire.getValidationState(), 'validated')
    self.assertTrue(questionnaire.getModificationDate() is not None and questionnaire.getModificationDate() >= start_time and questionnaire.getModificationDate() <= stop_time)

  def test_77_QuestionnaireWorkflow(self):
    """
    Use case:
        - create 2 Questionnaire
        - The first one is deleted directly after being validated
        - The second one follows the following transitions (in this order to test every transition possible):
          draft -> validated -> draft -> deleted
    """
    self.createUserAndLogin(role_list = ['Assignor'], name='assignor')
    questionnaire = self._createQuestionnaireAndAssertDraftState()

    self._validateQuestionnaireAndAssert(questionnaire)

    questionnaire.delete()
    self.assertEquals(questionnaire.getValidationState(), 'deleted')

    questionnaire = self._createQuestionnaireAndAssertDraftState()

    self._validateQuestionnaireAndAssert(questionnaire)

    questionnaire.update()
    self.assertEquals(questionnaire.getValidationState(), 'draft')

    questionnaire.delete()
    self.assertEquals(questionnaire.getValidationState(), 'deleted')

  def test_78_FillOutAgainWithNoModifications(self):
    self._fillOutTest(questionnaire_context = False, fill_out_again = True)

  def test_79_FillOutAgainAfterUpdatingWithNoModifications(self):
    self._fillOutTest(questionnaire_context = False, fill_out_again = True, edition = 'nothing')

  def test_80_FillOutAgainAfterAddingFirstQuestion(self):
    self._fillOutTest(questionnaire_context = False, fill_out_again = True, edition = 'first')

  def test_81_FillOutAgainAfterAddingLastQuestion(self):
    self._fillOutTest(questionnaire_context = False, fill_out_again = True, edition = 'last')

  def test_82_FillOutAgainAfterAddingMiddleQuestion(self):
    self._fillOutTest(questionnaire_context = False, fill_out_again = True, edition = 'middle')

  @skip("This test has to be rewritten")
  def test_83_FillOutAgainAfterRemovingQuestions(self):
    self._fillOutTest(questionnaire_context = False, fill_out_again = True, edition = 'removing')
    
  def test_84_UploadBadSpreadsheetAfterRequest(self):
    good_file_object = makeFileUpload('sample_attachment.ods')
    bad_file_object = makeFileUpload('sample_bad_attachment.ods')
    self.createUserAndLogin(role_list = ['Assignor'], name = 'assignor')
    questionnaire = self._newQuestionnaire()
    question, question_state = self._createQuestionAndAdd(questionnaire = questionnaire, portal_type = 'Document Question')
    document = self._newDocument()
    answer_set = self._newAnswerSet(questionnaire = questionnaire)
    answer = self._newAnswer(answer_set = answer_set, question = question, document = document)
    answer.Answer_edit(form_id='Answer_view', file = good_file_object, batch_mode = True)
    self.assertTrue(answer.documentExists())
    answer_set.submit()
    answer_set.request()
    self.tic()
    try:
      answer.Answer_edit(form_id='Answer_view', file = bad_file_object)
    except ValueError:
      pass
    else:
      self.fail("We expect a value error when Uploading the bad spreadsheet")
    self.assertTrue(answer.documentExists())
