protected KBArticle getKBArticle(long resourcePrimKey, int status) throws Exception {

    KBArticle kbArticle = KBArticleLocalServiceUtil.fetchLatestKBArticle(resourcePrimKey, status);

    if (kbArticle == null) {
      return null;
    }

    PermissionChecker permissionChecker = PermissionThreadLocal.getPermissionChecker();

    if (!KBArticlePermission.contains(permissionChecker, kbArticle, ActionKeys.VIEW)) {

      return null;
    }

    return kbArticle;
  }
  protected PortletURL getKBArticleURL(
      long plid, boolean privateLayout, KBArticle kbArticle, HttpServletRequest request)
      throws Exception {

    PortletURL firstMatchPortletURL = null;

    List<Layout> layouts = getCandidateLayouts(plid, privateLayout, kbArticle);

    for (Layout layout : layouts) {
      LayoutTypePortlet layoutTypePortlet = (LayoutTypePortlet) layout.getLayoutType();

      List<Portlet> portlets = layoutTypePortlet.getAllPortlets();

      for (Portlet portlet : portlets) {
        String rootPortletId = PortletConstants.getRootPortletId(portlet.getPortletId());

        if (rootPortletId.equals(PortletKeys.KNOWLEDGE_BASE_DISPLAY)) {
          PortletPreferences portletPreferences =
              PortletPreferencesFactoryUtil.getPortletSetup(
                  layout, portlet.getPortletId(), StringPool.BLANK);

          long kbFolderClassNameId = PortalUtil.getClassNameId(KBFolderConstants.getClassName());

          long resourceClassNameId =
              GetterUtil.getLong(
                  portletPreferences.getValue("resourceClassNameId", null), kbFolderClassNameId);
          long resourcePrimKey =
              GetterUtil.getLong(
                  portletPreferences.getValue("resourcePrimKey", null),
                  KBFolderConstants.DEFAULT_PARENT_FOLDER_ID);

          if (resourceClassNameId == kbFolderClassNameId) {
            if (isParentFolder(resourcePrimKey, kbArticle.getKbFolderId())) {

              return getKBArticleURL(layout.getPlid(), portlet.getPortletId(), kbArticle, request);
            }
          } else if (resourcePrimKey == kbArticle.getResourcePrimKey()) {

            return getKBArticleURL(layout.getPlid(), portlet.getPortletId(), kbArticle, request);
          }

          if (firstMatchPortletURL == null) {
            firstMatchPortletURL =
                getKBArticleURL(layout.getPlid(), portlet.getPortletId(), kbArticle, request);
          }
        }

        if (rootPortletId.equals(PortletKeys.KNOWLEDGE_BASE_SECTION)) {
          PortletPreferences portletPreferences =
              PortletPreferencesFactoryUtil.getPortletSetup(
                  layout, portlet.getPortletId(), StringPool.BLANK);

          String[] kbArticlesSections =
              portletPreferences.getValues("kbArticlesSections", new String[0]);

          KBArticle rootKBArticle =
              KBArticleLocalServiceUtil.fetchLatestKBArticle(
                  kbArticle.getRootResourcePrimKey(), WorkflowConstants.STATUS_APPROVED);

          if (rootKBArticle == null) {
            continue;
          }

          String[] sections = AdminUtil.unescapeSections(rootKBArticle.getSections());

          for (String section : sections) {
            if (!ArrayUtil.contains(kbArticlesSections, section)) {
              continue;
            }

            return getKBArticleURL(layout.getPlid(), portlet.getPortletId(), kbArticle, request);
          }
        }

        if (rootPortletId.equals(PortletKeys.KNOWLEDGE_BASE_ARTICLE)) {
          PortletPreferences portletPreferences =
              PortletPreferencesFactoryUtil.getPortletSetup(
                  layout, portlet.getPortletId(), StringPool.BLANK);

          long resourcePrimKey =
              GetterUtil.getLong(portletPreferences.getValue("resourcePrimKey", null));

          KBArticle selKBArticle =
              KBArticleLocalServiceUtil.fetchLatestKBArticle(
                  resourcePrimKey, WorkflowConstants.STATUS_APPROVED);

          if (selKBArticle == null) {
            continue;
          }

          long rootResourcePrimKey = kbArticle.getRootResourcePrimKey();
          long selRootResourcePrimKey = selKBArticle.getRootResourcePrimKey();

          if (rootResourcePrimKey == selRootResourcePrimKey) {
            return getKBArticleURL(layout.getPlid(), portlet.getPortletId(), kbArticle, request);
          }

          if (firstMatchPortletURL == null) {
            firstMatchPortletURL =
                getKBArticleURL(layout.getPlid(), portlet.getPortletId(), kbArticle, request);
          }
        }
      }
    }

    return firstMatchPortletURL;
  }
  @Override
  protected void doImportStagedModel(PortletDataContext portletDataContext, KBArticle kbArticle)
      throws Exception {

    long userId = portletDataContext.getUserId(kbArticle.getUserUuid());

    if (kbArticle.getParentResourcePrimKey() != KBFolderConstants.DEFAULT_PARENT_FOLDER_ID) {

      if (kbArticle.getClassNameId() == kbArticle.getParentResourceClassNameId()) {

        StagedModelDataHandlerUtil.importReferenceStagedModels(
            portletDataContext, kbArticle, KBArticle.class);
      } else {
        StagedModelDataHandlerUtil.importReferenceStagedModels(
            portletDataContext, kbArticle, KBFolder.class);
      }
    }

    Map<Long, Long> kbArticleResourcePrimKeys =
        (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(KBArticle.class);

    long parentResourcePrimKey =
        MapUtil.getLong(
            kbArticleResourcePrimKeys,
            kbArticle.getParentResourcePrimKey(),
            KBFolderConstants.DEFAULT_PARENT_FOLDER_ID);

    long resourcePrimaryKey =
        MapUtil.getLong(kbArticleResourcePrimKeys, kbArticle.getResourcePrimKey(), 0);

    if (parentResourcePrimKey == KBFolderConstants.DEFAULT_PARENT_FOLDER_ID) {

      Map<Long, Long> kbFolderResourcePrimKeys =
          (Map<Long, Long>) portletDataContext.getNewPrimaryKeysMap(KBFolder.class);

      parentResourcePrimKey =
          MapUtil.getLong(
              kbFolderResourcePrimKeys,
              kbArticle.getParentResourcePrimKey(),
              KBFolderConstants.DEFAULT_PARENT_FOLDER_ID);
    }

    String[] sections = AdminUtil.unescapeSections(kbArticle.getSections());

    ServiceContext serviceContext = portletDataContext.createServiceContext(kbArticle);

    KBArticle importedKBArticle = null;

    if (portletDataContext.isDataStrategyMirror()) {
      KBArticle existingKBArticle =
          KBArticleUtil.fetchByR_V(resourcePrimaryKey, kbArticle.getVersion());

      if (existingKBArticle == null) {
        existingKBArticle =
            fetchStagedModelByUuidAndGroupId(
                kbArticle.getUuid(), portletDataContext.getScopeGroupId());
      }

      if (existingKBArticle == null) {
        serviceContext.setUuid(kbArticle.getUuid());

        existingKBArticle =
            KBArticleLocalServiceUtil.fetchLatestKBArticle(
                resourcePrimaryKey, WorkflowConstants.STATUS_ANY);

        if (existingKBArticle == null) {
          importedKBArticle =
              KBArticleLocalServiceUtil.addKBArticle(
                  userId,
                  kbArticle.getParentResourceClassNameId(),
                  parentResourcePrimKey,
                  kbArticle.getTitle(),
                  kbArticle.getUrlTitle(),
                  kbArticle.getContent(),
                  kbArticle.getDescription(),
                  kbArticle.getSourceURL(),
                  sections,
                  null,
                  serviceContext);

          KBArticleLocalServiceUtil.updatePriority(
              importedKBArticle.getResourcePrimKey(), kbArticle.getPriority());
        } else {
          KBArticleLocalServiceUtil.updateKBArticle(
              userId,
              existingKBArticle.getResourcePrimKey(),
              kbArticle.getTitle(),
              kbArticle.getContent(),
              kbArticle.getDescription(),
              kbArticle.getSourceURL(),
              sections,
              null,
              null,
              serviceContext);

          KBArticleLocalServiceUtil.moveKBArticle(
              userId,
              existingKBArticle.getResourcePrimKey(),
              existingKBArticle.getParentResourceClassNameId(),
              parentResourcePrimKey,
              kbArticle.getPriority());

          importedKBArticle =
              KBArticleLocalServiceUtil.getLatestKBArticle(
                  existingKBArticle.getResourcePrimKey(), WorkflowConstants.STATUS_APPROVED);
        }
      } else {
        importedKBArticle = existingKBArticle;
      }
    } else {
      importedKBArticle =
          KBArticleLocalServiceUtil.addKBArticle(
              userId,
              kbArticle.getParentResourceClassNameId(),
              parentResourcePrimKey,
              kbArticle.getTitle(),
              kbArticle.getUrlTitle(),
              kbArticle.getContent(),
              kbArticle.getDescription(),
              kbArticle.getSourceURL(),
              sections,
              null,
              serviceContext);

      KBArticleLocalServiceUtil.updatePriority(
          importedKBArticle.getResourcePrimKey(), kbArticle.getPriority());
    }

    importKBArticleAttachments(portletDataContext, kbArticle, importedKBArticle);

    portletDataContext.importClassedModel(kbArticle, importedKBArticle);

    if (!kbArticle.isMain()) {
      kbArticleResourcePrimKeys.put(
          kbArticle.getResourcePrimKey(), importedKBArticle.getResourcePrimKey());
    }
  }
  protected Tuple getResourceTuple(RenderRequest renderRequest) throws Exception {

    ThemeDisplay themeDisplay = (ThemeDisplay) renderRequest.getAttribute(WebKeys.THEME_DISPLAY);

    String urlTitle = ParamUtil.getString(renderRequest, "urlTitle");

    if (Validator.isNotNull(urlTitle)) {
      String kbFolderUrlTitle = ParamUtil.getString(renderRequest, "kbFolderUrlTitle");

      KBArticle kbArticle = null;

      if (Validator.isNotNull(kbFolderUrlTitle)) {
        kbArticle =
            KBArticleLocalServiceUtil.fetchKBArticleByUrlTitle(
                themeDisplay.getScopeGroupId(), kbFolderUrlTitle, urlTitle);
      } else {
        kbArticle =
            KBArticleLocalServiceUtil.fetchKBArticleByUrlTitle(
                themeDisplay.getScopeGroupId(),
                KBFolderConstants.DEFAULT_PARENT_FOLDER_ID,
                urlTitle);
      }

      if ((kbArticle != null)
          && KBArticlePermission.contains(
              themeDisplay.getPermissionChecker(), kbArticle, ActionKeys.VIEW)) {

        return new Tuple(kbArticle.getClassNameId(), kbArticle.getResourcePrimKey());
      }
    }

    PortletPreferences portletPreferences = renderRequest.getPreferences();

    long defaultResourcePrimKey =
        GetterUtil.getLong(portletPreferences.getValue("resourcePrimKey", null));

    String mvcPath = ParamUtil.getString(renderRequest, "mvcPath");

    if (((defaultResourcePrimKey == 0) && mvcPath.equals(viewTemplate))
        || mvcPath.equals("/display/select_configuration_article.jsp")) {

      return new Tuple(
          PortalUtil.getClassNameId(KBFolderConstants.getClassName()),
          KBFolderConstants.DEFAULT_PARENT_FOLDER_ID);
    }

    long defaultResourceClassNameId =
        GetterUtil.getLong(portletPreferences.getValue("resourceClassNameId", null));

    long resourceClassNameId =
        ParamUtil.getLong(renderRequest, "resourceClassNameId", defaultResourceClassNameId);

    long resourcePrimKey =
        ParamUtil.getLong(renderRequest, "resourcePrimKey", defaultResourcePrimKey);

    if ((resourcePrimKey == 0) || (resourcePrimKey != defaultResourcePrimKey)) {

      return new Tuple(resourceClassNameId, resourcePrimKey);
    }

    long kbFolderClassNameId = PortalUtil.getClassNameId(KBFolderConstants.getClassName());

    if (resourceClassNameId == kbFolderClassNameId) {
      KBFolder kbFolder = KBFolderLocalServiceUtil.fetchKBFolder(resourcePrimKey);

      if ((kbFolder != null)
          && !KBFolderPermission.contains(
              themeDisplay.getPermissionChecker(),
              themeDisplay.getScopeGroupId(),
              defaultResourcePrimKey,
              ActionKeys.VIEW)) {

        return new Tuple(
            PortalUtil.getClassNameId(KBFolderConstants.getClassName()),
            KBFolderConstants.DEFAULT_PARENT_FOLDER_ID);
      }
    } else {
      KBArticle kbArticle =
          KBArticleLocalServiceUtil.fetchLatestKBArticle(
              defaultResourcePrimKey, WorkflowConstants.STATUS_ANY);

      if ((kbArticle != null)
          && !KBArticlePermission.contains(
              themeDisplay.getPermissionChecker(), defaultResourcePrimKey, ActionKeys.VIEW)) {

        return new Tuple(
            PortalUtil.getClassNameId(KBFolderConstants.getClassName()),
            KBFolderConstants.DEFAULT_PARENT_FOLDER_ID);
      }
    }

    return new Tuple(defaultResourceClassNameId, defaultResourcePrimKey);
  }