private PermissibleObjectTreeNode findParentCommentNode(
     PermissibleObjectTreeNode rootNode, PermissibleObjectTreeNode node) {
   if (node.getObject().equals(rootNode.getObject())) {
     return rootNode;
   }
   for (PermissibleObject obj : rootNode.getChildren().keySet()) {
     if (obj.equals(((Comment) node.getObject()).getParentComment())) {
       return rootNode.getChildren().get(obj);
     }
     PermissibleObjectTreeNode possibleParent =
         findParentCommentNode(rootNode.getChildren().get(obj), node);
     if (possibleParent != null) {
       return possibleParent;
     }
   }
   return null;
 }
  private void loadCommentWidget(final boolean forceOpen) {
    clear();
    if (permissibleObject.isAllowComments()) {

      String fileName = permissibleObject.getName();
      final DisclosurePanel commentDisclosurePanel =
          new DisclosurePanel("View comments (" + numComments + ") for " + fileName);

      VerticalPanel commentsPanel = new VerticalPanel();
      commentsPanel.setSpacing(0);
      if (numComments > 0) {
        commentsPanel.setStyleName("commentsPanel");
      }
      commentsPanel.setWidth("100%");

      int renderedComments = 0;
      boolean userCanManage =
          AuthenticationHandler.getInstance().getUser() != null
              && (AuthenticationHandler.getInstance().getUser().isAdministrator()
                  || AuthenticationHandler.getInstance()
                      .getUser()
                      .equals(permissibleObject.getOwner()));
      List<PermissibleObject> sortedComments = new ArrayList<PermissibleObject>();
      if (comments != null) {
        sortedComments.addAll(comments);
      }
      if (!flatten) {
        sortedComments = sortComments(sortedComments);
      }

      for (PermissibleObject obj : sortedComments) {
        final Comment comment = (Comment) obj;
        int commentDepth = getCommentDepth(comment);

        int maxDepth =
            Integer.parseInt(
                maxCommentDepthListBox.getValue(maxCommentDepthListBox.getSelectedIndex()));
        if (commentDepth >= maxDepth) {
          continue;
        }

        boolean userIsAuthorOfComment =
            AuthenticationHandler.getInstance().getUser() != null
                && comment.getAuthor() != null
                && comment.getAuthor().equals(AuthenticationHandler.getInstance().getUser());

        if (userCanManage || userIsAuthorOfComment || comment.isApproved()) {

          FlexTable commentHeaderPanel = new FlexTable();
          commentHeaderPanel.setCellPadding(0);
          commentHeaderPanel.setCellSpacing(0);
          commentHeaderPanel.setStyleName("commentHeader");
          commentHeaderPanel.setWidth("100%");

          String authorLabelString =
              comment.getAuthor() == null ? comment.getEmail() : comment.getAuthor().getUsername();
          if (comment.getAuthor() != null
              && comment.getAuthor().getFirstname() != null
              && !"".equals(comment.getAuthor().getFirstname())) {
            authorLabelString += " (" + comment.getAuthor().getFirstname();
            if (comment.getAuthor() != null
                && comment.getAuthor().getLastname() != null
                && !"".equals(comment.getAuthor().getLastname())) {
              authorLabelString += " " + comment.getAuthor().getLastname() + ")";
            } else {
              authorLabelString += ")";
            }
          }

          Image replyCommentImage = new Image();
          replyCommentImage.setResource(BaseImageBundle.images.reply());
          replyCommentImage.setStyleName("commentActionButton");
          replyCommentImage.setTitle("Reply to this comment");
          replyCommentImage.addClickHandler(
              new ClickHandler() {

                public void onClick(ClickEvent event) {
                  replyToComment(comment);
                }
              });
          int columnIndex = 0;
          commentHeaderPanel.setWidget(0, columnIndex, replyCommentImage);
          commentHeaderPanel
              .getFlexCellFormatter()
              .setHorizontalAlignment(0, columnIndex, HasHorizontalAlignment.ALIGN_LEFT);
          columnIndex++;

          Label authorLabel = new Label(authorLabelString, false);
          commentHeaderPanel.setWidget(0, columnIndex, authorLabel);
          commentHeaderPanel
              .getFlexCellFormatter()
              .setHorizontalAlignment(0, columnIndex, HasHorizontalAlignment.ALIGN_LEFT);
          columnIndex++;
          commentHeaderPanel.setWidget(0, columnIndex, new Label());
          commentHeaderPanel.getFlexCellFormatter().setWidth(0, columnIndex, "100%");
          commentHeaderPanel
              .getFlexCellFormatter()
              .setHorizontalAlignment(0, columnIndex, HasHorizontalAlignment.ALIGN_RIGHT);
          columnIndex++;
          Label dateLabel = new Label(new Date(comment.getCommentDate()).toLocaleString(), false);
          commentHeaderPanel.setWidget(0, columnIndex, dateLabel);
          if (!userCanManage && !userIsAuthorOfComment) {
            DOM.setStyleAttribute(dateLabel.getElement(), "padding", "0 5px 0 0");
          }
          commentHeaderPanel
              .getFlexCellFormatter()
              .setHorizontalAlignment(0, columnIndex, HasHorizontalAlignment.ALIGN_RIGHT);

          columnIndex++;
          if (userCanManage || userIsAuthorOfComment) {
            if (userCanManage && !comment.isApproved()) {
              final Image approveCommentImage = new Image();
              approveCommentImage.setResource(BaseImageBundle.images.approve());
              approveCommentImage.setStyleName("commentActionButton");
              approveCommentImage.setTitle("Approve comment");
              approveCommentImage.addClickHandler(
                  new ClickHandler() {

                    public void onClick(ClickEvent event) {
                      workingOnComment = comment;
                      approveComment(comment);
                    }
                  });
              commentHeaderPanel.setWidget(0, columnIndex, approveCommentImage);
              commentHeaderPanel
                  .getFlexCellFormatter()
                  .setHorizontalAlignment(0, columnIndex, HasHorizontalAlignment.ALIGN_RIGHT);
              columnIndex++;
            } else {
              // put 16x16 spacer here for alignment
              final Image approveSpacerImage = new Image();
              approveSpacerImage.setResource(BaseImageBundle.images.empty16x16());
              approveSpacerImage.setStyleName("commentActionButton");
              commentHeaderPanel.setWidget(0, columnIndex, approveSpacerImage);
              commentHeaderPanel
                  .getFlexCellFormatter()
                  .setHorizontalAlignment(0, columnIndex, HasHorizontalAlignment.ALIGN_RIGHT);
              columnIndex++;
            }
            Image deleteCommentImage = new Image();
            deleteCommentImage.setResource(BaseImageBundle.images.delete());
            deleteCommentImage.setStyleName("commentActionButton");
            deleteCommentImage.setTitle("Remove comment");
            deleteCommentImage.addClickHandler(
                new ClickHandler() {

                  public void onClick(ClickEvent event) {
                    IDialogCallback callback =
                        new IDialogCallback() {

                          public void cancelPressed() {}

                          public void okPressed() {
                            deleteComment(comment);
                          }
                        };
                    PromptDialogBox dialogBox =
                        new PromptDialogBox("Question", "Yes", null, "No", false, true);
                    dialogBox.setContent(
                        new Label(
                            "Delete comment by "
                                + (comment.getAuthor() == null
                                    ? comment.getEmail()
                                    : comment.getAuthor().getUsername())
                                + "?"));
                    dialogBox.setCallback(callback);
                    dialogBox.center();
                  }
                });
            commentHeaderPanel.setWidget(0, columnIndex, deleteCommentImage);
            commentHeaderPanel
                .getFlexCellFormatter()
                .setHorizontalAlignment(0, columnIndex, HasHorizontalAlignment.ALIGN_RIGHT);
            columnIndex++;
          }

          if (commentDepth > 0) {
            HorizontalPanel commentHeaderPanelWrapper = new HorizontalPanel();
            commentHeaderPanelWrapper.setWidth("100%");
            Label spacerLabel = new Label();
            commentHeaderPanelWrapper.add(spacerLabel);
            if (!flatten) {
              commentHeaderPanelWrapper.setCellWidth(spacerLabel, (commentDepth * 20) + "px");
            }
            commentHeaderPanelWrapper.add(commentHeaderPanel);
            commentsPanel.add(commentHeaderPanelWrapper);
          } else {
            commentsPanel.add(commentHeaderPanel);
          }

          // Label commentLabel = new Label(comment.getId() + " " + comment.getComment(), true);
          Label commentLabel = new Label(comment.getComment(), true);
          if (comment.isApproved()) {
            commentLabel.setStyleName("comment");
          } else if (userCanManage || userIsAuthorOfComment) {
            commentLabel.setStyleName("commentAwaitingApproval");
          }

          if (commentDepth > 0) {
            HorizontalPanel commentHeaderPanelWrapper = new HorizontalPanel();
            commentHeaderPanelWrapper.setWidth("100%");
            Label spacerLabel = new Label();
            commentHeaderPanelWrapper.add(spacerLabel);
            if (!flatten) {
              commentHeaderPanelWrapper.setCellWidth(spacerLabel, (commentDepth * 20) + "px");
            }
            commentHeaderPanelWrapper.add(commentLabel);
            commentsPanel.add(commentHeaderPanelWrapper);
          } else {
            commentsPanel.add(commentLabel);
          }
          renderedComments++;
        }
      }

      final FlexTable mainPanel = new FlexTable();
      mainPanel.setWidth("100%");
      int row = 0;
      if (paginate) {
        mainPanel.setWidget(row, 0, createButtonPanel(mainPanel, forceOpen));
        mainPanel
            .getCellFormatter()
            .setHorizontalAlignment(row++, 0, HasHorizontalAlignment.ALIGN_LEFT);
      }
      mainPanel.setWidget(row, 0, commentsPanel);
      mainPanel.getCellFormatter().setWidth(row++, 0, "100%");

      commentDisclosurePanel.setContent(mainPanel);
      commentDisclosurePanel.setOpen(renderedComments == 0 || forceOpen);
      commentDisclosurePanel.setWidth("100%");
      add(createCommentPostPanel());
      add(commentDisclosurePanel);
    }
    if (layoutCallback != null) {
      layoutCallback.layoutComplete();
    }
  }