com.liferay.journal.search.JournalArticleIndexer.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.journal.search.JournalArticleIndexer.java

Source

/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.journal.search;

import com.liferay.dynamic.data.mapping.model.DDMStructure;
import com.liferay.dynamic.data.mapping.service.DDMStructureLocalService;
import com.liferay.dynamic.data.mapping.storage.DDMFormValues;
import com.liferay.dynamic.data.mapping.storage.Fields;
import com.liferay.dynamic.data.mapping.util.DDMIndexer;
import com.liferay.dynamic.data.mapping.util.FieldsToDDMFormValuesConverter;
import com.liferay.journal.configuration.JournalServiceConfiguration;
import com.liferay.journal.model.JournalArticle;
import com.liferay.journal.model.JournalArticleDisplay;
import com.liferay.journal.model.JournalArticleResource;
import com.liferay.journal.service.JournalArticleLocalService;
import com.liferay.journal.service.JournalArticleResourceLocalService;
import com.liferay.journal.service.permission.JournalArticlePermission;
import com.liferay.journal.util.JournalContent;
import com.liferay.journal.util.JournalConverter;
import com.liferay.journal.util.impl.JournalUtil;
import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
import com.liferay.portal.kernel.dao.orm.DynamicQuery;
import com.liferay.portal.kernel.dao.orm.IndexableActionableDynamicQuery;
import com.liferay.portal.kernel.dao.orm.Property;
import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.module.configuration.ConfigurationProvider;
import com.liferay.portal.kernel.portlet.PortletRequestModel;
import com.liferay.portal.kernel.search.BaseIndexer;
import com.liferay.portal.kernel.search.BooleanClauseOccur;
import com.liferay.portal.kernel.search.BooleanQuery;
import com.liferay.portal.kernel.search.DDMStructureIndexer;
import com.liferay.portal.kernel.search.Document;
import com.liferay.portal.kernel.search.DocumentImpl;
import com.liferay.portal.kernel.search.Field;
import com.liferay.portal.kernel.search.IndexWriterHelper;
import com.liferay.portal.kernel.search.Indexer;
import com.liferay.portal.kernel.search.IndexerRegistry;
import com.liferay.portal.kernel.search.Query;
import com.liferay.portal.kernel.search.SearchContext;
import com.liferay.portal.kernel.search.SearchException;
import com.liferay.portal.kernel.search.Summary;
import com.liferay.portal.kernel.search.filter.BooleanFilter;
import com.liferay.portal.kernel.search.filter.QueryFilter;
import com.liferay.portal.kernel.search.generic.BooleanQueryImpl;
import com.liferay.portal.kernel.security.auth.CompanyThreadLocal;
import com.liferay.portal.kernel.security.permission.ActionKeys;
import com.liferay.portal.kernel.security.permission.PermissionChecker;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.Constants;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.HtmlUtil;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.LocalizationUtil;
import com.liferay.portal.kernel.util.Portal;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.kernel.workflow.WorkflowConstants;
import com.liferay.portal.search.index.IndexStatusManager;
import com.liferay.trash.kernel.util.TrashUtil;

import java.io.Serializable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.portlet.PortletRequest;
import javax.portlet.PortletResponse;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

/**
 * @author Brian Wing Shun Chan
 * @author Harry Mark
 * @author Bruno Farache
 * @author Raymond Aug
 * @author Hugo Huijser
 * @author Tibor Lipusz
 */
@Component(immediate = true, service = Indexer.class)
public class JournalArticleIndexer extends BaseIndexer<JournalArticle> implements DDMStructureIndexer {

    public static final String CLASS_NAME = JournalArticle.class.getName();

    public JournalArticleIndexer() {
        setDefaultSelectedFieldNames(Field.ASSET_TAG_NAMES, Field.ARTICLE_ID, Field.COMPANY_ID,
                Field.DEFAULT_LANGUAGE_ID, Field.ENTRY_CLASS_NAME, Field.ENTRY_CLASS_PK, Field.GROUP_ID,
                Field.MODIFIED_DATE, Field.SCOPE_GROUP_ID, Field.VERSION, Field.UID);
        setDefaultSelectedLocalizedFieldNames(Field.CONTENT, Field.DESCRIPTION, Field.TITLE);
        setFilterSearch(true);
        setPermissionAware(true);
        setSelectAllLocales(true);
    }

    @Override
    public String getClassName() {
        return CLASS_NAME;
    }

    @Override
    public boolean hasPermission(PermissionChecker permissionChecker, String entryClassName, long entryClassPK,
            String actionId) throws Exception {

        return JournalArticlePermission.contains(permissionChecker, entryClassPK, ActionKeys.VIEW);
    }

    @Override
    public boolean isVisible(long classPK, int status) throws Exception {
        List<JournalArticle> articles = _journalArticleLocalService.getArticlesByResourcePrimKey(classPK);

        for (JournalArticle article : articles) {
            if (isVisible(article.getStatus(), status)) {
                return true;
            }
        }

        return false;
    }

    @Override
    public void postProcessContextBooleanFilter(BooleanFilter contextBooleanFilter, SearchContext searchContext)
            throws Exception {

        Long classNameId = (Long) searchContext.getAttribute(Field.CLASS_NAME_ID);

        if ((classNameId != null) && (classNameId != 0)) {
            contextBooleanFilter.addRequiredTerm(Field.CLASS_NAME_ID, classNameId.toString());
        }

        addStatus(contextBooleanFilter, searchContext);

        addSearchClassTypeIds(contextBooleanFilter, searchContext);

        String ddmStructureFieldName = (String) searchContext.getAttribute("ddmStructureFieldName");
        Serializable ddmStructureFieldValue = searchContext.getAttribute("ddmStructureFieldValue");

        if (Validator.isNotNull(ddmStructureFieldName) && Validator.isNotNull(ddmStructureFieldValue)) {

            QueryFilter queryFilter = _ddmIndexer.createFieldValueQueryFilter(ddmStructureFieldName,
                    ddmStructureFieldValue, searchContext.getLocale());

            contextBooleanFilter.add(queryFilter, BooleanClauseOccur.MUST);
        }

        String ddmStructureKey = (String) searchContext.getAttribute("ddmStructureKey");

        if (Validator.isNotNull(ddmStructureKey)) {
            contextBooleanFilter.addRequiredTerm("ddmStructureKey", ddmStructureKey);
        }

        String ddmTemplateKey = (String) searchContext.getAttribute("ddmTemplateKey");

        if (Validator.isNotNull(ddmTemplateKey)) {
            contextBooleanFilter.addRequiredTerm("ddmTemplateKey", ddmTemplateKey);
        }

        boolean head = GetterUtil.getBoolean(searchContext.getAttribute("head"), Boolean.TRUE);
        boolean relatedClassName = GetterUtil.getBoolean(searchContext.getAttribute("relatedClassName"));
        boolean showNonindexable = GetterUtil.getBoolean(searchContext.getAttribute("showNonindexable"));

        if (head && !relatedClassName && !showNonindexable) {
            contextBooleanFilter.addRequiredTerm("head", Boolean.TRUE);
        }

        if (!relatedClassName && showNonindexable) {
            contextBooleanFilter.addRequiredTerm("headListable", Boolean.TRUE);
        }
    }

    @Override
    public void postProcessSearchQuery(BooleanQuery searchQuery, BooleanFilter fullQueryBooleanFilter,
            SearchContext searchContext) throws Exception {

        addSearchTerm(searchQuery, searchContext, Field.ARTICLE_ID, false);
        addSearchTerm(searchQuery, searchContext, Field.CLASS_PK, false);
        addSearchLocalizedTerm(searchQuery, searchContext, Field.CONTENT, false);
        addSearchLocalizedTerm(searchQuery, searchContext, Field.DESCRIPTION, false);
        addSearchTerm(searchQuery, searchContext, Field.ENTRY_CLASS_PK, false);
        addSearchLocalizedTerm(searchQuery, searchContext, Field.TITLE, false);
        addSearchTerm(searchQuery, searchContext, Field.USER_NAME, false);

        LinkedHashMap<String, Object> params = (LinkedHashMap<String, Object>) searchContext.getAttribute("params");

        if (params != null) {
            String expandoAttributes = (String) params.get("expandoAttributes");

            if (Validator.isNotNull(expandoAttributes)) {
                addSearchExpando(searchQuery, searchContext, expandoAttributes);
            }
        }
    }

    @Override
    public void reindexDDMStructures(List<Long> ddmStructureIds) throws SearchException {

        if (_indexStatusManager.isIndexReadOnly() || !isIndexerEnabled()) {
            return;
        }

        try {
            final String[] ddmStructureKeys = new String[ddmStructureIds.size()];

            for (int i = 0; i < ddmStructureIds.size(); i++) {
                long ddmStructureId = ddmStructureIds.get(i);

                DDMStructure ddmStructure = _ddmStructureLocalService.getDDMStructure(ddmStructureId);

                ddmStructureKeys[i] = ddmStructure.getStructureKey();
            }

            final Indexer<JournalArticle> indexer = _indexerRegistry.nullSafeGetIndexer(JournalArticle.class);

            final ActionableDynamicQuery actionableDynamicQuery = _journalArticleLocalService
                    .getActionableDynamicQuery();

            actionableDynamicQuery.setAddCriteriaMethod(new ActionableDynamicQuery.AddCriteriaMethod() {

                @Override
                public void addCriteria(DynamicQuery dynamicQuery) {
                    Property ddmStructureKey = PropertyFactoryUtil.forName("DDMStructureKey");

                    dynamicQuery.add(ddmStructureKey.in(ddmStructureKeys));

                    if (!isIndexAllArticleVersions()) {
                        Property statusProperty = PropertyFactoryUtil.forName("status");

                        Integer[] statuses = { WorkflowConstants.STATUS_APPROVED,
                                WorkflowConstants.STATUS_IN_TRASH };

                        dynamicQuery.add(statusProperty.in(statuses));
                    }
                }

            });
            actionableDynamicQuery
                    .setPerformActionMethod(new ActionableDynamicQuery.PerformActionMethod<JournalArticle>() {

                        @Override
                        public void performAction(JournalArticle article) throws PortalException {

                            try {
                                indexer.reindex(indexer.getClassName(), article.getResourcePrimKey());
                            } catch (Exception e) {
                                throw new PortalException(e);
                            }
                        }

                    });

            actionableDynamicQuery.performActions();
        } catch (Exception e) {
            throw new SearchException(e);
        }
    }

    protected void addDDMStructureAttributes(Document document, JournalArticle article) throws Exception {

        DDMStructure ddmStructure = _ddmStructureLocalService.fetchStructure(article.getGroupId(),
                _portal.getClassNameId(JournalArticle.class), article.getDDMStructureKey(), true);

        if (ddmStructure == null) {
            return;
        }

        document.addKeyword(Field.CLASS_TYPE_ID, ddmStructure.getStructureId());

        DDMFormValues ddmFormValues = null;

        try {
            Fields fields = _journalConverter.getDDMFields(ddmStructure, article.getDocument());

            ddmFormValues = _fieldsToDDMFormValuesConverter.convert(ddmStructure, fields);
        } catch (Exception e) {
            return;
        }

        if (ddmFormValues != null) {
            _ddmIndexer.addAttributes(document, ddmStructure, ddmFormValues);
        }
    }

    @Override
    protected Map<String, Query> addSearchLocalizedTerm(BooleanQuery searchQuery, SearchContext searchContext,
            String field, boolean like) throws Exception {

        if (Validator.isNull(field)) {
            return Collections.emptyMap();
        }

        String value = String.valueOf(searchContext.getAttribute(field));

        if (Validator.isNull(value)) {
            value = searchContext.getKeywords();
        }

        if (Validator.isNull(value)) {
            return Collections.emptyMap();
        }

        String localizedField = DocumentImpl.getLocalizedName(searchContext.getLocale(), field);

        Map<String, Query> queries = new HashMap<>();

        if (Validator.isNull(searchContext.getKeywords())) {
            BooleanQuery localizedQuery = new BooleanQueryImpl();

            Query query = localizedQuery.addTerm(field, value, like);

            queries.put(field, query);

            Query localizedFieldQuery = localizedQuery.addTerm(localizedField, value, like);

            queries.put(field, localizedFieldQuery);

            BooleanClauseOccur booleanClauseOccur = BooleanClauseOccur.SHOULD;

            if (searchContext.isAndSearch()) {
                booleanClauseOccur = BooleanClauseOccur.MUST;
            }

            searchQuery.add(localizedQuery, booleanClauseOccur);
        } else {
            Query query = searchQuery.addTerm(localizedField, value, like);

            queries.put(field, query);
        }

        return queries;
    }

    @Override
    protected void doDelete(JournalArticle journalArticle) throws Exception {
        long classPK = journalArticle.getId();

        if (!isIndexAllArticleVersions()) {
            if (_journalArticleLocalService.getArticlesCount(journalArticle.getGroupId(),
                    journalArticle.getArticleId()) > 0) {

                doReindex(journalArticle);

                return;
            } else {
                classPK = journalArticle.getResourcePrimKey();
            }
        }

        deleteDocument(journalArticle.getCompanyId(), classPK);

        if (!journalArticle.isApproved()) {
            return;
        }

        JournalArticle latestIndexableArticle = _journalArticleLocalService
                .fetchLatestIndexableArticle(journalArticle.getResourcePrimKey());

        if ((latestIndexableArticle == null)
                || (latestIndexableArticle.getVersion() > journalArticle.getVersion())) {

            return;
        }

        _indexWriterHelper.updateDocument(getSearchEngineId(), journalArticle.getCompanyId(),
                getDocument(latestIndexableArticle), isCommitImmediately());
    }

    @Override
    protected Document doGetDocument(JournalArticle journalArticle) throws Exception {

        Document document = getBaseModelDocument(CLASS_NAME, journalArticle);

        long classPK = journalArticle.getId();

        if (!isIndexAllArticleVersions()) {
            classPK = journalArticle.getResourcePrimKey();
        }

        document.addUID(CLASS_NAME, classPK);

        String articleDefaultLanguageId = LocalizationUtil.getDefaultLanguageId(journalArticle.getDocument());

        String[] languageIds = LocalizationUtil.getAvailableLanguageIds(journalArticle.getDocument());

        for (String languageId : languageIds) {
            String content = extractDDMContent(journalArticle, languageId);

            String description = journalArticle.getDescription(languageId);

            String title = journalArticle.getTitle(languageId);

            if (languageId.equals(articleDefaultLanguageId)) {
                document.addText(Field.CONTENT, content);
                document.addText(Field.DESCRIPTION, description);
                document.addText("defaultLanguageId", languageId);
            }

            document.addText(LocalizationUtil.getLocalizedName(Field.CONTENT, languageId), content);
            document.addText(LocalizationUtil.getLocalizedName(Field.DESCRIPTION, languageId), description);
            document.addText(LocalizationUtil.getLocalizedName(Field.TITLE, languageId), title);
        }

        document.addKeyword(Field.FOLDER_ID, journalArticle.getFolderId());

        String articleId = journalArticle.getArticleId();

        if (journalArticle.isInTrash()) {
            articleId = TrashUtil.getOriginalTitle(articleId);
        }

        document.addKeywordSortable(Field.ARTICLE_ID, articleId);

        document.addKeyword(Field.LAYOUT_UUID, journalArticle.getLayoutUuid());
        document.addKeyword(Field.TREE_PATH, StringUtil.split(journalArticle.getTreePath(), CharPool.SLASH));
        document.addKeyword(Field.VERSION, journalArticle.getVersion());

        document.addKeyword("ddmStructureKey", journalArticle.getDDMStructureKey());
        document.addKeyword("ddmTemplateKey", journalArticle.getDDMTemplateKey());
        document.addDate("displayDate", journalArticle.getDisplayDate());
        document.addKeyword("head", JournalUtil.isHead(journalArticle));

        boolean headListable = JournalUtil.isHeadListable(journalArticle);

        document.addKeyword("headListable", headListable);

        // Scheduled listable articles should be visible in asset browser

        if (journalArticle.isScheduled() && headListable) {
            boolean visible = GetterUtil.getBoolean(document.get("visible"));

            if (!visible) {
                document.addKeyword("visible", true);
            }
        }

        addDDMStructureAttributes(document, journalArticle);

        return document;
    }

    @Override
    protected String doGetSortField(String orderByCol) {
        if (orderByCol.equals("display-date")) {
            return "displayDate";
        } else if (orderByCol.equals("id")) {
            return Field.ENTRY_CLASS_PK;
        } else if (orderByCol.equals("modified-date")) {
            return Field.MODIFIED_DATE;
        } else if (orderByCol.equals("title")) {
            return Field.TITLE;
        } else {
            return orderByCol;
        }
    }

    @Override
    protected Summary doGetSummary(Document document, Locale locale, String snippet, PortletRequest portletRequest,
            PortletResponse portletResponse) {

        Locale defaultLocale = LocaleUtil.fromLanguageId(document.get("defaultLanguageId"));

        Locale snippetLocale = getSnippetLocale(document, locale);

        String localizedTitleName = DocumentImpl.getLocalizedName(locale, Field.TITLE);

        if ((snippetLocale == null) && (document.getField(localizedTitleName) == null)) {

            snippetLocale = defaultLocale;
        } else {
            snippetLocale = locale;
        }

        String title = document.get(snippetLocale, Field.SNIPPET + StringPool.UNDERLINE + Field.TITLE, Field.TITLE);

        if (Validator.isNull(title) && !snippetLocale.equals(defaultLocale)) {
            title = document.get(defaultLocale, Field.SNIPPET + StringPool.UNDERLINE + Field.TITLE, Field.TITLE);
        }

        String content = getDDMContentSummary(document, snippetLocale, portletRequest, portletResponse);

        if (Validator.isNull(content) && !snippetLocale.equals(defaultLocale)) {
            content = getDDMContentSummary(document, defaultLocale, portletRequest, portletResponse);
        }

        Summary summary = new Summary(snippetLocale, title, content);

        summary.setMaxContentLength(200);

        return summary;
    }

    @Override
    protected void doReindex(JournalArticle article) throws Exception {
        if (_portal.getClassNameId(DDMStructure.class) == article.getClassNameId()) {

            Document document = getDocument(article);

            _indexWriterHelper.deleteDocument(getSearchEngineId(), article.getCompanyId(), document.get(Field.UID),
                    isCommitImmediately());

            return;
        }

        reindexArticleVersions(article);
    }

    @Override
    protected void doReindex(String className, long classPK) throws Exception {
        JournalArticle article = _journalArticleLocalService.fetchJournalArticle(classPK);

        if (article == null) {
            article = _journalArticleLocalService.fetchLatestArticle(classPK);
        }

        if (article != null) {
            doReindex(article);
        }
    }

    @Override
    protected void doReindex(String[] ids) throws Exception {
        long companyId = GetterUtil.getLong(ids[0]);

        reindexArticles(companyId);
    }

    protected String extractDDMContent(JournalArticle article, String languageId) throws Exception {

        DDMStructure ddmStructure = _ddmStructureLocalService.fetchStructure(article.getGroupId(),
                _portal.getClassNameId(JournalArticle.class), article.getDDMStructureKey(), true);

        if (ddmStructure == null) {
            return StringPool.BLANK;
        }

        DDMFormValues ddmFormValues = null;

        try {
            Fields fields = _journalConverter.getDDMFields(ddmStructure, article.getDocument());

            ddmFormValues = _fieldsToDDMFormValuesConverter.convert(ddmStructure, fields);
        } catch (Exception e) {
            return StringPool.BLANK;
        }

        if (ddmFormValues == null) {
            return StringPool.BLANK;
        }

        return _ddmIndexer.extractIndexableAttributes(ddmStructure, ddmFormValues,
                LocaleUtil.fromLanguageId(languageId));
    }

    protected JournalArticle fetchLatestIndexableArticleVersion(long resourcePrimKey) {

        JournalArticle latestIndexableArticle = _journalArticleLocalService.fetchLatestArticle(resourcePrimKey,
                new int[] { WorkflowConstants.STATUS_APPROVED, WorkflowConstants.STATUS_IN_TRASH });

        if (latestIndexableArticle == null) {
            latestIndexableArticle = _journalArticleLocalService.fetchLatestArticle(resourcePrimKey);
        }

        return latestIndexableArticle;
    }

    protected Collection<Document> getArticleVersions(JournalArticle article) throws PortalException {

        Collection<Document> documents = new ArrayList<>();

        List<JournalArticle> articles = null;

        if (isIndexAllArticleVersions()) {
            articles = _journalArticleLocalService.getArticlesByResourcePrimKey(article.getResourcePrimKey());
        } else {
            articles = new ArrayList<>();

            JournalArticle latestIndexableArticle = fetchLatestIndexableArticleVersion(
                    article.getResourcePrimKey());

            if (latestIndexableArticle != null) {
                articles.add(latestIndexableArticle);
            }
        }

        for (JournalArticle curArticle : articles) {
            Document document = getDocument(curArticle);

            documents.add(document);
        }

        return documents;
    }

    protected String getDDMContentSummary(Document document, Locale snippetLocale, PortletRequest portletRequest,
            PortletResponse portletResponse) {

        String content = StringPool.BLANK;

        if ((portletRequest == null) || (portletResponse == null)) {
            return content;
        }

        try {
            String articleId = document.get(Field.ARTICLE_ID);
            long groupId = GetterUtil.getLong(document.get(Field.GROUP_ID));
            double version = GetterUtil.getDouble(document.get(Field.VERSION));
            PortletRequestModel portletRequestModel = new PortletRequestModel(portletRequest, portletResponse);
            ThemeDisplay themeDisplay = (ThemeDisplay) portletRequest.getAttribute(WebKeys.THEME_DISPLAY);

            JournalArticleDisplay articleDisplay = _journalContent.getDisplay(groupId, articleId, version, null,
                    Constants.VIEW, LocaleUtil.toLanguageId(snippetLocale), 1, portletRequestModel, themeDisplay);

            content = articleDisplay.getDescription();

            content = HtmlUtil.replaceNewLine(content);

            if (Validator.isNull(content)) {
                content = HtmlUtil.extractText(articleDisplay.getContent());
            }
        } catch (Exception e) {
            if (_log.isDebugEnabled()) {
                _log.debug(e, e);
            }
        }

        return content;
    }

    protected boolean isIndexAllArticleVersions() {
        JournalServiceConfiguration journalServiceConfiguration = null;

        try {
            journalServiceConfiguration = _configurationProvider
                    .getCompanyConfiguration(JournalServiceConfiguration.class, CompanyThreadLocal.getCompanyId());

            return journalServiceConfiguration.indexAllArticleVersionsEnabled();
        } catch (Exception e) {
            _log.error(e, e);
        }

        return false;
    }

    protected void reindexArticles(long companyId) throws PortalException {
        final IndexableActionableDynamicQuery indexableActionableDynamicQuery;

        if (isIndexAllArticleVersions()) {
            indexableActionableDynamicQuery = _journalArticleLocalService.getIndexableActionableDynamicQuery();

            indexableActionableDynamicQuery
                    .setPerformActionMethod(new ActionableDynamicQuery.PerformActionMethod<JournalArticle>() {

                        @Override
                        public void performAction(JournalArticle article) {
                            try {
                                Document document = getDocument(article);

                                indexableActionableDynamicQuery.addDocuments(document);
                            } catch (PortalException pe) {
                                if (_log.isWarnEnabled()) {
                                    _log.warn("Unable to index journal article " + article.getId(), pe);
                                }
                            }
                        }

                    });
        } else {
            indexableActionableDynamicQuery = _journalArticleResourceLocalService
                    .getIndexableActionableDynamicQuery();

            indexableActionableDynamicQuery.setPerformActionMethod(
                    new ActionableDynamicQuery.PerformActionMethod<JournalArticleResource>() {

                        @Override
                        public void performAction(JournalArticleResource articleResource) {

                            JournalArticle latestIndexableArticle = fetchLatestIndexableArticleVersion(
                                    articleResource.getResourcePrimKey());

                            if (latestIndexableArticle == null) {
                                return;
                            }

                            try {
                                Document document = getDocument(latestIndexableArticle);

                                indexableActionableDynamicQuery.addDocuments(document);
                            } catch (PortalException pe) {
                                if (_log.isWarnEnabled()) {
                                    _log.warn("Unable to index journal article " + latestIndexableArticle.getId(),
                                            pe);
                                }
                            }
                        }

                    });
        }

        indexableActionableDynamicQuery.setCompanyId(companyId);
        indexableActionableDynamicQuery.setSearchEngineId(getSearchEngineId());

        indexableActionableDynamicQuery.performActions();
    }

    protected void reindexArticleVersions(JournalArticle article) throws PortalException {

        _indexWriterHelper.updateDocuments(getSearchEngineId(), article.getCompanyId(), getArticleVersions(article),
                isCommitImmediately());
    }

    @Reference(unbind = "-")
    protected void setConfigurationProvider(ConfigurationProvider configurationProvider) {

        _configurationProvider = configurationProvider;
    }

    @Reference(unbind = "-")
    protected void setDDMIndexer(DDMIndexer ddmIndexer) {
        _ddmIndexer = ddmIndexer;
    }

    @Reference(unbind = "-")
    protected void setDDMStructureLocalService(DDMStructureLocalService ddmStructureLocalService) {

        _ddmStructureLocalService = ddmStructureLocalService;
    }

    @Reference(unbind = "-")
    protected void setFieldsToDDMFormValuesConverter(
            FieldsToDDMFormValuesConverter fieldsToDDMFormValuesConverter) {

        _fieldsToDDMFormValuesConverter = fieldsToDDMFormValuesConverter;
    }

    @Reference(unbind = "-")
    protected void setJournalArticleLocalService(JournalArticleLocalService journalArticleLocalService) {

        _journalArticleLocalService = journalArticleLocalService;
    }

    @Reference(unbind = "-")
    protected void setJournalArticleResourceLocalService(
            JournalArticleResourceLocalService journalArticleResourceLocalService) {

        _journalArticleResourceLocalService = journalArticleResourceLocalService;
    }

    @Reference(unbind = "-")
    protected void setJournalContent(JournalContent journalContent) {
        _journalContent = journalContent;
    }

    @Reference(unbind = "-")
    protected void setJournalConverter(JournalConverter journalConverter) {
        _journalConverter = journalConverter;
    }

    private static final Log _log = LogFactoryUtil.getLog(JournalArticleIndexer.class);

    private ConfigurationProvider _configurationProvider;
    private DDMIndexer _ddmIndexer;
    private DDMStructureLocalService _ddmStructureLocalService;
    private FieldsToDDMFormValuesConverter _fieldsToDDMFormValuesConverter;

    @Reference
    private IndexerRegistry _indexerRegistry;

    @Reference
    private IndexStatusManager _indexStatusManager;

    @Reference
    private IndexWriterHelper _indexWriterHelper;

    private JournalArticleLocalService _journalArticleLocalService;
    private JournalArticleResourceLocalService _journalArticleResourceLocalService;
    private JournalContent _journalContent;
    private JournalConverter _journalConverter;

    @Reference
    private Portal _portal;

}