public void updateKBArticleAsset(
      long userId, KBArticle kbArticle, long[] assetCategoryIds, String[] assetTagNames)
      throws PortalException, SystemException {
    // TBD
    long classTypeId = 0;

    assetEntryLocalService.updateEntry(
        userId,
        kbArticle.getGroupId(),
        KBArticle.class.getName(),
        kbArticle.getClassPK(),
        kbArticle.getUuid(),
        classTypeId,
        assetCategoryIds,
        assetTagNames,
        false,
        null,
        null,
        null,
        null,
        ContentTypes.TEXT_HTML,
        kbArticle.getTitle(),
        kbArticle.getDescription(),
        null,
        null,
        null,
        0,
        0,
        null,
        false);
  }
  @Override
  protected Document doGetDocument(Object obj) throws Exception {
    KBArticle kbArticle = (KBArticle) obj;

    Document document = getBaseModelDocument(PORTLET_ID, kbArticle);

    document.addText(Field.CONTENT, HtmlUtil.extractText(kbArticle.getContent()));
    document.addText(Field.DESCRIPTION, kbArticle.getDescription());
    document.addText(Field.TITLE, kbArticle.getTitle());

    document.addKeyword("titleKeyword", kbArticle.getTitle(), true);

    return document;
  }
  protected KBArticle addKBArticleMarkdown(
      long userId,
      long groupId,
      long parentResourcePrimaryKey,
      String markdown,
      String fileEntryName,
      ZipReader zipReader,
      Map<String, String> metadata,
      ServiceContext serviceContext)
      throws KBArticleImportException {

    if (Validator.isNull(markdown)) {
      throw new KBArticleImportException("Markdown is null for file entry " + fileEntryName);
    }

    KBArticleMarkdownConverter kbArticleMarkdownConverter =
        new KBArticleMarkdownConverter(markdown, fileEntryName, metadata);

    String urlTitle = kbArticleMarkdownConverter.getUrlTitle();

    KBArticle kbArticle = KBArticleLocalServiceUtil.fetchKBArticleByUrlTitle(groupId, urlTitle);

    try {
      if (kbArticle == null) {
        kbArticle =
            KBArticleLocalServiceUtil.addKBArticle(
                userId,
                parentResourcePrimaryKey,
                kbArticleMarkdownConverter.getTitle(),
                urlTitle,
                markdown,
                null,
                kbArticleMarkdownConverter.getSourceURL(),
                null,
                null,
                serviceContext);
      }
    } catch (Exception e) {
      StringBundler sb = new StringBundler(4);

      sb.append("Unable to add basic KB article for file entry ");
      sb.append(fileEntryName);
      sb.append(": ");
      sb.append(e.getLocalizedMessage());

      throw new KBArticleImportException(sb.toString(), e);
    }

    try {
      String html =
          kbArticleMarkdownConverter.processAttachmentsReferences(
              userId, kbArticle, zipReader, new HashMap<String, FileEntry>());

      return KBArticleLocalServiceUtil.updateKBArticle(
          userId,
          kbArticle.getResourcePrimKey(),
          kbArticleMarkdownConverter.getTitle(),
          html,
          kbArticle.getDescription(),
          kbArticleMarkdownConverter.getSourceURL(),
          null,
          null,
          null,
          serviceContext);
    } catch (Exception e) {
      StringBundler sb = new StringBundler(4);

      sb.append("Unable to update KB article for file entry ");
      sb.append(fileEntryName);
      sb.append(": ");
      sb.append(e.getLocalizedMessage());

      throw new KBArticleImportException(sb.toString(), e);
    }
  }
  @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());
    }
  }