@Override
  protected SectionBreadcrumb findNextBreadcrumb(
      final QuestionnaireDefinition questionnaireDefinition,
      final Questionnaire questionnaire,
      Map<String, Object> answers,
      final SectionBreadcrumb lastBreadcrumb,
      final Integer lastBreadcrumbPosition) {

    SectionBreadcrumb breadcrumb =
        (SectionBreadcrumb)
            breadcrumbService.findByQuestionnaireIdAndPosition(
                questionnaire.getId(), lastBreadcrumbPosition + 1);

    SectionBreadcrumb nextBreadcrumb = null;

    // There is no real section when QuestionsRandomization is enabled
    if (breadcrumb == null
        && !questionnaireDefinition
            .getRandomizationStrategy()
            .equals(RandomizationStrategy.QUESTIONS_RANDOMIZATION)) {
      Assert.isInstanceOf(SectionBreadcrumb.class, lastBreadcrumb);

      Integer position =
          sectionService.positionInQuestionnaireDefinition(lastBreadcrumb.getSection().getId());
      Section next =
          sectionService.findOneByPositionInQuestionnaireDefinition(
              questionnaireDefinition.getId(), position + 1);
      // The respondent has reached the last question group
      if (next == null) {
        return null;
      }
      nextBreadcrumb =
          SectionBreadcrumb.with()
              .questionnaire(questionnaire)
              .section(next)
              .renderingMode(RenderingMode.SECTION_BY_SECTION)
              .build();
      Integer lastQuestionNumberDisplayed = extractLastQuestionNumberDisplayed(lastBreadcrumb);
      populateQuestionsBreadcrumbs(Arrays.asList(nextBreadcrumb), lastQuestionNumberDisplayed + 1);
    } else {
      nextBreadcrumb = breadcrumb;
    }
    return nextBreadcrumb;
  }
  @Override
  protected PageStructure createPageStructure(
      RandomizationStrategy randomizationStrategy,
      List<SectionBreadcrumb> breadcrumbs,
      Map<String, Object> answers) {
    PageStructure nextPage = super.createPageStructure(randomizationStrategy, breadcrumbs, answers);
    Breadcrumb active = breadcrumbs.get(0);

    SectionBreadcrumb sectionBreadcrumb = (SectionBreadcrumb) active;
    Builder builder = Section.with();
    if (!randomizationStrategy.equals(RandomizationStrategy.QUESTIONS_RANDOMIZATION)) {
      builder.id(sectionBreadcrumb.getSection().getId());
    }
    Section section = builder.build();
    for (QuestionBreadcrumb questionBreadcrumb : sectionBreadcrumb.getBreadcrumbs()) {
      section.addQuestion(
          Question.with()
              .id(questionBreadcrumb.getQuestion().getId())
              .number(questionBreadcrumb.getQuestionNumber())
              .build());
    }
    nextPage.addSection(section);
    return nextPage;
  }
  @Override
  protected List<SectionBreadcrumb> makeBreadcrumbs(
      QuestionnaireDefinition questionnaireDefinition, Questionnaire questionnaire) {
    List<SectionBreadcrumb> breadcrumbs = new ArrayList<>();
    SectionBreadcrumb breadcrumb = null;
    Integer questionnaireDefinitionId = questionnaireDefinition.getId();
    RandomizationStrategy randomizationStrategy =
        questionnaireDefinition.getRandomizationStrategy();
    if (RandomizationStrategy.SECTIONS_RANDOMIZATION.equals(randomizationStrategy)) {
      List<Section> sections =
          sectionService.findByExample(
              Section.with()
                  .questionnaireDefinition(
                      QuestionnaireDefinition.with().id(questionnaireDefinitionId).build())
                  .build(),
              new SearchParameters());
      Collections.shuffle(sections);
      for (Section section : sections) {
        breadcrumb =
            SectionBreadcrumb.with()
                .questionnaire(questionnaire)
                .section(section)
                .last(Boolean.FALSE)
                .renderingMode(RenderingMode.SECTION_BY_SECTION)
                .build();
        breadcrumbs.add(breadcrumb);
      }
      populateQuestionsBreadcrumbs(breadcrumbs, QUESTION_NUMBER_START_COUNTER);
    } else if (RandomizationStrategy.QUESTIONS_RANDOMIZATION.equals(randomizationStrategy)) {
      List<Question> questions =
          questionnaireDefinitionService.getQuestions(questionnaireDefinitionId);
      Collections.shuffle(questions);
      Integer questionPerPage = questionnaireDefinition.getQuestionsPerPage();
      int questionIdx = 0;
      Integer questionNumberCounter = QUESTION_NUMBER_START_COUNTER;
      for (Question question : questions) {
        if (questionIdx % questionPerPage == 0) {
          breadcrumb =
              SectionBreadcrumb.with()
                  .questionnaire(questionnaire)
                  .last(Boolean.FALSE)
                  .renderingMode(RenderingMode.SECTION_BY_SECTION)
                  .build();
          breadcrumbs.add(breadcrumb);
        }
        breadcrumb.addBreadcrumb(
            QuestionBreadcrumb.with()
                .question(question)
                .last(Boolean.FALSE)
                .questionNumber(questionNumberCounter++)
                .build());
        questionIdx++;
      }

    } else {
      Section section =
          sectionService.findOneByPositionInQuestionnaireDefinition(
              questionnaireDefinitionId, INITIAL_POSITION);
      breadcrumb =
          SectionBreadcrumb.with()
              .questionnaire(questionnaire)
              .section(section)
              .renderingMode(RenderingMode.SECTION_BY_SECTION)
              .build();
      breadcrumbs.add(breadcrumb);
      populateQuestionsBreadcrumbs(breadcrumbs, QUESTION_NUMBER_START_COUNTER);
    }
    breadcrumbs.get(0).setLast(Boolean.TRUE);
    return breadcrumbs;
  }
 private Integer extractLastQuestionNumberDisplayed(SectionBreadcrumb lastBreadcrumb) {
   int questionsCount = lastBreadcrumb.getBreadcrumbs().size();
   return lastBreadcrumb.getBreadcrumbs().get(questionsCount - 1).getQuestionNumber();
 }