/**
   * For the first time a curation page is opened, create a MergeCas that contains only agreeing
   * annotations Using the CAS of the curator user.
   *
   * @param aProject the project
   * @param randomAnnotationDocument an annotation document.
   * @param jCases the JCases
   * @param aAnnotationLayers the layers.
   * @return the JCas.
   * @throws IOException if an I/O error occurs.
   */
  public JCas createCurationCas(
      Project aProject,
      AnnotationDocument randomAnnotationDocument,
      Map<String, JCas> jCases,
      List<AnnotationLayer> aAnnotationLayers)
      throws IOException {
    User userLoggedIn =
        userRepository.get(SecurityContextHolder.getContext().getAuthentication().getName());

    JCas mergeJCas = repository.readAnnotationCas(randomAnnotationDocument);
    jCases.put(CurationPanel.CURATION_USER, mergeJCas);

    List<Type> entryTypes = getEntryTypes(mergeJCas, aAnnotationLayers, annotationService);

    DiffResult diff =
        CasDiff2.doDiffSingle(
            annotationService,
            aProject,
            entryTypes,
            jCases,
            0,
            mergeJCas.getDocumentText().length());

    for (Entry<Position, ConfigurationSet> diffEntry :
        diff.getDifferingConfigurationSets().entrySet()) {
      // Remove FSes with differences from the merge CAS
      List<Configuration> cfgsForCurationUser =
          diffEntry.getValue().getConfigurations(CurationPanel.CURATION_USER);
      for (Configuration cfg : cfgsForCurationUser) {
        FeatureStructure fs = cfg.getFs(CurationPanel.CURATION_USER, jCases);
        mergeJCas.removeFsFromIndexes(fs);
      }
    }

    repository.writeCurationCas(mergeJCas, randomAnnotationDocument.getDocument(), userLoggedIn);
    return mergeJCas;
  }
  public CurationContainer buildCurationContainer(BratAnnotatorModel aBModel)
      throws UIMAException, ClassNotFoundException, IOException, BratAnnotationException {
    CurationContainer curationContainer = new CurationContainer();
    // initialize Variables
    SourceDocument sourceDocument = aBModel.getDocument();
    Map<Integer, Integer> segmentBeginEnd = new HashMap<Integer, Integer>();
    Map<Integer, Integer> segmentNumber = new HashMap<Integer, Integer>();
    Map<String, Map<Integer, Integer>> segmentAdress = new HashMap<String, Map<Integer, Integer>>();
    // get annotation documents

    List<AnnotationDocument> finishedAnnotationDocuments = new ArrayList<AnnotationDocument>();

    for (AnnotationDocument annotationDocument :
        repository.listAnnotationDocuments(aBModel.getDocument())) {
      if (annotationDocument.getState().equals(AnnotationDocumentState.FINISHED)) {
        finishedAnnotationDocuments.add(annotationDocument);
      }
    }

    Map<String, JCas> jCases = new HashMap<String, JCas>();

    AnnotationDocument randomAnnotationDocument = null;
    JCas mergeJCas;

    // get the correction/automation JCas for the logged in user
    if (aBModel.getMode().equals(Mode.AUTOMATION) || aBModel.getMode().equals(Mode.CORRECTION)) {
      jCases = listJcasesforCorrection(randomAnnotationDocument, sourceDocument, aBModel.getMode());
      mergeJCas = getMergeCas(aBModel, sourceDocument, jCases, randomAnnotationDocument);
      String username = jCases.keySet().iterator().next();
      updateSegment(
          aBModel,
          segmentBeginEnd,
          segmentNumber,
          segmentAdress,
          jCases.get(username),
          username,
          aBModel.getPreferences().getWindowSize());

    } else {

      jCases =
          listJcasesforCuration(
              finishedAnnotationDocuments, randomAnnotationDocument, aBModel.getMode());
      mergeJCas = getMergeCas(aBModel, sourceDocument, jCases, randomAnnotationDocument);
      updateSegment(
          aBModel,
          segmentBeginEnd,
          segmentNumber,
          segmentAdress,
          mergeJCas,
          CurationPanel.CURATION_USER,
          aBModel.getPreferences().getCurationWindowSize());
    }

    List<Type> entryTypes = null;

    segmentAdress.put(CurationPanel.CURATION_USER, new HashMap<Integer, Integer>());
    for (Sentence sentence : selectCovered(mergeJCas, Sentence.class, begin, end)) {
      segmentAdress.get(CurationPanel.CURATION_USER).put(sentence.getBegin(), getAddr(sentence));
    }

    if (entryTypes == null) {
      entryTypes = getEntryTypes(mergeJCas, aBModel.getAnnotationLayers(), annotationService);
    }

    // for cross-sentences annotation, update the end of the segment
    if (firstload) {
      updateCrossSentAnnoList(segmentBeginEnd, jCases, entryTypes);
      firstload = false;
    }

    for (Integer begin : segmentBeginEnd.keySet()) {
      Integer end = segmentBeginEnd.get(begin);

      DiffResult diff =
          CasDiff2.doDiffSingle(
              annotationService, aBModel.getProject(), entryTypes, jCases, begin, end);
      SourceListView curationSegment = new SourceListView();
      curationSegment.setBegin(begin);
      curationSegment.setEnd(end);
      if (diff.hasDifferences() || !diff.getIncompleteConfigurationSets().isEmpty()) {
        curationSegment.setSentenceState(SentenceState.DISAGREE);
      } else {
        curationSegment.setSentenceState(SentenceState.AGREE);
      }
      curationSegment.setSentenceNumber(segmentNumber.get(begin));

      for (String username : segmentAdress.keySet()) {
        curationSegment.getSentenceAddress().put(username, segmentAdress.get(username).get(begin));
      }
      curationContainer.getCurationViewByBegin().put(begin, curationSegment);
    }
    return curationContainer;
  }