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