@Override
  public boolean include(HttpServletRequest request, HttpServletResponse response, String template)
      throws Exception {

    MBMessageDisplay messageDisplay =
        MBMessageServiceUtil.getMessageDisplay(
            _rootMessage.getMessageId(),
            WorkflowConstants.STATUS_ANY,
            MBThreadConstants.THREAD_VIEW_TREE,
            false);

    request.setAttribute(WebKeys.MESSAGE_BOARDS_MESSAGE, messageDisplay);

    MBTreeWalker treeWalker = messageDisplay.getTreeWalker();

    request.setAttribute(WebKeys.MESSAGE_BOARDS_TREE_WALKER, treeWalker);
    request.setAttribute(WebKeys.MESSAGE_BOARDS_TREE_WALKER_CATEGORY, messageDisplay.getCategory());
    request.setAttribute(WebKeys.MESSAGE_BOARDS_TREE_WALKER_CUR_MESSAGE, treeWalker.getRoot());
    request.setAttribute(WebKeys.MESSAGE_BOARDS_TREE_WALKER_DEPTH, Integer.valueOf(0));
    request.setAttribute(WebKeys.MESSAGE_BOARDS_TREE_WALKER_LAST_NODE, Boolean.FALSE);
    request.setAttribute(WebKeys.MESSAGE_BOARDS_TREE_WALKER_SEL_MESSAGE, _rootMessage);
    request.setAttribute(WebKeys.MESSAGE_BOARDS_TREE_WALKER_THREAD, messageDisplay.getThread());

    return super.include(request, response, template);
  }
  @Override
  public long addComment(
      long userId,
      long groupId,
      String className,
      long classPK,
      String userName,
      String subject,
      String body,
      Function<String, ServiceContext> serviceContextFunction)
      throws PortalException {

    MBMessageDisplay mbMessageDisplay =
        _mbMessageLocalService.getDiscussionMessageDisplay(
            userId, groupId, className, classPK, WorkflowConstants.STATUS_APPROVED);

    MBThread mbThread = mbMessageDisplay.getThread();

    ServiceContext serviceContext = serviceContextFunction.apply(MBMessage.class.getName());

    MBMessage mbMessage =
        _mbMessageLocalService.addDiscussionMessage(
            userId,
            userName,
            groupId,
            className,
            classPK,
            mbThread.getThreadId(),
            mbThread.getRootMessageId(),
            subject,
            body,
            serviceContext);

    return mbMessage.getMessageId();
  }
  @Override
  public void addComment(
      long userId,
      long groupId,
      String className,
      long classPK,
      String body,
      ServiceContext serviceContext)
      throws PortalException {

    MBMessageDisplay messageDisplay =
        _mbMessageLocalService.getDiscussionMessageDisplay(
            userId, groupId, className, classPK, WorkflowConstants.STATUS_APPROVED);

    MBThread thread = messageDisplay.getThread();

    List<MBMessage> messages =
        _mbMessageLocalService.getThreadMessages(
            thread.getThreadId(), WorkflowConstants.STATUS_APPROVED);

    for (MBMessage message : messages) {
      String messageBody = message.getBody();

      if (messageBody.equals(body)) {
        throw new DuplicateCommentException();
      }
    }

    _mbMessageLocalService.addDiscussionMessage(
        userId,
        StringPool.BLANK,
        groupId,
        className,
        classPK,
        thread.getThreadId(),
        thread.getRootMessageId(),
        StringPool.BLANK,
        body,
        serviceContext);
  }
  @Override
  public MBThread splitThread(long messageId, String subject, ServiceContext serviceContext)
      throws PortalException, SystemException {

    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);

    if (message.isRoot()) {
      throw new SplitThreadException();
    }

    MBCategory category = message.getCategory();
    MBThread oldThread = message.getThread();
    MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(oldThread.getRootMessageId());

    // Message flags

    mbMessageLocalService.updateAnswer(message, false, true);

    // Create new thread

    MBThread thread = addThread(message.getCategoryId(), message, serviceContext);

    oldThread.setModifiedDate(serviceContext.getModifiedDate(new Date()));

    mbThreadPersistence.update(oldThread);

    // Update messages

    if (Validator.isNotNull(subject)) {
      MBMessageDisplay messageDisplay =
          mbMessageService.getMessageDisplay(
              messageId, WorkflowConstants.STATUS_ANY, MBThreadConstants.THREAD_VIEW_TREE, false);

      MBTreeWalker treeWalker = messageDisplay.getTreeWalker();

      List<MBMessage> messages = treeWalker.getMessages();

      int[] range = treeWalker.getChildrenRange(message);

      for (int i = range[0]; i < range[1]; i++) {
        MBMessage curMessage = messages.get(i);

        String oldSubject = message.getSubject();
        String curSubject = curMessage.getSubject();

        if (oldSubject.startsWith("RE: ")) {
          curSubject = StringUtil.replace(curSubject, rootMessage.getSubject(), subject);
        } else {
          curSubject = StringUtil.replace(curSubject, oldSubject, subject);
        }

        curMessage.setSubject(curSubject);

        mbMessagePersistence.update(curMessage);
      }

      message.setSubject(subject);
    }

    message.setThreadId(thread.getThreadId());
    message.setRootMessageId(thread.getRootMessageId());
    message.setParentMessageId(0);

    mbMessagePersistence.update(message);

    // Indexer

    if (!message.isDiscussion()) {
      Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(MBMessage.class);

      indexer.reindex(message);
    }

    // Update children

    moveChildrenMessages(message, category, oldThread.getThreadId());

    // Update new thread

    MBUtil.updateThreadMessageCount(thread.getCompanyId(), thread.getThreadId());

    // Update old thread

    MBUtil.updateThreadMessageCount(oldThread.getCompanyId(), oldThread.getThreadId());

    // Category

    if ((message.getCategoryId() != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID)
        && (message.getCategoryId() != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {

      MBUtil.updateCategoryThreadCount(category.getCompanyId(), category.getCategoryId());
    }

    return thread;
  }