com.liferay.message.boards.internal.search.MBMessageIndexer.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.message.boards.internal.search.MBMessageIndexer.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.message.boards.internal.search;

import com.liferay.document.library.kernel.model.DLFileEntry;
import com.liferay.message.boards.kernel.model.MBCategory;
import com.liferay.message.boards.kernel.model.MBCategoryConstants;
import com.liferay.message.boards.kernel.model.MBMessage;
import com.liferay.message.boards.kernel.service.MBCategoryLocalService;
import com.liferay.message.boards.kernel.service.MBCategoryService;
import com.liferay.message.boards.kernel.service.MBMessageLocalService;
import com.liferay.message.boards.model.MBDiscussion;
import com.liferay.message.boards.service.MBDiscussionLocalService;
import com.liferay.portal.kernel.comment.Comment;
import com.liferay.portal.kernel.comment.CommentManager;
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.model.Group;
import com.liferay.portal.kernel.parsers.bbcode.BBCodeTranslatorUtil;
import com.liferay.portal.kernel.repository.model.FileEntry;
import com.liferay.portal.kernel.search.BaseIndexer;
import com.liferay.portal.kernel.search.BaseRelatedEntryIndexer;
import com.liferay.portal.kernel.search.BooleanClauseOccur;
import com.liferay.portal.kernel.search.Document;
import com.liferay.portal.kernel.search.Field;
import com.liferay.portal.kernel.search.IndexWriterHelperUtil;
import com.liferay.portal.kernel.search.Indexer;
import com.liferay.portal.kernel.search.IndexerRegistryUtil;
import com.liferay.portal.kernel.search.RelatedEntryIndexer;
import com.liferay.portal.kernel.search.RelatedEntryIndexerRegistryUtil;
import com.liferay.portal.kernel.search.SearchContext;
import com.liferay.portal.kernel.search.Summary;
import com.liferay.portal.kernel.search.filter.BooleanFilter;
import com.liferay.portal.kernel.search.filter.TermsFilter;
import com.liferay.portal.kernel.security.permission.ActionKeys;
import com.liferay.portal.kernel.security.permission.PermissionChecker;
import com.liferay.portal.kernel.service.GroupLocalService;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.HtmlUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.workflow.WorkflowConstants;
import com.liferay.portlet.messageboards.service.permission.MBMessagePermission;
import com.liferay.portlet.messageboards.util.MBMessageAttachmentsUtil;

import java.util.List;
import java.util.Locale;

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
 */
@Component(immediate = true, property = {
        "related.entry.indexer.class.name=com.liferay.message.boards.kernel.model.MBMessage" }, service = {
                Indexer.class, RelatedEntryIndexer.class })
public class MBMessageIndexer extends BaseIndexer<MBMessage> implements RelatedEntryIndexer {

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

    public MBMessageIndexer() {
        setDefaultSelectedFieldNames(Field.ASSET_TAG_NAMES, Field.CLASS_NAME_ID, Field.CLASS_PK, Field.COMPANY_ID,
                Field.CONTENT, Field.ENTRY_CLASS_NAME, Field.ENTRY_CLASS_PK, Field.GROUP_ID, Field.MODIFIED_DATE,
                Field.SCOPE_GROUP_ID, Field.TITLE, Field.UID);
        setFilterSearch(true);
        setPermissionAware(true);
    }

    @Override
    public void addRelatedClassNames(BooleanFilter contextFilter, SearchContext searchContext) throws Exception {

        _relatedEntryIndexer.addRelatedClassNames(contextFilter, searchContext);
    }

    @Override
    public void addRelatedEntryFields(Document document, Object obj) throws Exception {

        FileEntry fileEntry = (FileEntry) obj;

        MBMessage message = MBMessageAttachmentsUtil.fetchMessage(fileEntry.getFileEntryId());

        if (message == null) {
            return;
        }

        document.addKeyword(Field.CATEGORY_ID, message.getCategoryId());

        document.addKeyword("discussion", false);
        document.addKeyword("threadId", message.getThreadId());
    }

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

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

        MBMessage message = mbMessageLocalService.getMessage(entryClassPK);

        if (message.isDiscussion()) {
            Indexer<?> indexer = IndexerRegistryUtil.getIndexer(message.getClassName());

            return indexer.hasPermission(permissionChecker, message.getClassName(), message.getClassPK(),
                    ActionKeys.VIEW);
        }

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

    @Override
    public boolean isVisible(long classPK, int status) throws Exception {
        MBMessage message = mbMessageLocalService.getMessage(classPK);

        return isVisible(message.getStatus(), status);
    }

    @Override
    public boolean isVisibleRelatedEntry(long classPK, int status) {
        try {
            MBMessage message = mbMessageLocalService.getMessage(classPK);

            if (message.isDiscussion()) {
                Indexer<?> indexer = IndexerRegistryUtil.getIndexer(message.getClassName());

                return indexer.isVisible(message.getClassPK(), status);
            }
        } catch (Exception e) {
            if (_log.isInfoEnabled()) {
                _log.info("Unable to get message boards message", e);
            }

            return false;
        }

        return true;
    }

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

        addStatus(contextBooleanFilter, searchContext);

        boolean discussion = GetterUtil.getBoolean(searchContext.getAttribute("discussion"));

        contextBooleanFilter.addRequiredTerm("discussion", discussion);

        if (searchContext.isIncludeDiscussions()) {
            addRelatedClassNames(contextBooleanFilter, searchContext);
        }

        String classNameId = GetterUtil.getString(searchContext.getAttribute(Field.CLASS_NAME_ID));

        if (Validator.isNotNull(classNameId)) {
            contextBooleanFilter.addRequiredTerm(Field.CLASS_NAME_ID, classNameId);
        }

        long threadId = GetterUtil.getLong((String) searchContext.getAttribute("threadId"));

        if (threadId > 0) {
            contextBooleanFilter.addRequiredTerm("threadId", threadId);
        }

        long[] categoryIds = searchContext.getCategoryIds();

        if ((categoryIds != null) && (categoryIds.length > 0)
                && (categoryIds[0] != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID)) {

            TermsFilter categoriesTermsFilter = new TermsFilter(Field.CATEGORY_ID);

            for (long categoryId : categoryIds) {
                try {
                    mbCategoryService.getCategory(categoryId);
                } catch (PortalException pe) {
                    if (_log.isDebugEnabled()) {
                        _log.debug("Unable to get message boards category " + categoryId, pe);
                    }

                    continue;
                }

                categoriesTermsFilter.addValue(String.valueOf(categoryId));
            }

            if (!categoriesTermsFilter.isEmpty()) {
                contextBooleanFilter.add(categoriesTermsFilter, BooleanClauseOccur.MUST);
            }
        }
    }

    @Override
    public void updateFullQuery(SearchContext searchContext) {
        if (searchContext.isIncludeDiscussions()) {
            searchContext.addFullQueryEntryClassName(MBMessage.class.getName());

            searchContext.setAttribute("discussion", Boolean.TRUE);
        }
    }

    @Override
    protected void doDelete(MBMessage mbMessage) throws Exception {
        deleteDocument(mbMessage.getCompanyId(), mbMessage.getMessageId());
    }

    @Override
    protected Document doGetDocument(MBMessage mbMessage) throws Exception {
        Document document = getBaseModelDocument(CLASS_NAME, mbMessage);

        document.addKeyword(Field.CATEGORY_ID, mbMessage.getCategoryId());
        document.addText(Field.CONTENT, processContent(mbMessage));
        document.addKeyword(Field.ROOT_ENTRY_CLASS_PK, mbMessage.getRootMessageId());
        document.addText(Field.TITLE, mbMessage.getSubject());

        if (mbMessage.isAnonymous()) {
            document.remove(Field.USER_NAME);
        }

        MBDiscussion discussion = mbDiscussionLocalService.fetchThreadDiscussion(mbMessage.getThreadId());

        if (discussion == null) {
            document.addKeyword("discussion", false);
        } else {
            document.addKeyword("discussion", true);
        }

        document.addKeyword("threadId", mbMessage.getThreadId());

        if (mbMessage.isDiscussion()) {
            List<RelatedEntryIndexer> relatedEntryIndexers = RelatedEntryIndexerRegistryUtil
                    .getRelatedEntryIndexers(mbMessage.getClassName());

            if (relatedEntryIndexers != null) {
                for (RelatedEntryIndexer relatedEntryIndexer : relatedEntryIndexers) {

                    Comment comment = commentManager.fetchComment(mbMessage.getMessageId());

                    if (comment != null) {
                        relatedEntryIndexer.addRelatedEntryFields(document, comment);

                        document.addKeyword(Field.RELATED_ENTRY, true);
                    }
                }
            }
        }

        return document;
    }

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

        Summary summary = createSummary(document, Field.TITLE, Field.CONTENT);

        summary.setMaxContentLength(200);

        return summary;
    }

    @Override
    protected void doReindex(MBMessage mbMessage) throws Exception {
        if ((!mbMessage.isApproved() && !mbMessage.isInTrash())
                || (mbMessage.isDiscussion() && mbMessage.isRoot())) {

            return;
        }

        Document document = getDocument(mbMessage);

        IndexWriterHelperUtil.updateDocument(getSearchEngineId(), mbMessage.getCompanyId(), document,
                isCommitImmediately());

        reindexAttachments(mbMessage);
    }

    @Override
    protected void doReindex(String className, long classPK) throws Exception {
        MBMessage message = mbMessageLocalService.getMessage(classPK);

        doReindex(message);

        if (message.isRoot()) {
            List<MBMessage> messages = mbMessageLocalService.getThreadMessages(message.getThreadId(),
                    WorkflowConstants.STATUS_APPROVED);

            for (MBMessage curMessage : messages) {
                reindex(curMessage);
            }
        } else {
            reindex(message);
        }
    }

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

        reindexCategories(companyId);
        reindexDiscussions(companyId);
        reindexRoot(companyId);
    }

    protected String processContent(MBMessage message) {
        String content = message.getBody();

        try {
            if (message.isFormatBBCode()) {
                content = BBCodeTranslatorUtil.getHTML(content);
            }
        } catch (Exception e) {
            _log.error(StringBundler.concat("Unable to parse message ", String.valueOf(message.getMessageId()),
                    ": ", e.getMessage()), e);
        }

        content = HtmlUtil.extractText(content);

        return content;
    }

    protected void reindexAttachments(MBMessage mbMessage) throws PortalException {

        Indexer<DLFileEntry> indexer = IndexerRegistryUtil.nullSafeGetIndexer(DLFileEntry.class);

        for (FileEntry attachmentsFileEntry : mbMessage.getAttachmentsFileEntries()) {

            indexer.reindex((DLFileEntry) attachmentsFileEntry.getModel());
        }
    }

    protected void reindexCategories(final long companyId) throws PortalException {

        ActionableDynamicQuery actionableDynamicQuery = mbCategoryLocalService.getActionableDynamicQuery();

        actionableDynamicQuery.setCompanyId(companyId);
        actionableDynamicQuery.setPerformActionMethod(new ActionableDynamicQuery.PerformActionMethod<MBCategory>() {

            @Override
            public void performAction(MBCategory category) throws PortalException {

                reindexMessages(companyId, category.getGroupId(), category.getCategoryId());
            }

        });

        actionableDynamicQuery.performActions();
    }

    protected void reindexDiscussions(final long companyId) throws PortalException {

        ActionableDynamicQuery actionableDynamicQuery = groupLocalService.getActionableDynamicQuery();

        actionableDynamicQuery.setCompanyId(companyId);
        actionableDynamicQuery.setPerformActionMethod(new ActionableDynamicQuery.PerformActionMethod<Group>() {

            @Override
            public void performAction(Group group) throws PortalException {
                reindexMessages(companyId, group.getGroupId(), MBCategoryConstants.DISCUSSION_CATEGORY_ID);
            }

        });

        actionableDynamicQuery.performActions();
    }

    protected void reindexMessages(long companyId, long groupId, final long categoryId) throws PortalException {

        final IndexableActionableDynamicQuery indexableActionableDynamicQuery = mbMessageLocalService
                .getIndexableActionableDynamicQuery();

        indexableActionableDynamicQuery.setAddCriteriaMethod(new ActionableDynamicQuery.AddCriteriaMethod() {

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

                dynamicQuery.add(categoryIdProperty.eq(categoryId));

                Property statusProperty = PropertyFactoryUtil.forName("status");

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

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

        });
        indexableActionableDynamicQuery.setCompanyId(companyId);
        indexableActionableDynamicQuery.setGroupId(groupId);
        indexableActionableDynamicQuery
                .setPerformActionMethod(new ActionableDynamicQuery.PerformActionMethod<MBMessage>() {

                    @Override
                    public void performAction(MBMessage message) {
                        if (message.isDiscussion() && message.isRoot()) {
                            return;
                        }

                        try {
                            Document document = getDocument(message);

                            indexableActionableDynamicQuery.addDocuments(document);
                        } catch (PortalException pe) {
                            if (_log.isWarnEnabled()) {
                                _log.warn("Unable to index message boards message " + message.getMessageId(), pe);
                            }
                        }
                    }

                });
        indexableActionableDynamicQuery.setSearchEngineId(getSearchEngineId());

        indexableActionableDynamicQuery.performActions();
    }

    protected void reindexRoot(final long companyId) throws PortalException {
        ActionableDynamicQuery actionableDynamicQuery = groupLocalService.getActionableDynamicQuery();

        actionableDynamicQuery.setCompanyId(companyId);
        actionableDynamicQuery.setPerformActionMethod(new ActionableDynamicQuery.PerformActionMethod<Group>() {

            @Override
            public void performAction(Group group) throws PortalException {
                reindexMessages(companyId, group.getGroupId(), MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID);
            }

        });

        actionableDynamicQuery.performActions();
    }

    @Reference
    protected CommentManager commentManager;

    @Reference
    protected GroupLocalService groupLocalService;

    @Reference
    protected MBCategoryLocalService mbCategoryLocalService;

    @Reference
    protected MBCategoryService mbCategoryService;

    @Reference
    protected MBDiscussionLocalService mbDiscussionLocalService;

    @Reference
    protected MBMessageLocalService mbMessageLocalService;

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

    private final RelatedEntryIndexer _relatedEntryIndexer = new BaseRelatedEntryIndexer();

}