Example #1
0
  public AutomationPage() {
    bModel = new BratAnnotatorModel();
    bModel.setMode(Mode.AUTOMATION);

    LinkedList<CurationUserSegmentForAnnotationDocument> sentences =
        new LinkedList<CurationUserSegmentForAnnotationDocument>();
    CurationUserSegmentForAnnotationDocument curationUserSegmentForAnnotationDocument =
        new CurationUserSegmentForAnnotationDocument();
    if (bModel.getDocument() != null) {
      curationUserSegmentForAnnotationDocument.setAnnotationSelectionByUsernameAndAddress(
          annotationSelectionByUsernameAndAddress);
      curationUserSegmentForAnnotationDocument.setBratAnnotatorModel(bModel);
      sentences.add(curationUserSegmentForAnnotationDocument);
    }
    automateView =
        new SuggestionViewPanel(
            "automateView",
            new Model<LinkedList<CurationUserSegmentForAnnotationDocument>>(sentences)) {
          private static final long serialVersionUID = 2583509126979792202L;

          @Override
          public void onChange(AjaxRequestTarget aTarget) {
            try {
              // update begin/end of the curationsegment based on bratAnnotatorModel changes
              // (like sentence change in auto-scroll mode,....
              aTarget.addChildren(getPage(), FeedbackPanel.class);
              curationContainer.setBratAnnotatorModel(bModel);
              setCurationSegmentBeginEnd();

              CuratorUtil.updatePanel(
                  aTarget,
                  this,
                  curationContainer,
                  mergeVisualizer,
                  repository,
                  annotationSelectionByUsernameAndAddress,
                  curationSegment,
                  annotationService,
                  userRepository);
            } catch (UIMAException e) {
              error(ExceptionUtils.getRootCause(e));
            } catch (ClassNotFoundException e) {
              error(e.getMessage());
            } catch (IOException e) {
              error(e.getMessage());
            } catch (BratAnnotationException e) {
              error(e.getMessage());
            }
            mergeVisualizer.bratRenderLater(aTarget);
            aTarget.add(numberOfPages);
            update(aTarget);
          }
        };

    automateView.setOutputMarkupId(true);
    add(automateView);

    annotationDetailEditorPanel =
        new AnnotationDetailEditorPanel(
            "annotationDetailEditorPanel", new Model<BratAnnotatorModel>(bModel)) {
          private static final long serialVersionUID = 2857345299480098279L;

          @Override
          protected void onChange(AjaxRequestTarget aTarget, BratAnnotatorModel aBModel) {
            aTarget.addChildren(getPage(), FeedbackPanel.class);

            try {
              mergeVisualizer.bratRender(aTarget, getCas(aBModel));
            } catch (UIMAException | ClassNotFoundException | IOException e) {
              LOG.info("Error reading CAS " + e.getMessage());
              error("Error reading CAS " + e.getMessage());
              return;
            }

            mergeVisualizer.bratRenderHighlight(aTarget, aBModel.getSelection().getAnnotation());

            mergeVisualizer.onChange(aTarget, aBModel);
            mergeVisualizer.onAnnotate(
                aTarget,
                aBModel,
                aBModel.getSelection().getBegin(),
                aBModel.getSelection().getEnd());
            if (!aBModel.getSelection().isAnnotate()) {
              mergeVisualizer.onDelete(
                  aTarget,
                  aBModel,
                  aBModel.getSelection().getBegin(),
                  aBModel.getSelection().getEnd());
            }
          }
        };

    annotationDetailEditorPanel.setOutputMarkupId(true);
    add(annotationDetailEditorPanel);

    mergeVisualizer =
        new BratAnnotator(
            "mergeView", new Model<BratAnnotatorModel>(bModel), annotationDetailEditorPanel) {
          private static final long serialVersionUID = 7279648231521710155L;

          @Override
          public void onChange(AjaxRequestTarget aTarget, BratAnnotatorModel aBratAnnotatorModel) {
            try {
              aTarget.addChildren(getPage(), FeedbackPanel.class);
              // info(bratAnnotatorModel.getMessage());
              aTarget.addChildren(getPage(), FeedbackPanel.class);
              bModel = aBratAnnotatorModel;
              SuggestionBuilder builder =
                  new SuggestionBuilder(repository, annotationService, userRepository);
              curationContainer = builder.buildCurationContainer(bModel);
              setCurationSegmentBeginEnd();
              curationContainer.setBratAnnotatorModel(bModel);

              CuratorUtil.updatePanel(
                  aTarget,
                  automateView,
                  curationContainer,
                  this,
                  repository,
                  annotationSelectionByUsernameAndAddress,
                  curationSegment,
                  annotationService,
                  userRepository);
              aTarget.add(automateView);
              aTarget.add(numberOfPages);
            } catch (UIMAException e) {
              error(ExceptionUtils.getRootCause(e));
            } catch (ClassNotFoundException e) {
              error(e.getMessage());
            } catch (IOException e) {
              error(e.getMessage());
            } catch (BratAnnotationException e) {
              error(e.getMessage());
            }
            update(aTarget);
          }

          @Override
          public void onAnnotate(
              AjaxRequestTarget aTarget,
              BratAnnotatorModel aBratAnnotatorModel,
              int aStart,
              int aEnd) {
            MiraTemplate template;
            Set<AnnotationFeature> features = bModel.getRememberedSpanFeatures().keySet();
            AnnotationFeature autoFeature = null;
            for (AnnotationFeature feature : features) {
              autoFeature = feature;
              break;
            }
            try {
              template = automationService.getMiraTemplate(autoFeature);
              if (!template.isAnnotateAndPredict()) {
                return;
              }
              /*
               * Tag tag = annotationService.getTag(bratAnnotatorModel
               * .getRememberedSpanFeatures().get(autoFeature), autoFeature.getTagset());
               */
              AutomationUtil.repeateAnnotation(
                  bModel,
                  repository,
                  userRepository,
                  annotationService,
                  automationService,
                  aStart,
                  aEnd,
                  autoFeature);
            } catch (UIMAException e) {
              error(ExceptionUtils.getRootCause(e));
            } catch (ClassNotFoundException e) {
              error(e.getMessage());
            } catch (IOException e) {
              error(e.getMessage());
            } catch (BratAnnotationException e) {
              error(e.getMessage());
            } catch (NoResultException e) { // no automation layer is configured yet.
              template = null;
              return;
            }
            update(aTarget);
          }

          @Override
          public void onDelete(
              AjaxRequestTarget aTarget,
              BratAnnotatorModel aBratAnnotatorModel,
              int aStart,
              int aEnd) {
            MiraTemplate template;
            Set<AnnotationFeature> features = bModel.getRememberedSpanFeatures().keySet();
            AnnotationFeature autoFeature = null;
            for (AnnotationFeature feature : features) {
              autoFeature = feature;
              break;
            }
            if (autoFeature == null) {
              return;
            }
            try {
              template = automationService.getMiraTemplate(autoFeature);
              if (!template.isAnnotateAndPredict()) {
                return;
              }
              /*
               * Tag tag = annotationService.getTag(bratAnnotatorModel
               * .getRememberedSpanFeatures().get(autoFeature), autoFeature.getTagset());
               */
              AutomationUtil.deleteAnnotation(
                  bModel,
                  repository,
                  annotationService,
                  automationService,
                  userRepository,
                  aStart,
                  aEnd,
                  autoFeature);
            } catch (UIMAException e) {
              error(ExceptionUtils.getRootCause(e));
            } catch (ClassNotFoundException e) {
              error(e.getMessage());
            } catch (IOException e) {
              error(e.getMessage());
            } catch (BratAnnotationException e) {
              error(e.getMessage());
            } catch (NoResultException e) { // no automation layer is configured yet.
              template = null;
              return;
            }
            update(aTarget);
          }
        };
    // reset sentenceAddress and lastSentenceAddress to the orginal once

    mergeVisualizer.setOutputMarkupId(true);
    add(mergeVisualizer);

    curationContainer = new CurationContainer();
    curationContainer.setBratAnnotatorModel(bModel);

    add(
        documentNamePanel =
            new DocumentNamePanel("documentNamePanel", new Model<BratAnnotatorModel>(bModel)));

    add(
        numberOfPages =
            (Label)
                new Label(
                        "numberOfPages",
                        new LoadableDetachableModel<String>() {
                          private static final long serialVersionUID = 891566759811286173L;

                          @Override
                          protected String load() {
                            if (bModel.getDocument() != null) {

                              JCas mergeJCas = null;
                              try {

                                mergeJCas = repository.readCorrectionCas(bModel.getDocument());

                                totalNumberOfSentence = getNumberOfPages(mergeJCas);

                                // If only one page, start displaying from sentence 1
                                /*
                                 * if (totalNumberOfSentence == 1) {
                                 * bratAnnotatorModel.setSentenceAddress(bratAnnotatorModel
                                 * .getFirstSentenceAddress()); }
                                 */
                                int address =
                                    getAddr(
                                        selectSentenceAt(
                                            mergeJCas,
                                            bModel.getSentenceBeginOffset(),
                                            bModel.getSentenceEndOffset()));
                                sentenceNumber = getFirstSentenceNumber(mergeJCas, address);
                                int firstSentenceNumber = sentenceNumber + 1;
                                int lastSentenceNumber;
                                if (firstSentenceNumber
                                        + bModel.getPreferences().getWindowSize()
                                        - 1
                                    < totalNumberOfSentence) {
                                  lastSentenceNumber =
                                      firstSentenceNumber
                                          + bModel.getPreferences().getWindowSize()
                                          - 1;
                                } else {
                                  lastSentenceNumber = totalNumberOfSentence;
                                }

                                return "showing "
                                    + firstSentenceNumber
                                    + "-"
                                    + lastSentenceNumber
                                    + " of "
                                    + totalNumberOfSentence
                                    + " sentences";
                              } catch (UIMAException e) {
                                return "";
                              } catch (DataRetrievalFailureException e) {
                                return "";
                              } catch (ClassNotFoundException e) {
                                return "";
                              } catch (FileNotFoundException e) {
                                return "";
                              } catch (IOException e) {
                                return "";
                              }

                            } else {
                              return ""; // no document yet selected
                            }
                          }
                        })
                    .setOutputMarkupId(true));

    final ModalWindow openDocumentsModal;
    add(openDocumentsModal = new ModalWindow("openDocumentsModal"));
    openDocumentsModal.setOutputMarkupId(true);

    openDocumentsModal.setInitialWidth(500);
    openDocumentsModal.setInitialHeight(300);
    openDocumentsModal.setResizable(true);
    openDocumentsModal.setWidthUnit("px");
    openDocumentsModal.setHeightUnit("px");
    openDocumentsModal.setTitle("Open document");

    add(
        new AjaxLink<Void>("showOpenDocumentModal") {
          private static final long serialVersionUID = 7496156015186497496L;

          @Override
          public void onClick(AjaxRequestTarget aTarget) {
            openDocumentsModal.setContent(
                new OpenModalWindowPanel(
                    openDocumentsModal.getContentId(),
                    bModel,
                    openDocumentsModal,
                    Mode.AUTOMATION));
            openDocumentsModal.setWindowClosedCallback(
                new ModalWindow.WindowClosedCallback() {
                  private static final long serialVersionUID = -1746088901018629567L;

                  @Override
                  public void onClose(AjaxRequestTarget target) {
                    if (bModel.getDocument() == null) {
                      setResponsePage(WelcomePage.class);
                      return;
                    }

                    try {
                      target.addChildren(getPage(), FeedbackPanel.class);
                      bModel.setDocument(bModel.getDocument());
                      bModel.setProject(bModel.getProject());

                      String username =
                          SecurityContextHolder.getContext().getAuthentication().getName();

                      repository.upgradeCasAndSave(bModel.getDocument(), Mode.AUTOMATION, username);
                      loadDocumentAction();
                      setCurationSegmentBeginEnd();
                      update(target);

                    } catch (UIMAException e) {
                      target.addChildren(getPage(), FeedbackPanel.class);
                      error(ExceptionUtils.getRootCause(e));
                    } catch (ClassNotFoundException e) {
                      target.addChildren(getPage(), FeedbackPanel.class);
                      error(e.getMessage());
                    } catch (IOException e) {
                      target.addChildren(getPage(), FeedbackPanel.class);
                      error(e.getMessage());
                    } catch (BratAnnotationException e) {
                      error(e.getMessage());
                    }
                    finish.setModelObject(bModel);
                    target.add(finish.setOutputMarkupId(true));
                    target.appendJavaScript(
                        "Wicket.Window.unloadConfirmation=false;window.location.reload()");
                    target.add(documentNamePanel.setOutputMarkupId(true));
                    target.add(numberOfPages);
                  }
                });
            openDocumentsModal.show(aTarget);
          }
        });

    add(
        new AnnotationLayersModalPanel(
            "annotationLayersModalPanel", new Model<BratAnnotatorModel>(bModel)) {
          private static final long serialVersionUID = -4657965743173979437L;

          @Override
          protected void onChange(AjaxRequestTarget aTarget) {
            curationContainer.setBratAnnotatorModel(bModel);
            try {
              aTarget.addChildren(getPage(), FeedbackPanel.class);
              setCurationSegmentBeginEnd();
            } catch (UIMAException e) {
              error(ExceptionUtils.getRootCauseMessage(e));
            } catch (ClassNotFoundException e) {
              error(e.getMessage());
            } catch (IOException e) {
              error(e.getMessage());
            }
            update(aTarget);
            // mergeVisualizer.reloadContent(aTarget);
            aTarget.appendJavaScript(
                "Wicket.Window.unloadConfirmation = false;window.location.reload()");
          }
        });

    add(new ExportModalPanel("exportModalPanel", new Model<BratAnnotatorModel>(bModel)));

    gotoPageTextField =
        (NumberTextField<Integer>)
            new NumberTextField<Integer>("gotoPageText", new Model<Integer>(0));
    Form<Void> gotoPageTextFieldForm = new Form<Void>("gotoPageTextFieldForm");
    gotoPageTextFieldForm.add(
        new AjaxFormSubmitBehavior(gotoPageTextFieldForm, "onsubmit") {
          private static final long serialVersionUID = -4549805321484461545L;

          @Override
          protected void onSubmit(AjaxRequestTarget aTarget) {
            if (gotoPageAddress == 0) {
              aTarget.appendJavaScript("alert('The sentence number entered is not valid')");
              return;
            }
            JCas mergeJCas = null;
            try {
              aTarget.addChildren(getPage(), FeedbackPanel.class);
              mergeJCas = repository.readCorrectionCas(bModel.getDocument());
              if (bModel.getSentenceAddress() != gotoPageAddress) {

                ubdateSentenceNumber(mergeJCas, gotoPageAddress);

                SuggestionBuilder builder =
                    new SuggestionBuilder(repository, annotationService, userRepository);
                curationContainer = builder.buildCurationContainer(bModel);
                setCurationSegmentBeginEnd();
                curationContainer.setBratAnnotatorModel(bModel);
                update(aTarget);
                mergeVisualizer.bratRenderLater(aTarget);
              }
            } catch (UIMAException e) {
              error(ExceptionUtils.getRootCause(e));
            } catch (ClassNotFoundException e) {
              error(e.getMessage());
            } catch (IOException e) {
              error(e.getMessage());
            } catch (BratAnnotationException e) {
              error(e.getMessage());
            }
          }
        });

    gotoPageTextField.setType(Integer.class);
    gotoPageTextField.setMinimum(1);
    gotoPageTextField.setDefaultModelObject(1);
    add(gotoPageTextFieldForm.add(gotoPageTextField));
    gotoPageTextField.add(
        new AjaxFormComponentUpdatingBehavior("onchange") {
          private static final long serialVersionUID = -3853194405966729661L;

          @Override
          protected void onUpdate(AjaxRequestTarget target) {
            JCas mergeJCas = null;
            try {
              mergeJCas = repository.readCorrectionCas(bModel.getDocument());
              gotoPageAddress = getSentenceAddress(mergeJCas, gotoPageTextField.getModelObject());
            } catch (UIMAException e) {
              error(ExceptionUtils.getRootCause(e));
            } catch (ClassNotFoundException e) {
              error(ExceptionUtils.getRootCause(e));
            } catch (IOException e) {
              error(e.getMessage());
            }
          }
        });

    add(
        new AjaxLink<Void>("gotoPageLink") {
          private static final long serialVersionUID = 7496156015186497496L;

          @Override
          public void onClick(AjaxRequestTarget aTarget) {

            if (gotoPageAddress == 0) {
              aTarget.appendJavaScript("alert('The sentence number entered is not valid')");
              return;
            }
            if (bModel.getDocument() == null) {
              aTarget.appendJavaScript("alert('Please open a document first!')");
              return;
            }
            JCas mergeJCas = null;
            try {
              aTarget.addChildren(getPage(), FeedbackPanel.class);
              mergeJCas = repository.readCorrectionCas(bModel.getDocument());
              if (bModel.getSentenceAddress() != gotoPageAddress) {

                ubdateSentenceNumber(mergeJCas, gotoPageAddress);

                SuggestionBuilder builder =
                    new SuggestionBuilder(repository, annotationService, userRepository);
                curationContainer = builder.buildCurationContainer(bModel);
                setCurationSegmentBeginEnd();
                curationContainer.setBratAnnotatorModel(bModel);
                update(aTarget);
                mergeVisualizer.bratRenderLater(aTarget);
              }
            } catch (UIMAException e) {
              error(ExceptionUtils.getRootCause(e));
            } catch (ClassNotFoundException e) {
              error(e.getMessage());
            } catch (IOException e) {
              error(e.getMessage());
            } catch (BratAnnotationException e) {
              error(e.getMessage());
            }
          }
        });

    finish =
        new FinishImage(
            "finishImage",
            new LoadableDetachableModel<BratAnnotatorModel>() {
              private static final long serialVersionUID = -2737326878793568454L;

              @Override
              protected BratAnnotatorModel load() {
                return bModel;
              }
            });

    add(
        new FinishLink("showYesNoModalPanel", new Model<BratAnnotatorModel>(bModel), finish) {
          private static final long serialVersionUID = -4657965743173979437L;
        });

    // Show the previous document, if exist
    add(
        new AjaxLink<Void>("showPreviousDocument") {
          private static final long serialVersionUID = 7496156015186497496L;

          /**
           * Get the current beginning sentence address and add on it the size of the display window
           */
          @Override
          public void onClick(AjaxRequestTarget target) {
            target.addChildren(getPage(), FeedbackPanel.class);
            // List of all Source Documents in the project
            List<SourceDocument> listOfSourceDocuements =
                repository.listSourceDocuments(bModel.getProject());

            String username = SecurityContextHolder.getContext().getAuthentication().getName();
            User user = userRepository.get(username);

            List<SourceDocument> sourceDocumentsinIgnorState = new ArrayList<SourceDocument>();
            for (SourceDocument sourceDocument : listOfSourceDocuements) {
              if (repository.existsAnnotationDocument(sourceDocument, user)
                  && repository
                      .getAnnotationDocument(sourceDocument, user)
                      .getState()
                      .equals(AnnotationDocumentState.IGNORE)) {
                sourceDocumentsinIgnorState.add(sourceDocument);
              } else if (sourceDocument.isTrainingDocument()) {
                sourceDocumentsinIgnorState.add(sourceDocument);
              }
            }

            listOfSourceDocuements.removeAll(sourceDocumentsinIgnorState);

            // Index of the current source document in the list
            int currentDocumentIndex = listOfSourceDocuements.indexOf(bModel.getDocument());

            // If the first the document
            if (currentDocumentIndex == 0) {
              target.appendJavaScript("alert('This is the first document!')");
            } else {
              bModel.setDocumentName(
                  listOfSourceDocuements.get(currentDocumentIndex - 1).getName());
              bModel.setDocument(listOfSourceDocuements.get(currentDocumentIndex - 1));

              try {
                repository.upgradeCasAndSave(
                    bModel.getDocument(), Mode.AUTOMATION, bModel.getUser().getUsername());
                loadDocumentAction();
                setCurationSegmentBeginEnd();
                update(target);

              } catch (UIMAException e) {
                error(ExceptionUtils.getRootCause(e));
              } catch (ClassNotFoundException e) {
                error(ExceptionUtils.getRootCause(e));
              } catch (IOException e) {
                error(ExceptionUtils.getRootCause(e));
              } catch (BratAnnotationException e) {
                target.addChildren(getPage(), FeedbackPanel.class);
                error(e.getMessage());
              }

              finish.setModelObject(bModel);
              target.add(finish.setOutputMarkupId(true));
              target.add(numberOfPages);
              target.add(documentNamePanel);
              mergeVisualizer.bratRenderLater(target);
            }
          }
        }.add(new InputBehavior(new KeyType[] {KeyType.Shift, KeyType.Page_up}, EventType.click)));

    // Show the next document if exist
    add(
        new AjaxLink<Void>("showNextDocument") {
          private static final long serialVersionUID = 7496156015186497496L;

          /**
           * Get the current beginning sentence address and add on it the size of the display window
           */
          @Override
          public void onClick(AjaxRequestTarget target) {
            target.addChildren(getPage(), FeedbackPanel.class);
            // List of all Source Documents in the project
            List<SourceDocument> listOfSourceDocuements =
                repository.listSourceDocuments(bModel.getProject());

            String username = SecurityContextHolder.getContext().getAuthentication().getName();
            User user = userRepository.get(username);

            List<SourceDocument> sourceDocumentsinIgnorState = new ArrayList<SourceDocument>();
            for (SourceDocument sourceDocument : listOfSourceDocuements) {
              if (repository.existsAnnotationDocument(sourceDocument, user)
                  && repository
                      .getAnnotationDocument(sourceDocument, user)
                      .getState()
                      .equals(AnnotationDocumentState.IGNORE)) {
                sourceDocumentsinIgnorState.add(sourceDocument);
              } else if (sourceDocument.isTrainingDocument()) {
                sourceDocumentsinIgnorState.add(sourceDocument);
              }
            }

            listOfSourceDocuements.removeAll(sourceDocumentsinIgnorState);

            // Index of the current source document in the list
            int currentDocumentIndex = listOfSourceDocuements.indexOf(bModel.getDocument());

            // If the first document
            if (currentDocumentIndex == listOfSourceDocuements.size() - 1) {
              target.appendJavaScript("alert('This is the last document!')");
              return;
            }
            bModel.setDocumentName(listOfSourceDocuements.get(currentDocumentIndex + 1).getName());
            bModel.setDocument(listOfSourceDocuements.get(currentDocumentIndex + 1));

            try {
              repository.upgradeCasAndSave(
                  bModel.getDocument(), Mode.AUTOMATION, bModel.getUser().getUsername());
              loadDocumentAction();
              setCurationSegmentBeginEnd();
              update(target);

            } catch (UIMAException e) {
              error(ExceptionUtils.getRootCause(e));
            } catch (ClassNotFoundException e) {
              error(ExceptionUtils.getRootCause(e));
            } catch (IOException e) {
              error(ExceptionUtils.getRootCause(e));
            } catch (BratAnnotationException e) {
              target.addChildren(getPage(), FeedbackPanel.class);
              error(e.getMessage());
            }

            finish.setModelObject(bModel);
            target.add(finish.setOutputMarkupId(true));
            target.add(numberOfPages);
            target.add(documentNamePanel);
            mergeVisualizer.bratRenderLater(target);
          }
        }.add(
            new InputBehavior(new KeyType[] {KeyType.Shift, KeyType.Page_down}, EventType.click)));

    // Show the next page of this document
    add(
        new AjaxLink<Void>("showNext") {
          private static final long serialVersionUID = 7496156015186497496L;

          /**
           * Get the current beginning sentence address and add on it the size of the display window
           */
          @Override
          public void onClick(AjaxRequestTarget aTarget) {
            if (bModel.getDocument() != null) {
              JCas mergeJCas = null;
              try {
                aTarget.addChildren(getPage(), FeedbackPanel.class);
                mergeJCas = repository.readCorrectionCas(bModel.getDocument());
                int address =
                    getAddr(
                        selectSentenceAt(
                            mergeJCas,
                            bModel.getSentenceBeginOffset(),
                            bModel.getSentenceEndOffset()));
                int nextSentenceAddress =
                    getNextPageFirstSentenceAddress(
                        mergeJCas, address, bModel.getPreferences().getWindowSize());
                if (address != nextSentenceAddress) {
                  ubdateSentenceNumber(mergeJCas, nextSentenceAddress);

                  SuggestionBuilder builder =
                      new SuggestionBuilder(repository, annotationService, userRepository);
                  curationContainer = builder.buildCurationContainer(bModel);
                  setCurationSegmentBeginEnd();
                  curationContainer.setBratAnnotatorModel(bModel);
                  update(aTarget);
                  mergeVisualizer.bratRenderLater(aTarget);
                } else {
                  aTarget.appendJavaScript("alert('This is last page!')");
                }
              } catch (UIMAException e) {
                error(ExceptionUtils.getRootCause(e));
              } catch (ClassNotFoundException e) {
                error(e.getMessage());
              } catch (IOException e) {
                error(e.getMessage());
              } catch (BratAnnotationException e) {
                error(e.getMessage());
              }
            } else {
              aTarget.appendJavaScript("alert('Please open a document first!')");
            }
          }
        }.add(new InputBehavior(new KeyType[] {KeyType.Page_down}, EventType.click)));

    // SHow the previous page of this document
    add(
        new AjaxLink<Void>("showPrevious") {
          private static final long serialVersionUID = 7496156015186497496L;

          @Override
          public void onClick(AjaxRequestTarget aTarget) {
            if (bModel.getDocument() != null) {

              JCas mergeJCas = null;
              try {
                aTarget.addChildren(getPage(), FeedbackPanel.class);
                mergeJCas = repository.readCorrectionCas(bModel.getDocument());
                int previousSentenceAddress =
                    BratAjaxCasUtil.getPreviousDisplayWindowSentenceBeginAddress(
                        mergeJCas,
                        bModel.getSentenceAddress(),
                        bModel.getPreferences().getWindowSize());
                if (bModel.getSentenceAddress() != previousSentenceAddress) {
                  ubdateSentenceNumber(mergeJCas, previousSentenceAddress);

                  SuggestionBuilder builder =
                      new SuggestionBuilder(repository, annotationService, userRepository);

                  curationContainer = builder.buildCurationContainer(bModel);
                  setCurationSegmentBeginEnd();
                  curationContainer.setBratAnnotatorModel(bModel);
                  update(aTarget);
                  mergeVisualizer.bratRenderLater(aTarget);
                } else {
                  aTarget.appendJavaScript("alert('This is First Page!')");
                }
              } catch (UIMAException e) {
                error(ExceptionUtils.getRootCause(e));
              } catch (ClassNotFoundException e) {
                error(e.getMessage());
              } catch (IOException e) {;
                error(e.getMessage());
              } catch (BratAnnotationException e) {
                error(e.getMessage());
              }
            } else {
              aTarget.appendJavaScript("alert('Please open a document first!')");
            }
          }
        }.add(new InputBehavior(new KeyType[] {KeyType.Page_up}, EventType.click)));

    add(
        new AjaxLink<Void>("showFirst") {
          private static final long serialVersionUID = 7496156015186497496L;

          @Override
          public void onClick(AjaxRequestTarget aTarget) {
            if (bModel.getDocument() != null) {
              JCas mergeJCas = null;
              try {
                aTarget.addChildren(getPage(), FeedbackPanel.class);
                mergeJCas = repository.readCorrectionCas(bModel.getDocument());

                int address =
                    getAddr(
                        selectSentenceAt(
                            mergeJCas,
                            bModel.getSentenceBeginOffset(),
                            bModel.getSentenceEndOffset()));
                int firstAddress = getFirstSentenceAddress(mergeJCas);

                if (firstAddress != address) {
                  ubdateSentenceNumber(mergeJCas, firstAddress);

                  SuggestionBuilder builder =
                      new SuggestionBuilder(repository, annotationService, userRepository);
                  curationContainer = builder.buildCurationContainer(bModel);
                  setCurationSegmentBeginEnd();
                  curationContainer.setBratAnnotatorModel(bModel);
                  update(aTarget);
                  mergeVisualizer.bratRenderLater(aTarget);
                } else {
                  aTarget.appendJavaScript("alert('This is first page!')");
                }
              } catch (UIMAException e) {
                error(ExceptionUtils.getRootCause(e));
              } catch (ClassNotFoundException e) {
                error(e.getMessage());
              } catch (IOException e) {
                error(e.getMessage());
              } catch (BratAnnotationException e) {
                error(e.getMessage());
              }
            } else {
              aTarget.appendJavaScript("alert('Please open a document first!')");
            }
          }
        }.add(new InputBehavior(new KeyType[] {KeyType.Home}, EventType.click)));

    add(
        new AjaxLink<Void>("showLast") {
          private static final long serialVersionUID = 7496156015186497496L;

          @Override
          public void onClick(AjaxRequestTarget aTarget) {
            if (bModel.getDocument() != null) {
              JCas mergeJCas = null;
              try {
                aTarget.addChildren(getPage(), FeedbackPanel.class);
                mergeJCas = repository.readCorrectionCas(bModel.getDocument());
                int lastDisplayWindowBeginingSentenceAddress =
                    BratAjaxCasUtil.getLastDisplayWindowFirstSentenceAddress(
                        mergeJCas, bModel.getPreferences().getWindowSize());
                if (lastDisplayWindowBeginingSentenceAddress != bModel.getSentenceAddress()) {
                  ubdateSentenceNumber(mergeJCas, lastDisplayWindowBeginingSentenceAddress);

                  SuggestionBuilder builder =
                      new SuggestionBuilder(repository, annotationService, userRepository);
                  curationContainer = builder.buildCurationContainer(bModel);
                  setCurationSegmentBeginEnd();
                  curationContainer.setBratAnnotatorModel(bModel);
                  update(aTarget);
                  mergeVisualizer.bratRenderLater(aTarget);

                } else {
                  aTarget.appendJavaScript("alert('This is last Page!')");
                }
              } catch (UIMAException e) {
                error(ExceptionUtils.getRootCause(e));
              } catch (ClassNotFoundException e) {
                error(e.getMessage());
              } catch (IOException e) {
                error(e.getMessage());
              } catch (BratAnnotationException e) {
                error(e.getMessage());
              }
            } else {
              aTarget.appendJavaScript("alert('Please open a document first!')");
            }
          }
        }.add(new InputBehavior(new KeyType[] {KeyType.End}, EventType.click)));

    add(new GuidelineModalPanel("guidelineModalPanel", new Model<BratAnnotatorModel>(bModel)));
  }
  public CurationPanel(String id, final IModel<CurationContainer> cCModel) {
    super(id, cCModel);
    WebMarkupContainer sidebarCell =
        new WebMarkupContainer("sidebarCell") {
          private static final long serialVersionUID = 1L;

          @Override
          protected void onComponentTag(ComponentTag aTag) {
            super.onComponentTag(aTag);
            aTag.put("width", bModel.getPreferences().getSidebarSize() + "%");
          }
        };
    add(sidebarCell);

    WebMarkupContainer annotationViewCell =
        new WebMarkupContainer("annotationViewCell") {
          private static final long serialVersionUID = 1L;

          @Override
          protected void onComponentTag(ComponentTag aTag) {
            super.onComponentTag(aTag);
            aTag.put("width", (100 - bModel.getPreferences().getSidebarSize()) + "%");
          }
        };
    add(annotationViewCell);

    // add container for list of sentences panel
    sentencesListView = new WebMarkupContainer("sentencesListView");
    sentencesListView.setOutputMarkupId(true);
    add(sentencesListView);

    // add container for the list of sentences where annotations exists crossing multiple
    // sentences
    // outside of the current page
    corssSentAnnoView = new WebMarkupContainer("corssSentAnnoView");
    corssSentAnnoView.setOutputMarkupId(true);
    annotationViewCell.add(corssSentAnnoView);

    bModel = getModelObject().getBratAnnotatorModel();

    LinkedList<CurationUserSegmentForAnnotationDocument> sentences =
        new LinkedList<CurationUserSegmentForAnnotationDocument>();
    CurationUserSegmentForAnnotationDocument curationUserSegmentForAnnotationDocument =
        new CurationUserSegmentForAnnotationDocument();
    if (bModel != null) {
      curationUserSegmentForAnnotationDocument.setAnnotationSelectionByUsernameAndAddress(
          annotationSelectionByUsernameAndAddress);
      curationUserSegmentForAnnotationDocument.setBratAnnotatorModel(bModel);
      sentences.add(curationUserSegmentForAnnotationDocument);
    }
    // update source list model only first time.
    sourceListModel =
        sourceListModel == null ? getModelObject().getCurationViews() : sourceListModel;

    suggestionViewPanel =
        new SuggestionViewPanel(
            "suggestionViewPanel",
            new Model<LinkedList<CurationUserSegmentForAnnotationDocument>>(sentences)) {
          private static final long serialVersionUID = 2583509126979792202L;
          CurationContainer curationContainer = cCModel.getObject();

          @Override
          public void onChange(AjaxRequestTarget aTarget) {
            try {
              // update begin/end of the curationsegment based on bratAnnotatorModel changes
              // (like sentence change in auto-scroll mode,....
              aTarget.addChildren(getPage(), FeedbackPanel.class);
              updatePanel(aTarget, curationContainer);
            } catch (UIMAException e) {
              error(ExceptionUtils.getRootCause(e));
            } catch (ClassNotFoundException e) {
              error(e.getMessage());
            } catch (IOException e) {
              error(e.getMessage());
            } catch (BratAnnotationException e) {
              error(e.getMessage());
            }
          }
        };

    suggestionViewPanel.setOutputMarkupId(true);
    annotationViewCell.add(suggestionViewPanel);

    editor =
        new AnnotationDetailEditorPanel(
            "annotationDetailEditorPanel", new Model<BratAnnotatorModel>(bModel)) {
          private static final long serialVersionUID = 2857345299480098279L;

          @Override
          protected void onChange(AjaxRequestTarget aTarget, BratAnnotatorModel aBModel) {
            aTarget.addChildren(getPage(), FeedbackPanel.class);
            annotate = true;

            annotator.onChange(aTarget, aBModel);
          }

          @Override
          protected void onAutoForward(AjaxRequestTarget aTarget, BratAnnotatorModel aBModel) {
            try {
              annotator.autoForward(aTarget, getCas(aBModel));
            } catch (UIMAException
                | ClassNotFoundException
                | IOException
                | BratAnnotationException e) {
              LOG.info("Error reading CAS " + e.getMessage());
              error("Error reading CAS " + e.getMessage());
              return;
            }
          }

          @Override
          protected void onConfigure() {
            super.onConfigure();
            setEnabled(
                bModel.getDocument() != null
                    && !repository
                        .getSourceDocument(
                            bModel.getDocument().getProject(), bModel.getDocument().getName())
                        .getState()
                        .equals(SourceDocumentState.CURATION_FINISHED));
          }
        };

    editor.setOutputMarkupId(true);
    sidebarCell.add(editor);

    annotator =
        new BratAnnotator("mergeView", new Model<BratAnnotatorModel>(bModel), editor) {

          private static final long serialVersionUID = 7279648231521710155L;

          @Override
          public void onChange(AjaxRequestTarget aTarget, BratAnnotatorModel bratAnnotatorModel) {
            aTarget.addChildren(getPage(), FeedbackPanel.class);
            try {
              updatePanel(aTarget, cCModel.getObject());
            } catch (UIMAException e) {
              error(ExceptionUtils.getRootCause(e));
            } catch (ClassNotFoundException e) {
              error(e.getMessage());
            } catch (IOException e) {
              error(e.getMessage());
            } catch (BratAnnotationException e) {
              error(e.getMessage());
            }
          }
        };
    // reset sentenceAddress and lastSentenceAddress to the orginal once

    annotator.setOutputMarkupId(true);
    annotationViewCell.add(annotator);

    LoadableDetachableModel sentenceDiffModel =
        new LoadableDetachableModel() {

          @Override
          protected Object load() {
            int fSN = bModel.getFSN();
            int lSN = bModel.getLSN();

            List<String> crossSentAnnos = new ArrayList<>();
            if (SuggestionBuilder.crossSentenceLists != null) {
              for (int sn : SuggestionBuilder.crossSentenceLists.keySet()) {
                if (sn >= fSN && sn <= lSN) {
                  List<Integer> cr = new ArrayList<>();
                  for (int c : SuggestionBuilder.crossSentenceLists.get(sn)) {
                    if (c < fSN || c > lSN) {
                      cr.add(c);
                    }
                  }
                  if (!cr.isEmpty()) {
                    crossSentAnnos.add(sn + "-->" + cr);
                  }
                }
              }
            }

            return crossSentAnnos;
          }
        };

    crossSentAnnoList =
        new ListView<String>("crossSentAnnoList", sentenceDiffModel) {
          private static final long serialVersionUID = 8539162089561432091L;

          @Override
          protected void populateItem(ListItem<String> item) {
            String crossSentAnno = item.getModelObject();

            // ajax call when clicking on a sentence on the left side
            final AbstractDefaultAjaxBehavior click =
                new AbstractDefaultAjaxBehavior() {
                  private static final long serialVersionUID = 5803814168152098822L;

                  @Override
                  protected void respond(AjaxRequestTarget aTarget) {
                    // Expand curation view
                  }
                };

            // add subcomponents to the component
            item.add(click);
            Label crossSentAnnoItem = new AjaxLabel("crossAnnoSent", crossSentAnno, click);
            item.add(crossSentAnnoItem);
          }
        };
    crossSentAnnoList.setOutputMarkupId(true);
    corssSentAnnoView.add(crossSentAnnoList);

    LoadableDetachableModel sentencesListModel =
        new LoadableDetachableModel() {

          @Override
          protected Object load() {

            return getModelObject().getCurationViews();
          }
        };

    sentenceList =
        new ListView<SourceListView>("sentencesList", sentencesListModel) {
          private static final long serialVersionUID = 8539162089561432091L;

          @Override
          protected void populateItem(ListItem<SourceListView> item) {
            final SourceListView curationViewItem = item.getModelObject();

            // ajax call when clicking on a sentence on the left side
            final AbstractDefaultAjaxBehavior click =
                new AbstractDefaultAjaxBehavior() {
                  private static final long serialVersionUID = 5803814168152098822L;

                  @Override
                  protected void respond(AjaxRequestTarget aTarget) {
                    curationView = curationViewItem;
                    fSn = 0;
                    try {
                      JCas jCas = repository.readCurationCas(bModel.getDocument());
                      updateCurationView(cCModel.getObject(), curationViewItem, aTarget, jCas);
                      updatePanel(aTarget, cCModel.getObject());
                      bModel.setSentenceNumber(curationViewItem.getSentenceNumber());

                    } catch (UIMAException e) {
                      error(ExceptionUtils.getRootCause(e));
                    } catch (ClassNotFoundException e) {
                      error(e.getMessage());
                    } catch (IOException e) {
                      error(e.getMessage());
                    } catch (BratAnnotationException e) {
                      error(e.getMessage());
                    }
                  }
                };

            // add subcomponents to the component
            item.add(click);

            String cC = curationViewItem.getSentenceState().getValue();
            // mark current sentence in orange if disagree
            if (curationViewItem.getSentenceNumber() == bModel.getSentenceNumber()) {
              if (cC != null) {
                item.add(AttributeModifier.append("class", "current-disagree"));
              }
            } else if (cC != null) {
              // disagree in range
              if (curationViewItem.getSentenceNumber() >= fSn
                  && curationViewItem.getSentenceNumber() <= lSn) {
                item.add(AttributeModifier.append("class", "range-disagree"));
              } else {
                item.add(AttributeModifier.append("class", "disagree"));
              }
            }
            // agree and in range
            else if (curationViewItem.getSentenceNumber() >= fSn
                && curationViewItem.getSentenceNumber() <= lSn) {
              item.add(AttributeModifier.append("class", "range-agree"));
            } else {
              item.add(AttributeModifier.append("class", "agree"));
            }
            Label sentenceNumber =
                new AjaxLabel(
                    "sentenceNumber", curationViewItem.getSentenceNumber().toString(), click);
            item.add(sentenceNumber);
          }
        };
    // add subcomponents to the component
    sentenceList.setOutputMarkupId(true);
    sentencesListView.add(sentenceList);
  }