public List<Exam> createExamList(Examination examination) {
    List<Topic> topicList = examination.getTopicList();
    List<Exam> examList = new ArrayList<Exam>(topicList.size());
    Map<Topic, Exam> topicToExamMap = new HashMap<Topic, Exam>(topicList.size());
    for (Topic topic : topicList) {
      Exam exam = new Exam();
      exam.setId(topic.getId());
      exam.setTopic(topic);
      examList.add(exam);
      topicToExamMap.put(topic, exam);
    }
    for (PeriodHardConstraint periodHardConstraint : examination.getPeriodHardConstraintList()) {
      if (periodHardConstraint.getPeriodHardConstraintType()
          == PeriodHardConstraintType.EXAM_COINCIDENCE) {
        Exam leftExam = topicToExamMap.get(periodHardConstraint.getLeftSideTopic());
        Exam rightExam = topicToExamMap.get(periodHardConstraint.getRightSideTopic());

        Set<Exam> newCoincidenceExamSet = new LinkedHashSet<Exam>(4);
        ExamCoincidence leftExamCoincidence = leftExam.getExamCoincidence();
        if (leftExamCoincidence != null) {
          newCoincidenceExamSet.addAll(leftExamCoincidence.getCoincidenceExamSet());
        } else {
          newCoincidenceExamSet.add(leftExam);
        }
        ExamCoincidence rightExamCoincidence = rightExam.getExamCoincidence();
        if (rightExamCoincidence != null) {
          newCoincidenceExamSet.addAll(rightExamCoincidence.getCoincidenceExamSet());
        } else {
          newCoincidenceExamSet.add(rightExam);
        }
        ExamCoincidence newExamCoincidence = new ExamCoincidence(newCoincidenceExamSet);
        for (Exam exam : newCoincidenceExamSet) {
          exam.setExamCoincidence(newExamCoincidence);
        }
      } else if (periodHardConstraint.getPeriodHardConstraintType()
          == PeriodHardConstraintType.AFTER) {
        Exam afterExam = topicToExamMap.get(periodHardConstraint.getLeftSideTopic());
        Exam beforeExam = topicToExamMap.get(periodHardConstraint.getRightSideTopic());
        ExamBefore examBefore = beforeExam.getExamBefore();
        if (examBefore == null) {
          examBefore = new ExamBefore(new LinkedHashSet<Exam>(2));
          beforeExam.setExamBefore(examBefore);
        }
        examBefore.getAfterExamSet().add(afterExam);
      }
    }
    return examList;
  }
  private void initializeExamList(
      LocalSearchSolverScope localSearchSolverScope, Examination examination) {
    List<Period> periodList = examination.getPeriodList();
    List<Room> roomList = examination.getRoomList();
    List<Exam> examList =
        new ArrayList<Exam>(
            examination
                .getTopicList()
                .size()); // TODO this can be returned from createExamAssigningScoreList
    WorkingMemory workingMemory = localSearchSolverScope.getWorkingMemory();

    List<ExamInitializationWeight> examInitialWeightList =
        createExamAssigningScoreList(examination);

    for (ExamInitializationWeight examInitialWeight : examInitialWeightList) {
      Score unscheduledScore = localSearchSolverScope.calculateScoreFromWorkingMemory();
      Exam leader = examInitialWeight.getExam();
      FactHandle leaderHandle = null;

      List<ExamToHandle> examToHandleList = new ArrayList<ExamToHandle>(5);
      if (leader.getExamCoincidence() == null) {
        examToHandleList.add(new ExamToHandle(leader));
      } else {
        for (Exam coincidenceExam : leader.getExamCoincidence().getCoincidenceExamSet()) {
          examToHandleList.add(new ExamToHandle(coincidenceExam));
        }
      }

      List<PeriodScoring> periodScoringList = new ArrayList<PeriodScoring>(periodList.size());
      for (Period period : periodList) {
        for (ExamToHandle examToHandle : examToHandleList) {
          if (examToHandle.getExamHandle() == null) {
            examToHandle.getExam().setPeriod(period);
            examToHandle.setExamHandle(workingMemory.insert(examToHandle.getExam()));
            if (examToHandle.getExam().isCoincidenceLeader()) {
              leaderHandle = examToHandle.getExamHandle();
            }
          } else {
            examToHandle.getExam().setPeriod(period);
            workingMemory.update(examToHandle.getExamHandle(), examToHandle.getExam());
          }
        }
        Score score = localSearchSolverScope.calculateScoreFromWorkingMemory();
        periodScoringList.add(new PeriodScoring(period, score));
      }
      Collections.sort(periodScoringList);

      scheduleLeader(
          periodScoringList,
          roomList,
          localSearchSolverScope,
          workingMemory,
          unscheduledScore,
          examToHandleList,
          leader,
          leaderHandle);
      examList.add(leader);

      // Schedule the non leaders
      for (ExamToHandle examToHandle : examToHandleList) {
        Exam exam = examToHandle.getExam();
        // Leader already has a room
        if (!exam.isCoincidenceLeader()) {
          scheduleNonLeader(
              roomList, localSearchSolverScope, workingMemory, exam, examToHandle.getExamHandle());
          examList.add(exam);
        }
      }
    }
    Collections.sort(examList, new PersistableIdComparator());
    examination.setExamList(examList);
  }
 @Override
 public boolean isSolutionInitialized(LocalSearchSolverScope localSearchSolverScope) {
   Examination examination = (Examination) localSearchSolverScope.getWorkingSolution();
   return examination.isInitialized();
 }