001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.bookmarks.service.impl;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.json.JSONFactoryUtil;
020    import com.liferay.portal.kernel.json.JSONObject;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.search.Field;
024    import com.liferay.portal.kernel.search.Hits;
025    import com.liferay.portal.kernel.search.Indexable;
026    import com.liferay.portal.kernel.search.IndexableType;
027    import com.liferay.portal.kernel.search.Indexer;
028    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
029    import com.liferay.portal.kernel.search.SearchContext;
030    import com.liferay.portal.kernel.search.Sort;
031    import com.liferay.portal.kernel.util.ArrayUtil;
032    import com.liferay.portal.kernel.util.ContentTypes;
033    import com.liferay.portal.kernel.util.OrderByComparator;
034    import com.liferay.portal.kernel.util.StringPool;
035    import com.liferay.portal.kernel.util.Validator;
036    import com.liferay.portal.kernel.workflow.WorkflowConstants;
037    import com.liferay.portal.model.Group;
038    import com.liferay.portal.model.ResourceConstants;
039    import com.liferay.portal.model.User;
040    import com.liferay.portal.service.ServiceContext;
041    import com.liferay.portal.service.ServiceContextUtil;
042    import com.liferay.portal.util.Portal;
043    import com.liferay.portal.util.PortletKeys;
044    import com.liferay.portal.util.SubscriptionSender;
045    import com.liferay.portlet.asset.model.AssetEntry;
046    import com.liferay.portlet.asset.model.AssetLinkConstants;
047    import com.liferay.portlet.bookmarks.EntryURLException;
048    import com.liferay.portlet.bookmarks.model.BookmarksEntry;
049    import com.liferay.portlet.bookmarks.model.BookmarksFolder;
050    import com.liferay.portlet.bookmarks.model.BookmarksFolderConstants;
051    import com.liferay.portlet.bookmarks.service.base.BookmarksEntryLocalServiceBaseImpl;
052    import com.liferay.portlet.bookmarks.social.BookmarksActivityKeys;
053    import com.liferay.portlet.bookmarks.util.BookmarksUtil;
054    import com.liferay.portlet.bookmarks.util.comparator.EntryModifiedDateComparator;
055    import com.liferay.portlet.social.model.SocialActivityConstants;
056    import com.liferay.portlet.trash.model.TrashEntry;
057    import com.liferay.portlet.trash.model.TrashVersion;
058    
059    import java.util.ArrayList;
060    import java.util.Date;
061    import java.util.List;
062    import java.util.Locale;
063    import java.util.Map;
064    
065    import javax.portlet.PortletPreferences;
066    
067    /**
068     * @author Brian Wing Shun Chan
069     * @author Raymond Aug??
070     * @author Levente Hud??k
071     */
072    public class BookmarksEntryLocalServiceImpl
073            extends BookmarksEntryLocalServiceBaseImpl {
074    
075            @Indexable(type = IndexableType.REINDEX)
076            @Override
077            public BookmarksEntry addEntry(
078                            long userId, long groupId, long folderId, String name, String url,
079                            String description, ServiceContext serviceContext)
080                    throws PortalException, SystemException {
081    
082                    // Entry
083    
084                    User user = userPersistence.findByPrimaryKey(userId);
085    
086                    if (Validator.isNull(name)) {
087                            name = url;
088                    }
089    
090                    Date now = new Date();
091    
092                    validate(url);
093    
094                    long entryId = counterLocalService.increment();
095    
096                    BookmarksEntry entry = bookmarksEntryPersistence.create(entryId);
097    
098                    entry.setUuid(serviceContext.getUuid());
099                    entry.setGroupId(groupId);
100                    entry.setCompanyId(user.getCompanyId());
101                    entry.setUserId(user.getUserId());
102                    entry.setUserName(user.getFullName());
103                    entry.setCreateDate(serviceContext.getCreateDate(now));
104                    entry.setModifiedDate(serviceContext.getModifiedDate(now));
105                    entry.setFolderId(folderId);
106                    entry.setTreePath(entry.buildTreePath());
107                    entry.setName(name);
108                    entry.setUrl(url);
109                    entry.setDescription(description);
110                    entry.setExpandoBridgeAttributes(serviceContext);
111    
112                    bookmarksEntryPersistence.update(entry);
113    
114                    // Resources
115    
116                    resourceLocalService.addModelResources(entry, serviceContext);
117    
118                    // Asset
119    
120                    updateAsset(
121                            userId, entry, serviceContext.getAssetCategoryIds(),
122                            serviceContext.getAssetTagNames(),
123                            serviceContext.getAssetLinkEntryIds());
124    
125                    // Social
126    
127                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
128    
129                    extraDataJSONObject.put("title", entry.getName());
130    
131                    socialActivityLocalService.addActivity(
132                            userId, groupId, BookmarksEntry.class.getName(), entryId,
133                            BookmarksActivityKeys.ADD_ENTRY, extraDataJSONObject.toString(), 0);
134    
135                    // Subscriptions
136    
137                    notifySubscribers(entry, serviceContext);
138    
139                    return entry;
140            }
141    
142            @Override
143            public void deleteEntries(long groupId, long folderId)
144                    throws PortalException, SystemException {
145    
146                    deleteEntries(groupId, folderId, true);
147            }
148    
149            @Override
150            public void deleteEntries(
151                            long groupId, long folderId, boolean includeTrashedEntries)
152                    throws PortalException, SystemException {
153    
154                    List<BookmarksEntry> entries = bookmarksEntryPersistence.findByG_F(
155                            groupId, folderId);
156    
157                    for (BookmarksEntry entry : entries) {
158                            if (includeTrashedEntries || !entry.isInTrash()) {
159                                    bookmarksEntryLocalService.deleteEntry(entry);
160                            }
161                    }
162            }
163    
164            @Indexable(type = IndexableType.DELETE)
165            @Override
166            public BookmarksEntry deleteEntry(BookmarksEntry entry)
167                    throws PortalException, SystemException {
168    
169                    // Entry
170    
171                    bookmarksEntryPersistence.remove(entry);
172    
173                    // Resources
174    
175                    resourceLocalService.deleteResource(
176                            entry, ResourceConstants.SCOPE_INDIVIDUAL);
177    
178                    // Asset
179    
180                    assetEntryLocalService.deleteEntry(
181                            BookmarksEntry.class.getName(), entry.getEntryId());
182    
183                    // Expando
184    
185                    expandoRowLocalService.deleteRows(entry.getEntryId());
186    
187                    // Subscriptions
188    
189                    subscriptionLocalService.deleteSubscriptions(
190                            entry.getCompanyId(), BookmarksEntry.class.getName(),
191                            entry.getEntryId());
192    
193                    // Trash
194    
195                    trashEntryLocalService.deleteEntry(
196                            BookmarksEntry.class.getName(), entry.getEntryId());
197    
198                    return entry;
199            }
200    
201            @Indexable(type = IndexableType.DELETE)
202            @Override
203            public BookmarksEntry deleteEntry(long entryId)
204                    throws PortalException, SystemException {
205    
206                    BookmarksEntry entry = bookmarksEntryPersistence.findByPrimaryKey(
207                            entryId);
208    
209                    return deleteEntry(entry);
210            }
211    
212            @Override
213            public List<BookmarksEntry> getEntries(
214                            long groupId, long folderId, int start, int end)
215                    throws SystemException {
216    
217                    return bookmarksEntryPersistence.findByG_F_S(
218                            groupId, folderId, WorkflowConstants.STATUS_APPROVED, start, end);
219            }
220    
221            @Override
222            public List<BookmarksEntry> getEntries(
223                            long groupId, long folderId, int start, int end,
224                            OrderByComparator orderByComparator)
225                    throws SystemException {
226    
227                    return bookmarksEntryPersistence.findByG_F_S(
228                            groupId, folderId, WorkflowConstants.STATUS_APPROVED, start, end,
229                            orderByComparator);
230            }
231    
232            @Override
233            public int getEntriesCount(long groupId, long folderId)
234                    throws SystemException {
235    
236                    return bookmarksEntryPersistence.countByG_F_S(
237                            groupId, folderId, WorkflowConstants.STATUS_APPROVED);
238            }
239    
240            @Override
241            public BookmarksEntry getEntry(long entryId)
242                    throws PortalException, SystemException {
243    
244                    return bookmarksEntryPersistence.findByPrimaryKey(entryId);
245            }
246    
247            @Override
248            public int getFoldersEntriesCount(long groupId, List<Long> folderIds)
249                    throws SystemException {
250    
251                    return bookmarksEntryPersistence.countByG_F_S(
252                            groupId,
253                            ArrayUtil.toArray(folderIds.toArray(new Long[folderIds.size()])),
254                            WorkflowConstants.STATUS_APPROVED);
255            }
256    
257            @Override
258            public List<BookmarksEntry> getGroupEntries(
259                            long groupId, int start, int end)
260                    throws SystemException {
261    
262                    return bookmarksEntryPersistence.findByG_S(
263                            groupId, WorkflowConstants.STATUS_APPROVED, start, end,
264                            new EntryModifiedDateComparator());
265            }
266    
267            @Override
268            public List<BookmarksEntry> getGroupEntries(
269                            long groupId, long userId, int start, int end)
270                    throws SystemException {
271    
272                    OrderByComparator orderByComparator = new EntryModifiedDateComparator();
273    
274                    if (userId <= 0) {
275                            return bookmarksEntryPersistence.findByG_S(
276                                    groupId, WorkflowConstants.STATUS_APPROVED, start, end,
277                                    orderByComparator);
278                    }
279                    else {
280                            return bookmarksEntryPersistence.findByG_U_S(
281                                    groupId, userId, WorkflowConstants.STATUS_APPROVED, start, end,
282                                    orderByComparator);
283                    }
284            }
285    
286            @Override
287            public int getGroupEntriesCount(long groupId) throws SystemException {
288                    return bookmarksEntryPersistence.countByG_S(
289                            groupId, WorkflowConstants.STATUS_APPROVED);
290            }
291    
292            @Override
293            public int getGroupEntriesCount(long groupId, long userId)
294                    throws SystemException {
295    
296                    if (userId <= 0) {
297                            return getGroupEntriesCount(groupId);
298                    }
299                    else {
300                            return bookmarksEntryPersistence.countByG_U_S(
301                                    groupId, userId, WorkflowConstants.STATUS_APPROVED);
302                    }
303            }
304    
305            @Override
306            public List<BookmarksEntry> getNoAssetEntries() throws SystemException {
307                    return bookmarksEntryFinder.findByNoAssets();
308            }
309    
310            @Indexable(type = IndexableType.REINDEX)
311            @Override
312            public BookmarksEntry moveEntry(long entryId, long parentFolderId)
313                    throws PortalException, SystemException {
314    
315                    BookmarksEntry entry = getBookmarksEntry(entryId);
316    
317                    entry.setFolderId(parentFolderId);
318                    entry.setTreePath(entry.buildTreePath());
319    
320                    bookmarksEntryPersistence.update(entry);
321    
322                    return entry;
323            }
324    
325            @Override
326            public BookmarksEntry moveEntryFromTrash(
327                            long userId, long entryId, long parentFolderId)
328                    throws PortalException, SystemException {
329    
330                    BookmarksEntry entry = getBookmarksEntry(entryId);
331    
332                    TrashEntry trashEntry = entry.getTrashEntry();
333    
334                    if (trashEntry.isTrashEntry(BookmarksEntry.class, entryId)) {
335                            restoreEntryFromTrash(userId, entryId);
336                    }
337                    else {
338    
339                            // Entry
340    
341                            TrashVersion trashVersion =
342                                    trashVersionLocalService.fetchVersion(
343                                            trashEntry.getEntryId(), BookmarksEntry.class.getName(),
344                                            entryId);
345    
346                            int status = WorkflowConstants.STATUS_APPROVED;
347    
348                            if (trashVersion != null) {
349                                    status = trashVersion.getStatus();
350                            }
351    
352                            updateStatus(userId, entry, status);
353    
354                            // Trash
355    
356                            if (trashVersion != null) {
357                                    trashVersionLocalService.deleteTrashVersion(trashVersion);
358                            }
359                    }
360    
361                    return bookmarksEntryLocalService.moveEntry(entryId, parentFolderId);
362            }
363    
364            @Indexable(type = IndexableType.REINDEX)
365            @Override
366            public BookmarksEntry moveEntryToTrash(long userId, BookmarksEntry entry)
367                    throws PortalException, SystemException {
368    
369                    int oldStatus = entry.getStatus();
370    
371                    entry = updateStatus(userId, entry, WorkflowConstants.STATUS_IN_TRASH);
372    
373                    trashEntryLocalService.addTrashEntry(
374                            userId, entry.getGroupId(), BookmarksEntry.class.getName(),
375                            entry.getEntryId(), entry.getUuid(), null, oldStatus, null, null);
376    
377                    return entry;
378            }
379    
380            @Indexable(type = IndexableType.REINDEX)
381            @Override
382            public BookmarksEntry moveEntryToTrash(long userId, long entryId)
383                    throws PortalException, SystemException {
384    
385                    BookmarksEntry entry = getEntry(entryId);
386    
387                    return moveEntryToTrash(userId, entry);
388            }
389    
390            @Override
391            public BookmarksEntry openEntry(long userId, BookmarksEntry entry)
392                    throws SystemException {
393    
394                    entry.setVisits(entry.getVisits() + 1);
395    
396                    bookmarksEntryPersistence.update(entry);
397    
398                    assetEntryLocalService.incrementViewCounter(
399                            userId, BookmarksEntry.class.getName(), entry.getEntryId(), 1);
400    
401                    return entry;
402            }
403    
404            @Override
405            public BookmarksEntry openEntry(long userId, long entryId)
406                    throws PortalException, SystemException {
407    
408                    BookmarksEntry entry = bookmarksEntryPersistence.findByPrimaryKey(
409                            entryId);
410    
411                    return openEntry(userId, entry);
412            }
413    
414            @Override
415            public void rebuildTree(long companyId)
416                    throws PortalException, SystemException {
417    
418                    List<BookmarksEntry> entries = bookmarksEntryPersistence.findByC_NotS(
419                            companyId, WorkflowConstants.STATUS_IN_TRASH);
420    
421                    for (BookmarksEntry entry : entries) {
422                            entry.setTreePath(entry.buildTreePath());
423    
424                            bookmarksEntryPersistence.update(entry);
425                    }
426            }
427    
428            @Indexable(type = IndexableType.REINDEX)
429            @Override
430            public BookmarksEntry restoreEntryFromTrash(long userId, long entryId)
431                    throws PortalException, SystemException {
432    
433                    BookmarksEntry entry = bookmarksEntryPersistence.findByPrimaryKey(
434                            entryId);
435    
436                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
437                            BookmarksEntry.class.getName(), entryId);
438    
439                    entry = updateStatus(userId, entry, trashEntry.getStatus());
440    
441                    trashEntryLocalService.deleteEntry(
442                            BookmarksEntry.class.getName(), entry.getEntryId());
443    
444                    return entry;
445            }
446    
447            @Override
448            public Hits search(
449                            long groupId, long userId, long creatorUserId, int status,
450                            int start, int end)
451                    throws PortalException, SystemException {
452    
453                    Indexer indexer = IndexerRegistryUtil.getIndexer(
454                            BookmarksEntry.class.getName());
455    
456                    SearchContext searchContext = new SearchContext();
457    
458                    searchContext.setAttribute(Field.STATUS, status);
459    
460                    if (creatorUserId > 0) {
461                            searchContext.setAttribute(
462                                    Field.USER_ID, String.valueOf(creatorUserId));
463                    }
464    
465                    searchContext.setAttribute("paginationType", "none");
466    
467                    Group group = groupLocalService.getGroup(groupId);
468    
469                    searchContext.setCompanyId(group.getCompanyId());
470    
471                    searchContext.setEnd(end);
472                    searchContext.setGroupIds(new long[] {groupId});
473                    searchContext.setSorts(new Sort(Field.MODIFIED_DATE, true));
474                    searchContext.setStart(start);
475                    searchContext.setUserId(userId);
476    
477                    return indexer.search(searchContext);
478            }
479    
480            @Override
481            public void subscribeEntry(long userId, long entryId)
482                    throws PortalException, SystemException {
483    
484                    BookmarksEntry entry = bookmarksEntryPersistence.findByPrimaryKey(
485                            entryId);
486    
487                    subscriptionLocalService.addSubscription(
488                            userId, entry.getGroupId(), BookmarksEntry.class.getName(),
489                            entryId);
490            }
491    
492            @Override
493            public void unsubscribeEntry(long userId, long entryId)
494                    throws PortalException, SystemException {
495    
496                    subscriptionLocalService.deleteSubscription(
497                            userId, BookmarksEntry.class.getName(), entryId);
498            }
499    
500            @Override
501            public void updateAsset(
502                            long userId, BookmarksEntry entry, long[] assetCategoryIds,
503                            String[] assetTagNames, long[] assetLinkEntryIds)
504                    throws PortalException, SystemException {
505    
506                    AssetEntry assetEntry = assetEntryLocalService.updateEntry(
507                            userId, entry.getGroupId(), entry.getCreateDate(),
508                            entry.getModifiedDate(), BookmarksEntry.class.getName(),
509                            entry.getEntryId(), entry.getUuid(), 0, assetCategoryIds,
510                            assetTagNames, true, null, null, null, ContentTypes.TEXT_PLAIN,
511                            entry.getName(), entry.getDescription(), null, entry.getUrl(), null,
512                            0, 0, null, false);
513    
514                    assetLinkLocalService.updateLinks(
515                            userId, assetEntry.getEntryId(), assetLinkEntryIds,
516                            AssetLinkConstants.TYPE_RELATED);
517            }
518    
519            @Indexable(type = IndexableType.REINDEX)
520            @Override
521            public BookmarksEntry updateEntry(
522                            long userId, long entryId, long groupId, long folderId, String name,
523                            String url, String description, ServiceContext serviceContext)
524                    throws PortalException, SystemException {
525    
526                    // Entry
527    
528                    BookmarksEntry entry = bookmarksEntryPersistence.findByPrimaryKey(
529                            entryId);
530    
531                    if (Validator.isNull(name)) {
532                            name = url;
533                    }
534    
535                    validate(url);
536    
537                    entry.setModifiedDate(serviceContext.getModifiedDate(null));
538                    entry.setFolderId(folderId);
539                    entry.setTreePath(entry.buildTreePath());
540                    entry.setName(name);
541                    entry.setUrl(url);
542                    entry.setDescription(description);
543                    entry.setExpandoBridgeAttributes(serviceContext);
544    
545                    bookmarksEntryPersistence.update(entry);
546    
547                    // Asset
548    
549                    updateAsset(
550                            userId, entry, serviceContext.getAssetCategoryIds(),
551                            serviceContext.getAssetTagNames(),
552                            serviceContext.getAssetLinkEntryIds());
553    
554                    // Social
555    
556                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
557    
558                    extraDataJSONObject.put("title", entry.getName());
559    
560                    socialActivityLocalService.addActivity(
561                            userId, entry.getGroupId(), BookmarksEntry.class.getName(), entryId,
562                            BookmarksActivityKeys.UPDATE_ENTRY, extraDataJSONObject.toString(),
563                            0);
564    
565                    // Subscriptions
566    
567                    notifySubscribers(entry, serviceContext);
568    
569                    return entry;
570            }
571    
572            @Override
573            public BookmarksEntry updateStatus(
574                            long userId, BookmarksEntry entry, int status)
575                    throws PortalException, SystemException {
576    
577                    // Entry
578    
579                    User user = userPersistence.findByPrimaryKey(userId);
580    
581                    entry.setStatus(status);
582                    entry.setStatusByUserId(userId);
583                    entry.setStatusByUserName(user.getScreenName());
584                    entry.setStatusDate(new Date());
585    
586                    bookmarksEntryPersistence.update(entry);
587    
588                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
589    
590                    extraDataJSONObject.put("title", entry.getName());
591    
592                    if (status == WorkflowConstants.STATUS_APPROVED) {
593    
594                            // Asset
595    
596                            assetEntryLocalService.updateVisible(
597                                    BookmarksEntry.class.getName(), entry.getEntryId(), true);
598    
599                            // Social
600    
601                            socialActivityLocalService.addActivity(
602                                    userId, entry.getGroupId(), BookmarksEntry.class.getName(),
603                                    entry.getEntryId(),
604                                    SocialActivityConstants.TYPE_RESTORE_FROM_TRASH,
605                                    extraDataJSONObject.toString(), 0);
606                    }
607                    else if (status == WorkflowConstants.STATUS_IN_TRASH) {
608    
609                            // Asset
610    
611                            assetEntryLocalService.updateVisible(
612                                    BookmarksEntry.class.getName(), entry.getEntryId(), false);
613    
614                            // Social
615    
616                            socialActivityLocalService.addActivity(
617                                    userId, entry.getGroupId(), BookmarksEntry.class.getName(),
618                                    entry.getEntryId(), SocialActivityConstants.TYPE_MOVE_TO_TRASH,
619                                    extraDataJSONObject.toString(), 0);
620                    }
621    
622                    return entry;
623            }
624    
625            protected long getFolder(BookmarksEntry entry, long folderId)
626                    throws SystemException {
627    
628                    if ((entry.getFolderId() != folderId) &&
629                            (folderId != BookmarksFolderConstants.DEFAULT_PARENT_FOLDER_ID)) {
630    
631                            BookmarksFolder newFolder =
632                                    bookmarksFolderPersistence.fetchByPrimaryKey(folderId);
633    
634                            if ((newFolder == null) ||
635                                    (entry.getGroupId() != newFolder.getGroupId())) {
636    
637                                    folderId = entry.getFolderId();
638                            }
639                    }
640    
641                    return folderId;
642            }
643    
644            protected void notifySubscribers(
645                            BookmarksEntry entry, ServiceContext serviceContext)
646                    throws PortalException, SystemException {
647    
648                    String layoutFullURL = serviceContext.getLayoutFullURL();
649    
650                    if (Validator.isNull(layoutFullURL)) {
651                            return;
652                    }
653    
654                    PortletPreferences preferences =
655                            ServiceContextUtil.getPortletPreferences(serviceContext);
656    
657                    if (preferences == null) {
658                            long ownerId = entry.getGroupId();
659                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
660                            long plid = PortletKeys.PREFS_PLID_SHARED;
661                            String portletId = PortletKeys.BOOKMARKS;
662                            String defaultPreferences = null;
663    
664                            preferences = portletPreferencesLocalService.getPreferences(
665                                    entry.getCompanyId(), ownerId, ownerType, plid, portletId,
666                                    defaultPreferences);
667                    }
668    
669                    if ((serviceContext.isCommandAdd() &&
670                             !BookmarksUtil.getEmailEntryAddedEnabled(preferences)) ||
671                            (serviceContext.isCommandUpdate() &&
672                             !BookmarksUtil.getEmailEntryUpdatedEnabled(preferences))) {
673    
674                            return;
675                    }
676    
677                    String statusByUserName = StringPool.BLANK;
678    
679                    try {
680                            User user = userLocalService.getUserById(
681                                    serviceContext.getGuestOrUserId());
682    
683                            statusByUserName = user.getFullName();
684                    }
685                    catch (Exception e) {
686                            _log.error(e, e);
687                    }
688    
689                    String entryURL =
690                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "bookmarks" +
691                                    StringPool.SLASH + entry.getEntryId();
692    
693                    String fromAddress = BookmarksUtil.getEmailFromAddress(
694                            preferences, entry.getCompanyId());
695                    String fromName = BookmarksUtil.getEmailFromName(
696                            preferences, entry.getCompanyId());
697    
698                    Map<Locale, String> localizedSubjectMap = null;
699                    Map<Locale, String> localizedBodyMap = null;
700    
701                    if (serviceContext.isCommandUpdate()) {
702                            localizedSubjectMap = BookmarksUtil.getEmailEntryUpdatedSubjectMap(
703                                    preferences);
704                            localizedBodyMap = BookmarksUtil.getEmailEntryUpdatedBodyMap(
705                                    preferences);
706                    }
707                    else {
708                            localizedSubjectMap = BookmarksUtil.getEmailEntryAddedSubjectMap(
709                                    preferences);
710                            localizedBodyMap = BookmarksUtil.getEmailEntryAddedBodyMap(
711                                    preferences);
712                    }
713    
714                    SubscriptionSender subscriptionSender = new SubscriptionSender();
715    
716                    subscriptionSender.setCompanyId(entry.getCompanyId());
717                    subscriptionSender.setContextAttributes(
718                            "[$BOOKMARKS_ENTRY_STATUS_BY_USER_NAME$]", statusByUserName,
719                            "[$BOOKMARKS_ENTRY_URL$]", entryURL);
720                    subscriptionSender.setContextUserPrefix("BOOKMARKS_ENTRY");
721                    subscriptionSender.setFrom(fromAddress, fromName);
722                    subscriptionSender.setHtmlFormat(true);
723                    subscriptionSender.setLocalizedBodyMap(localizedBodyMap);
724                    subscriptionSender.setLocalizedSubjectMap(localizedSubjectMap);
725                    subscriptionSender.setMailId("bookmarks_entry", entry.getEntryId());
726                    subscriptionSender.setPortletId(PortletKeys.BOOKMARKS);
727                    subscriptionSender.setReplyToAddress(fromAddress);
728                    subscriptionSender.setScopeGroupId(entry.getGroupId());
729                    subscriptionSender.setServiceContext(serviceContext);
730                    subscriptionSender.setUserId(entry.getUserId());
731    
732                    BookmarksFolder folder = entry.getFolder();
733    
734                    List<Long> folderIds = new ArrayList<Long>();
735    
736                    if (folder != null) {
737                            folderIds.add(folder.getFolderId());
738    
739                            folderIds.addAll(folder.getAncestorFolderIds());
740                    }
741    
742                    for (long curFolderId : folderIds) {
743                            subscriptionSender.addPersistedSubscribers(
744                                    BookmarksFolder.class.getName(), curFolderId);
745                    }
746    
747                    subscriptionSender.addPersistedSubscribers(
748                            BookmarksFolder.class.getName(), entry.getGroupId());
749    
750                    subscriptionSender.addPersistedSubscribers(
751                            BookmarksEntry.class.getName(), entry.getEntryId());
752    
753                    subscriptionSender.flushNotificationsAsync();
754            }
755    
756            protected void validate(String url) throws PortalException {
757                    if (!Validator.isUrl(url)) {
758                            throw new EntryURLException();
759                    }
760            }
761    
762            private static Log _log = LogFactoryUtil.getLog(
763                    BookmarksEntryLocalServiceImpl.class);
764    
765    }