com.liferay.bookmarks.service.impl.BookmarksEntryLocalServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.bookmarks.service.impl.BookmarksEntryLocalServiceImpl.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.bookmarks.service.impl;

import aQute.bnd.annotation.ProviderType;

import com.liferay.asset.kernel.model.AssetEntry;
import com.liferay.asset.kernel.model.AssetLinkConstants;
import com.liferay.bookmarks.configuration.BookmarksGroupServiceOverriddenConfiguration;
import com.liferay.bookmarks.constants.BookmarksConstants;
import com.liferay.bookmarks.constants.BookmarksPortletKeys;
import com.liferay.bookmarks.exception.EntryURLException;
import com.liferay.bookmarks.model.BookmarksEntry;
import com.liferay.bookmarks.model.BookmarksFolder;
import com.liferay.bookmarks.model.BookmarksFolderConstants;
import com.liferay.bookmarks.service.base.BookmarksEntryLocalServiceBaseImpl;
import com.liferay.bookmarks.service.permission.BookmarksResourcePermissionChecker;
import com.liferay.bookmarks.social.BookmarksActivityKeys;
import com.liferay.bookmarks.util.comparator.EntryModifiedDateComparator;
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.dao.orm.RestrictionsFactoryUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONObject;
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.model.ResourceConstants;
import com.liferay.portal.kernel.model.SystemEventConstants;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.module.configuration.ConfigurationProvider;
import com.liferay.portal.kernel.notifications.UserNotificationDefinition;
import com.liferay.portal.kernel.search.Document;
import com.liferay.portal.kernel.search.Field;
import com.liferay.portal.kernel.search.Hits;
import com.liferay.portal.kernel.search.Indexable;
import com.liferay.portal.kernel.search.IndexableType;
import com.liferay.portal.kernel.search.Indexer;
import com.liferay.portal.kernel.search.IndexerRegistryUtil;
import com.liferay.portal.kernel.search.QueryConfig;
import com.liferay.portal.kernel.search.SearchContext;
import com.liferay.portal.kernel.search.Sort;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.settings.GroupServiceSettingsLocator;
import com.liferay.portal.kernel.settings.LocalizedValuesMap;
import com.liferay.portal.kernel.systemevent.SystemEvent;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.ContentTypes;
import com.liferay.portal.kernel.util.GroupSubscriptionCheckSubscriptionSender;
import com.liferay.portal.kernel.util.LocalizationUtil;
import com.liferay.portal.kernel.util.OrderByComparator;
import com.liferay.portal.kernel.util.Portal;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.SubscriptionSender;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.workflow.WorkflowConstants;
import com.liferay.portal.spring.extender.service.ServiceReference;
import com.liferay.social.kernel.model.SocialActivityConstants;
import com.liferay.trash.kernel.exception.RestoreEntryException;
import com.liferay.trash.kernel.exception.TrashEntryException;
import com.liferay.trash.kernel.model.TrashEntry;
import com.liferay.trash.kernel.model.TrashVersion;

import java.util.Date;
import java.util.List;

/**
 * @author Brian Wing Shun Chan
 * @author Raymond Aug
 * @author Levente Hudk
 */
@ProviderType
public class BookmarksEntryLocalServiceImpl extends BookmarksEntryLocalServiceBaseImpl {

    @Indexable(type = IndexableType.REINDEX)
    @Override
    public BookmarksEntry addEntry(long userId, long groupId, long folderId, String name, String url,
            String description, ServiceContext serviceContext) throws PortalException {

        // Entry

        User user = userPersistence.findByPrimaryKey(userId);

        if (Validator.isNull(name)) {
            name = url;
        }

        validate(url);

        long entryId = counterLocalService.increment();

        BookmarksEntry entry = bookmarksEntryPersistence.create(entryId);

        entry.setUuid(serviceContext.getUuid());
        entry.setGroupId(groupId);
        entry.setCompanyId(user.getCompanyId());
        entry.setUserId(user.getUserId());
        entry.setUserName(user.getFullName());
        entry.setFolderId(folderId);
        entry.setTreePath(entry.buildTreePath());
        entry.setName(name);
        entry.setUrl(url);
        entry.setDescription(description);
        entry.setExpandoBridgeAttributes(serviceContext);

        bookmarksEntryPersistence.update(entry);

        // Resources

        resourceLocalService.addModelResources(entry, serviceContext);

        // Asset

        updateAsset(userId, entry, serviceContext.getAssetCategoryIds(), serviceContext.getAssetTagNames(),
                serviceContext.getAssetLinkEntryIds(), serviceContext.getAssetPriority());

        // Social

        JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();

        extraDataJSONObject.put("title", entry.getName());

        socialActivityLocalService.addActivity(userId, groupId, BookmarksEntry.class.getName(), entryId,
                BookmarksActivityKeys.ADD_ENTRY, extraDataJSONObject.toString(), 0);

        // Subscriptions

        notifySubscribers(userId, entry, serviceContext);

        return entry;
    }

    @Override
    public void deleteEntries(long groupId, long folderId) throws PortalException {

        deleteEntries(groupId, folderId, true);
    }

    @Override
    public void deleteEntries(long groupId, long folderId, boolean includeTrashedEntries) throws PortalException {

        List<BookmarksEntry> entries = bookmarksEntryPersistence.findByG_F(groupId, folderId);

        for (BookmarksEntry entry : entries) {
            if (includeTrashedEntries || !entry.isInTrashExplicitly()) {
                bookmarksEntryLocalService.deleteEntry(entry);
            }
        }
    }

    @Indexable(type = IndexableType.DELETE)
    @Override
    @SystemEvent(type = SystemEventConstants.TYPE_DELETE)
    public BookmarksEntry deleteEntry(BookmarksEntry entry) throws PortalException {

        // Entry

        bookmarksEntryPersistence.remove(entry);

        // Resources

        resourceLocalService.deleteResource(entry, ResourceConstants.SCOPE_INDIVIDUAL);

        // Asset

        assetEntryLocalService.deleteEntry(BookmarksEntry.class.getName(), entry.getEntryId());

        // Expando

        expandoRowLocalService.deleteRows(entry.getEntryId());

        // Ratings

        ratingsStatsLocalService.deleteStats(BookmarksEntry.class.getName(), entry.getEntryId());

        // Subscriptions

        subscriptionLocalService.deleteSubscriptions(entry.getCompanyId(), BookmarksEntry.class.getName(),
                entry.getEntryId());

        // Trash

        if (entry.isInTrashExplicitly()) {
            trashEntryLocalService.deleteEntry(BookmarksEntry.class.getName(), entry.getEntryId());
        } else {
            trashVersionLocalService.deleteTrashVersion(BookmarksEntry.class.getName(), entry.getEntryId());
        }

        return entry;
    }

    @Indexable(type = IndexableType.DELETE)
    @Override
    public BookmarksEntry deleteEntry(long entryId) throws PortalException {
        BookmarksEntry entry = bookmarksEntryPersistence.findByPrimaryKey(entryId);

        return bookmarksEntryLocalService.deleteEntry(entry);
    }

    @Override
    public List<BookmarksEntry> getEntries(long groupId, long folderId, int start, int end) {

        return getEntries(groupId, folderId, WorkflowConstants.STATUS_APPROVED, start, end);
    }

    @Override
    public List<BookmarksEntry> getEntries(long groupId, long folderId, int status, int start, int end) {

        return getEntries(groupId, folderId, status, start, end, null);
    }

    @Override
    public List<BookmarksEntry> getEntries(long groupId, long folderId, int status, int start, int end,
            OrderByComparator<BookmarksEntry> orderByComparator) {

        return bookmarksEntryPersistence.findByG_F_S(groupId, folderId, status, start, end, orderByComparator);
    }

    @Override
    public List<BookmarksEntry> getEntries(long groupId, long folderId, int start, int end,
            OrderByComparator<BookmarksEntry> orderByComparator) {

        return getEntries(groupId, folderId, WorkflowConstants.STATUS_APPROVED, start, end, orderByComparator);
    }

    @Override
    public int getEntriesCount(long groupId, long folderId) {
        return getEntriesCount(groupId, folderId, WorkflowConstants.STATUS_APPROVED);
    }

    @Override
    public int getEntriesCount(long groupId, long folderId, int status) {
        return bookmarksEntryPersistence.countByG_F_S(groupId, folderId, status);
    }

    @Override
    public BookmarksEntry getEntry(long entryId) throws PortalException {
        return bookmarksEntryPersistence.findByPrimaryKey(entryId);
    }

    @Override
    public int getFoldersEntriesCount(long groupId, List<Long> folderIds) {
        return bookmarksEntryPersistence.countByG_F_S(groupId,
                ArrayUtil.toArray(folderIds.toArray(new Long[folderIds.size()])),
                WorkflowConstants.STATUS_APPROVED);
    }

    @Override
    public List<BookmarksEntry> getGroupEntries(long groupId, int start, int end) {

        return bookmarksEntryPersistence.findByG_S(groupId, WorkflowConstants.STATUS_APPROVED, start, end,
                new EntryModifiedDateComparator());
    }

    @Override
    public List<BookmarksEntry> getGroupEntries(long groupId, long userId, int start, int end) {

        OrderByComparator<BookmarksEntry> orderByComparator = new EntryModifiedDateComparator();

        if (userId <= 0) {
            return bookmarksEntryPersistence.findByG_S(groupId, WorkflowConstants.STATUS_APPROVED, start, end,
                    orderByComparator);
        } else {
            return bookmarksEntryPersistence.findByG_U_S(groupId, userId, WorkflowConstants.STATUS_APPROVED, start,
                    end, orderByComparator);
        }
    }

    @Override
    public int getGroupEntriesCount(long groupId) {
        return bookmarksEntryPersistence.countByG_S(groupId, WorkflowConstants.STATUS_APPROVED);
    }

    @Override
    public int getGroupEntriesCount(long groupId, long userId) {
        if (userId <= 0) {
            return getGroupEntriesCount(groupId);
        } else {
            return bookmarksEntryPersistence.countByG_U_S(groupId, userId, WorkflowConstants.STATUS_APPROVED);
        }
    }

    @Override
    public List<BookmarksEntry> getNoAssetEntries() {
        return bookmarksEntryFinder.findByNoAssets();
    }

    @Indexable(type = IndexableType.REINDEX)
    @Override
    public BookmarksEntry moveEntry(long entryId, long parentFolderId) throws PortalException {

        BookmarksEntry entry = getBookmarksEntry(entryId);

        entry.setFolderId(parentFolderId);
        entry.setTreePath(entry.buildTreePath());

        bookmarksEntryPersistence.update(entry);

        return entry;
    }

    @Override
    public BookmarksEntry moveEntryFromTrash(long userId, long entryId, long parentFolderId)
            throws PortalException {

        BookmarksEntry entry = getBookmarksEntry(entryId);

        if (!entry.isInTrash()) {
            throw new RestoreEntryException(RestoreEntryException.INVALID_STATUS);
        }

        if (entry.isInTrashExplicitly()) {
            restoreEntryFromTrash(userId, entryId);
        } else {

            // Entry

            TrashVersion trashVersion = trashVersionLocalService.fetchVersion(BookmarksEntry.class.getName(),
                    entryId);

            int status = WorkflowConstants.STATUS_APPROVED;

            if (trashVersion != null) {
                status = trashVersion.getStatus();
            }

            updateStatus(userId, entry, status);

            // Trash

            if (trashVersion != null) {
                trashVersionLocalService.deleteTrashVersion(trashVersion);
            }
        }

        return bookmarksEntryLocalService.moveEntry(entryId, parentFolderId);
    }

    @Indexable(type = IndexableType.REINDEX)
    @Override
    public BookmarksEntry moveEntryToTrash(long userId, BookmarksEntry entry) throws PortalException {

        if (entry.isInTrash()) {
            throw new TrashEntryException();
        }

        int oldStatus = entry.getStatus();

        entry = updateStatus(userId, entry, WorkflowConstants.STATUS_IN_TRASH);

        trashEntryLocalService.addTrashEntry(userId, entry.getGroupId(), BookmarksEntry.class.getName(),
                entry.getEntryId(), entry.getUuid(), null, oldStatus, null, null);

        return entry;
    }

    @Indexable(type = IndexableType.REINDEX)
    @Override
    public BookmarksEntry moveEntryToTrash(long userId, long entryId) throws PortalException {

        BookmarksEntry entry = getEntry(entryId);

        return moveEntryToTrash(userId, entry);
    }

    @Override
    public BookmarksEntry openEntry(long userId, BookmarksEntry entry) {
        entry.setVisits(entry.getVisits() + 1);

        bookmarksEntryPersistence.update(entry);

        assetEntryLocalService.incrementViewCounter(userId, BookmarksEntry.class.getName(), entry.getEntryId(), 1);

        return entry;
    }

    @Override
    public BookmarksEntry openEntry(long userId, long entryId) throws PortalException {

        BookmarksEntry entry = bookmarksEntryPersistence.findByPrimaryKey(entryId);

        return openEntry(userId, entry);
    }

    @Override
    public void rebuildTree(long companyId) throws PortalException {
        bookmarksFolderLocalService.rebuildTree(companyId);
    }

    @Indexable(type = IndexableType.REINDEX)
    @Override
    public BookmarksEntry restoreEntryFromTrash(long userId, long entryId) throws PortalException {

        BookmarksEntry entry = bookmarksEntryPersistence.findByPrimaryKey(entryId);

        if (!entry.isInTrash()) {
            throw new RestoreEntryException(RestoreEntryException.INVALID_STATUS);
        }

        TrashEntry trashEntry = trashEntryLocalService.getEntry(BookmarksEntry.class.getName(), entryId);

        entry = updateStatus(userId, entry, trashEntry.getStatus());

        trashEntryLocalService.deleteEntry(BookmarksEntry.class.getName(), entry.getEntryId());

        return entry;
    }

    @Override
    public Hits search(long groupId, long userId, long creatorUserId, int status, int start, int end)
            throws PortalException {

        Indexer<BookmarksEntry> indexer = IndexerRegistryUtil.getIndexer(BookmarksEntry.class.getName());

        SearchContext searchContext = new SearchContext();

        searchContext.setAttribute(Field.STATUS, status);

        if (creatorUserId > 0) {
            searchContext.setAttribute(Field.USER_ID, String.valueOf(creatorUserId));
        }

        searchContext.setAttribute("paginationType", "none");

        Group group = groupLocalService.getGroup(groupId);

        searchContext.setCompanyId(group.getCompanyId());

        searchContext.setEnd(end);
        searchContext.setGroupIds(new long[] { groupId });
        searchContext.setSorts(new Sort(Field.MODIFIED_DATE, true));
        searchContext.setStart(start);
        searchContext.setUserId(userId);

        QueryConfig queryConfig = searchContext.getQueryConfig();

        queryConfig.setHighlightEnabled(false);
        queryConfig.setScoreEnabled(false);

        return indexer.search(searchContext);
    }

    @Override
    public void setTreePaths(final long folderId, final String treePath, final boolean reindex)
            throws PortalException {

        if (treePath == null) {
            throw new IllegalArgumentException("Tree path is null");
        }

        final IndexableActionableDynamicQuery indexableActionableDynamicQuery = getIndexableActionableDynamicQuery();

        indexableActionableDynamicQuery.setAddCriteriaMethod(new ActionableDynamicQuery.AddCriteriaMethod() {

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

                dynamicQuery.add(folderIdProperty.eq(folderId));

                Property treePathProperty = PropertyFactoryUtil.forName("treePath");

                dynamicQuery
                        .add(RestrictionsFactoryUtil.or(treePathProperty.isNull(), treePathProperty.ne(treePath)));
            }

        });

        final Indexer<BookmarksEntry> indexer = IndexerRegistryUtil.getIndexer(BookmarksEntry.class);

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

                    @Override
                    public void performAction(BookmarksEntry entry) throws PortalException {

                        entry.setTreePath(treePath);

                        updateBookmarksEntry(entry);

                        if (!reindex) {
                            return;
                        }

                        Document document = indexer.getDocument(entry);

                        indexableActionableDynamicQuery.addDocuments(document);
                    }

                });

        indexableActionableDynamicQuery.performActions();
    }

    @Override
    public void subscribeEntry(long userId, long entryId) throws PortalException {

        BookmarksEntry entry = bookmarksEntryPersistence.findByPrimaryKey(entryId);

        subscriptionLocalService.addSubscription(userId, entry.getGroupId(), BookmarksEntry.class.getName(),
                entryId);
    }

    @Override
    public void unsubscribeEntry(long userId, long entryId) throws PortalException {

        subscriptionLocalService.deleteSubscription(userId, BookmarksEntry.class.getName(), entryId);
    }

    @Override
    public void updateAsset(long userId, BookmarksEntry entry, long[] assetCategoryIds, String[] assetTagNames,
            long[] assetLinkEntryIds, Double priority) throws PortalException {

        AssetEntry assetEntry = assetEntryLocalService.updateEntry(userId, entry.getGroupId(),
                entry.getCreateDate(), entry.getModifiedDate(), BookmarksEntry.class.getName(), entry.getEntryId(),
                entry.getUuid(), 0, assetCategoryIds, assetTagNames, true, true, null, null, entry.getCreateDate(),
                null, ContentTypes.TEXT_PLAIN, entry.getName(), entry.getDescription(), null, entry.getUrl(), null,
                0, 0, priority);

        assetLinkLocalService.updateLinks(userId, assetEntry.getEntryId(), assetLinkEntryIds,
                AssetLinkConstants.TYPE_RELATED);
    }

    @Indexable(type = IndexableType.REINDEX)
    @Override
    public BookmarksEntry updateEntry(long userId, long entryId, long groupId, long folderId, String name,
            String url, String description, ServiceContext serviceContext) throws PortalException {

        // Entry

        BookmarksEntry entry = bookmarksEntryPersistence.findByPrimaryKey(entryId);

        if (Validator.isNull(name)) {
            name = url;
        }

        validate(url);

        entry.setFolderId(folderId);
        entry.setTreePath(entry.buildTreePath());
        entry.setName(name);
        entry.setUrl(url);
        entry.setDescription(description);
        entry.setExpandoBridgeAttributes(serviceContext);

        bookmarksEntryPersistence.update(entry);

        // Asset

        updateAsset(userId, entry, serviceContext.getAssetCategoryIds(), serviceContext.getAssetTagNames(),
                serviceContext.getAssetLinkEntryIds(), serviceContext.getAssetPriority());

        // Social

        JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();

        extraDataJSONObject.put("title", entry.getName());

        socialActivityLocalService.addActivity(userId, entry.getGroupId(), BookmarksEntry.class.getName(), entryId,
                BookmarksActivityKeys.UPDATE_ENTRY, extraDataJSONObject.toString(), 0);

        // Subscriptions

        notifySubscribers(userId, entry, serviceContext);

        return entry;
    }

    @Override
    public BookmarksEntry updateStatus(long userId, BookmarksEntry entry, int status) throws PortalException {

        // Entry

        User user = userPersistence.findByPrimaryKey(userId);

        entry.setStatus(status);
        entry.setStatusByUserId(userId);
        entry.setStatusByUserName(user.getScreenName());
        entry.setStatusDate(new Date());

        bookmarksEntryPersistence.update(entry);

        JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();

        extraDataJSONObject.put("title", entry.getName());

        if (status == WorkflowConstants.STATUS_APPROVED) {

            // Asset

            assetEntryLocalService.updateVisible(BookmarksEntry.class.getName(), entry.getEntryId(), true);

            // Social

            socialActivityLocalService.addActivity(userId, entry.getGroupId(), BookmarksEntry.class.getName(),
                    entry.getEntryId(), SocialActivityConstants.TYPE_RESTORE_FROM_TRASH,
                    extraDataJSONObject.toString(), 0);
        } else if (status == WorkflowConstants.STATUS_IN_TRASH) {

            // Asset

            assetEntryLocalService.updateVisible(BookmarksEntry.class.getName(), entry.getEntryId(), false);

            // Social

            socialActivityLocalService.addActivity(userId, entry.getGroupId(), BookmarksEntry.class.getName(),
                    entry.getEntryId(), SocialActivityConstants.TYPE_MOVE_TO_TRASH, extraDataJSONObject.toString(),
                    0);
        }

        return entry;
    }

    protected long getFolder(BookmarksEntry entry, long folderId) {
        if ((entry.getFolderId() != folderId) && (folderId != BookmarksFolderConstants.DEFAULT_PARENT_FOLDER_ID)) {

            BookmarksFolder newFolder = bookmarksFolderPersistence.fetchByPrimaryKey(folderId);

            if ((newFolder == null) || (entry.getGroupId() != newFolder.getGroupId())) {

                folderId = entry.getFolderId();
            }
        }

        return folderId;
    }

    protected void notifySubscribers(long userId, BookmarksEntry entry, ServiceContext serviceContext)
            throws PortalException {

        String layoutFullURL = serviceContext.getLayoutFullURL();

        if (!entry.isApproved() || Validator.isNull(layoutFullURL)) {
            return;
        }

        BookmarksGroupServiceOverriddenConfiguration bookmarksGroupServiceOverriddenConfiguration = configurationProvider
                .getConfiguration(BookmarksGroupServiceOverriddenConfiguration.class,
                        new GroupServiceSettingsLocator(entry.getGroupId(), BookmarksConstants.SERVICE_NAME));

        if ((serviceContext.isCommandAdd()
                && !bookmarksGroupServiceOverriddenConfiguration.emailEntryAddedEnabled())
                || (serviceContext.isCommandUpdate()
                        && !bookmarksGroupServiceOverriddenConfiguration.emailEntryUpdatedEnabled())) {

            return;
        }

        String statusByUserName = StringPool.BLANK;

        try {
            User user = userLocalService.getUserById(serviceContext.getGuestOrUserId());

            statusByUserName = user.getFullName();
        } catch (Exception e) {
            _log.error(e, e);
        }

        String entryTitle = entry.getName();

        StringBundler sb = new StringBundler(7);

        sb.append(layoutFullURL);
        sb.append(Portal.FRIENDLY_URL_SEPARATOR);
        sb.append("bookmarks");
        sb.append(StringPool.SLASH);
        sb.append("folder");
        sb.append(StringPool.SLASH);
        sb.append(entry.getFolderId());

        String entryURL = sb.toString();

        String fromName = bookmarksGroupServiceOverriddenConfiguration.emailFromName();
        String fromAddress = bookmarksGroupServiceOverriddenConfiguration.emailFromAddress();

        LocalizedValuesMap subjectLocalizedValuesMap = null;
        LocalizedValuesMap bodyLocalizedValuesMap = null;

        if (serviceContext.isCommandUpdate()) {
            subjectLocalizedValuesMap = bookmarksGroupServiceOverriddenConfiguration.emailEntryUpdatedSubject();
            bodyLocalizedValuesMap = bookmarksGroupServiceOverriddenConfiguration.emailEntryUpdatedBody();
        } else {
            subjectLocalizedValuesMap = bookmarksGroupServiceOverriddenConfiguration.emailEntryAddedSubject();
            bodyLocalizedValuesMap = bookmarksGroupServiceOverriddenConfiguration.emailEntryAddedBody();
        }

        SubscriptionSender subscriptionSender = new GroupSubscriptionCheckSubscriptionSender(
                BookmarksResourcePermissionChecker.RESOURCE_NAME);

        subscriptionSender.setClassName(entry.getModelClassName());
        subscriptionSender.setClassPK(entry.getEntryId());
        subscriptionSender.setCompanyId(entry.getCompanyId());
        subscriptionSender.setContextAttributes("[$BOOKMARKS_ENTRY_STATUS_BY_USER_NAME$]", statusByUserName,
                "[$BOOKMARKS_ENTRY_URL$]", entryURL);
        subscriptionSender.setContextCreatorUserPrefix("BOOKMARKS_ENTRY");
        subscriptionSender.setCreatorUserId(entry.getUserId());
        subscriptionSender.setCurrentUserId(userId);
        subscriptionSender.setEntryTitle(entryTitle);
        subscriptionSender.setEntryURL(entryURL);
        subscriptionSender.setFrom(fromAddress, fromName);
        subscriptionSender.setHtmlFormat(true);

        if (bodyLocalizedValuesMap != null) {
            subscriptionSender.setLocalizedBodyMap(LocalizationUtil.getMap(bodyLocalizedValuesMap));
        }

        if (subjectLocalizedValuesMap != null) {
            subscriptionSender.setLocalizedSubjectMap(LocalizationUtil.getMap(subjectLocalizedValuesMap));
        }

        subscriptionSender.setMailId("bookmarks_entry", entry.getEntryId());

        int notificationType = UserNotificationDefinition.NOTIFICATION_TYPE_ADD_ENTRY;

        if (serviceContext.isCommandUpdate()) {
            notificationType = UserNotificationDefinition.NOTIFICATION_TYPE_UPDATE_ENTRY;
        }

        subscriptionSender.setNotificationType(notificationType);

        subscriptionSender.setPortletId(BookmarksPortletKeys.BOOKMARKS);
        subscriptionSender.setReplyToAddress(fromAddress);
        subscriptionSender.setScopeGroupId(entry.getGroupId());
        subscriptionSender.setServiceContext(serviceContext);

        BookmarksFolder folder = entry.getFolder();

        if (folder != null) {
            subscriptionSender.addPersistedSubscribers(BookmarksFolder.class.getName(), folder.getFolderId());

            for (Long ancestorFolderId : folder.getAncestorFolderIds()) {
                subscriptionSender.addPersistedSubscribers(BookmarksFolder.class.getName(), ancestorFolderId);
            }
        }

        subscriptionSender.addPersistedSubscribers(BookmarksFolder.class.getName(), entry.getGroupId());

        subscriptionSender.addPersistedSubscribers(BookmarksEntry.class.getName(), entry.getEntryId());

        subscriptionSender.flushNotificationsAsync();
    }

    protected void validate(String url) throws PortalException {
        if (!Validator.isUrl(url)) {
            throw new EntryURLException();
        }
    }

    @ServiceReference(type = ConfigurationProvider.class)
    protected ConfigurationProvider configurationProvider;

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

}