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.announcements.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.language.LanguageUtil;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.search.Indexer;
023    import com.liferay.portal.kernel.util.ListUtil;
024    import com.liferay.portal.kernel.util.OrderByComparator;
025    import com.liferay.portal.kernel.util.PropsKeys;
026    import com.liferay.portal.kernel.util.Time;
027    import com.liferay.portal.kernel.util.Validator;
028    import com.liferay.portal.kernel.workflow.WorkflowConstants;
029    import com.liferay.portal.model.Company;
030    import com.liferay.portal.model.Group;
031    import com.liferay.portal.model.Organization;
032    import com.liferay.portal.model.ResourceConstants;
033    import com.liferay.portal.model.Role;
034    import com.liferay.portal.model.RoleConstants;
035    import com.liferay.portal.model.User;
036    import com.liferay.portal.model.UserGroup;
037    import com.liferay.portal.util.PortalUtil;
038    import com.liferay.portal.util.PortletKeys;
039    import com.liferay.portal.util.PrefsPropsUtil;
040    import com.liferay.portal.util.PropsValues;
041    import com.liferay.portal.util.SubscriptionSender;
042    import com.liferay.portlet.announcements.EntryContentException;
043    import com.liferay.portlet.announcements.EntryDisplayDateException;
044    import com.liferay.portlet.announcements.EntryExpirationDateException;
045    import com.liferay.portlet.announcements.EntryTitleException;
046    import com.liferay.portlet.announcements.EntryURLException;
047    import com.liferay.portlet.announcements.model.AnnouncementsDelivery;
048    import com.liferay.portlet.announcements.model.AnnouncementsEntry;
049    import com.liferay.portlet.announcements.service.base.AnnouncementsEntryLocalServiceBaseImpl;
050    import com.liferay.util.ContentUtil;
051    
052    import java.util.Date;
053    import java.util.LinkedHashMap;
054    import java.util.List;
055    import java.util.Locale;
056    
057    /**
058     * @author Brian Wing Shun Chan
059     * @author Raymond Aug??
060     */
061    public class AnnouncementsEntryLocalServiceImpl
062            extends AnnouncementsEntryLocalServiceBaseImpl {
063    
064            @Override
065            public AnnouncementsEntry addEntry(
066                            long userId, long classNameId, long classPK, String title,
067                            String content, String url, String type, int displayDateMonth,
068                            int displayDateDay, int displayDateYear, int displayDateHour,
069                            int displayDateMinute, boolean displayImmediately,
070                            int expirationDateMonth, int expirationDateDay,
071                            int expirationDateYear, int expirationDateHour,
072                            int expirationDateMinute, int priority, boolean alert)
073                    throws PortalException, SystemException {
074    
075                    // Entry
076    
077                    User user = userPersistence.findByPrimaryKey(userId);
078    
079                    Date now = new Date();
080    
081                    Date displayDate = now;
082    
083                    if (!displayImmediately) {
084                            displayDate = PortalUtil.getDate(
085                                    displayDateMonth, displayDateDay, displayDateYear,
086                                    displayDateHour, displayDateMinute, user.getTimeZone(),
087                                    EntryDisplayDateException.class);
088                    }
089    
090                    Date expirationDate = PortalUtil.getDate(
091                            expirationDateMonth, expirationDateDay, expirationDateYear,
092                            expirationDateHour, expirationDateMinute, user.getTimeZone(),
093                            EntryExpirationDateException.class);
094    
095                    validate(title, content, url);
096    
097                    long entryId = counterLocalService.increment();
098    
099                    AnnouncementsEntry entry = announcementsEntryPersistence.create(
100                            entryId);
101    
102                    entry.setCompanyId(user.getCompanyId());
103                    entry.setUserId(user.getUserId());
104                    entry.setUserName(user.getFullName());
105                    entry.setCreateDate(now);
106                    entry.setModifiedDate(now);
107                    entry.setClassNameId(classNameId);
108                    entry.setClassPK(classPK);
109                    entry.setTitle(title);
110                    entry.setContent(content);
111                    entry.setUrl(url);
112                    entry.setType(type);
113                    entry.setDisplayDate(displayDate);
114                    entry.setExpirationDate(expirationDate);
115                    entry.setPriority(priority);
116                    entry.setAlert(alert);
117    
118                    announcementsEntryPersistence.update(entry);
119    
120                    // Resources
121    
122                    resourceLocalService.addResources(
123                            user.getCompanyId(), 0, user.getUserId(),
124                            AnnouncementsEntry.class.getName(), entry.getEntryId(), false,
125                            false, false);
126    
127                    return entry;
128            }
129    
130            /**
131             * @deprecated As of 6.2.0, replaced by {@link #addEntry(long, long, long,
132             *             String, String, String, String, int, int, int, int, int,
133             *             boolean, int, int, int, int, int, int, boolean)}
134             */
135            @Override
136            public AnnouncementsEntry addEntry(
137                            long userId, long classNameId, long classPK, String title,
138                            String content, String url, String type, int displayDateMonth,
139                            int displayDateDay, int displayDateYear, int displayDateHour,
140                            int displayDateMinute, int expirationDateMonth,
141                            int expirationDateDay, int expirationDateYear,
142                            int expirationDateHour, int expirationDateMinute, int priority,
143                            boolean alert)
144                    throws PortalException, SystemException {
145    
146                    return addEntry(
147                            userId, classNameId, classPK, title, content, url, type,
148                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
149                            displayDateMinute, false, expirationDateMonth, expirationDateDay,
150                            expirationDateYear, expirationDateHour, expirationDateMinute,
151                            priority, alert);
152            }
153    
154            @Override
155            public void checkEntries() throws PortalException, SystemException {
156                    Date now = new Date();
157    
158                    if (_previousCheckDate == null) {
159                            _previousCheckDate = new Date(
160                                    now.getTime() - _ANNOUNCEMENTS_ENTRY_CHECK_INTERVAL);
161                    }
162    
163                    List<AnnouncementsEntry> entries =
164                            announcementsEntryFinder.findByDisplayDate(now, _previousCheckDate);
165    
166                    if (_log.isDebugEnabled()) {
167                            _log.debug("Processing " + entries.size() + " entries");
168                    }
169    
170                    for (AnnouncementsEntry entry : entries) {
171                            notifyUsers(entry);
172                    }
173    
174                    _previousCheckDate = now;
175            }
176    
177            @Override
178            public void deleteEntry(AnnouncementsEntry entry)
179                    throws PortalException, SystemException {
180    
181                    // Entry
182    
183                    announcementsEntryPersistence.remove(entry);
184    
185                    // Resources
186    
187                    resourceLocalService.deleteResource(
188                            entry.getCompanyId(), AnnouncementsEntry.class.getName(),
189                            ResourceConstants.SCOPE_INDIVIDUAL, entry.getEntryId());
190    
191                    // Flags
192    
193                    announcementsFlagLocalService.deleteFlags(entry.getEntryId());
194            }
195    
196            @Override
197            public void deleteEntry(long entryId)
198                    throws PortalException, SystemException {
199    
200                    AnnouncementsEntry entry =
201                            announcementsEntryPersistence.findByPrimaryKey(entryId);
202    
203                    deleteEntry(entry);
204            }
205    
206            @Override
207            public List<AnnouncementsEntry> getEntries(
208                            long userId, LinkedHashMap<Long, long[]> scopes, boolean alert,
209                            int flagValue, int start, int end)
210                    throws SystemException {
211    
212                    return getEntries(
213                            userId, scopes, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, alert, flagValue,
214                            start, end);
215            }
216    
217            @Override
218            public List<AnnouncementsEntry> getEntries(
219                            long userId, LinkedHashMap<Long, long[]> scopes,
220                            int displayDateMonth, int displayDateDay, int displayDateYear,
221                            int displayDateHour, int displayDateMinute, int expirationDateMonth,
222                            int expirationDateDay, int expirationDateYear,
223                            int expirationDateHour, int expirationDateMinute, boolean alert,
224                            int flagValue, int start, int end)
225                    throws SystemException {
226    
227                    return announcementsEntryFinder.findByScopes(
228                            userId, scopes, displayDateMonth, displayDateDay, displayDateYear,
229                            displayDateHour, displayDateMinute, expirationDateMonth,
230                            expirationDateDay, expirationDateYear, expirationDateHour,
231                            expirationDateMinute, alert, flagValue, start, end);
232            }
233    
234            @Override
235            public List<AnnouncementsEntry> getEntries(
236                            long classNameId, long classPK, boolean alert, int start, int end)
237                    throws SystemException {
238    
239                    return announcementsEntryPersistence.findByC_C_A(
240                            classNameId, classPK, alert, start, end);
241            }
242    
243            @Override
244            public List<AnnouncementsEntry> getEntries(
245                            long userId, long classNameId, long[] classPKs,
246                            int displayDateMonth, int displayDateDay, int displayDateYear,
247                            int displayDateHour, int displayDateMinute, int expirationDateMonth,
248                            int expirationDateDay, int expirationDateYear,
249                            int expirationDateHour, int expirationDateMinute, boolean alert,
250                            int flagValue, int start, int end)
251                    throws SystemException {
252    
253                    return announcementsEntryFinder.findByScope(
254                            userId, classNameId, classPKs, displayDateMonth, displayDateDay,
255                            displayDateYear, displayDateHour, displayDateMinute,
256                            expirationDateMonth, expirationDateDay, expirationDateYear,
257                            expirationDateHour, expirationDateMinute, alert, flagValue, start,
258                            end);
259            }
260    
261            @Override
262            public int getEntriesCount(
263                            long userId, LinkedHashMap<Long, long[]> scopes, boolean alert,
264                            int flagValue)
265                    throws SystemException {
266    
267                    return getEntriesCount(
268                            userId, scopes, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, alert, flagValue);
269            }
270    
271            @Override
272            public int getEntriesCount(
273                            long userId, LinkedHashMap<Long, long[]> scopes,
274                            int displayDateMonth, int displayDateDay, int displayDateYear,
275                            int displayDateHour, int displayDateMinute, int expirationDateMonth,
276                            int expirationDateDay, int expirationDateYear,
277                            int expirationDateHour, int expirationDateMinute, boolean alert,
278                            int flagValue)
279                    throws SystemException {
280    
281                    return announcementsEntryFinder.countByScopes(
282                            userId, scopes, displayDateMonth, displayDateDay, displayDateYear,
283                            displayDateHour, displayDateMinute, expirationDateMonth,
284                            expirationDateDay, expirationDateYear, expirationDateHour,
285                            expirationDateMinute, alert, flagValue);
286            }
287    
288            @Override
289            public int getEntriesCount(long classNameId, long classPK, boolean alert)
290                    throws SystemException {
291    
292                    return announcementsEntryPersistence.countByC_C_A(
293                            classNameId, classPK, alert);
294            }
295    
296            @Override
297            public int getEntriesCount(
298                            long userId, long classNameId, long[] classPKs, boolean alert,
299                            int flagValue)
300                    throws SystemException {
301    
302                    return getEntriesCount(
303                            userId, classNameId, classPKs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, alert,
304                            flagValue);
305            }
306    
307            @Override
308            public int getEntriesCount(
309                            long userId, long classNameId, long[] classPKs,
310                            int displayDateMonth, int displayDateDay, int displayDateYear,
311                            int displayDateHour, int displayDateMinute, int expirationDateMonth,
312                            int expirationDateDay, int expirationDateYear,
313                            int expirationDateHour, int expirationDateMinute, boolean alert,
314                            int flagValue)
315                    throws SystemException {
316    
317                    return announcementsEntryFinder.countByScope(
318                            userId, classNameId, classPKs, displayDateMonth, displayDateDay,
319                            displayDateYear, displayDateHour, displayDateMinute,
320                            expirationDateMonth, expirationDateDay, expirationDateYear,
321                            expirationDateHour, expirationDateMinute, alert, flagValue);
322            }
323    
324            @Override
325            public AnnouncementsEntry getEntry(long entryId)
326                    throws PortalException, SystemException {
327    
328                    return announcementsEntryPersistence.findByPrimaryKey(entryId);
329            }
330    
331            @Override
332            public List<AnnouncementsEntry> getUserEntries(
333                            long userId, int start, int end)
334                    throws SystemException {
335    
336                    return announcementsEntryPersistence.findByUserId(userId, start, end);
337            }
338    
339            @Override
340            public int getUserEntriesCount(long userId) throws SystemException {
341                    return announcementsEntryPersistence.countByUserId(userId);
342            }
343    
344            @Override
345            public AnnouncementsEntry updateEntry(
346                            long userId, long entryId, String title, String content, String url,
347                            String type, int displayDateMonth, int displayDateDay,
348                            int displayDateYear, int displayDateHour, int displayDateMinute,
349                            boolean displayImmediately, int expirationDateMonth,
350                            int expirationDateDay, int expirationDateYear,
351                            int expirationDateHour, int expirationDateMinute, int priority)
352                    throws PortalException, SystemException {
353    
354                    // Entry
355    
356                    User user = userPersistence.findByPrimaryKey(userId);
357    
358                    Date now = new Date();
359    
360                    Date displayDate = now;
361    
362                    if (!displayImmediately) {
363                            displayDate = PortalUtil.getDate(
364                                    displayDateMonth, displayDateDay, displayDateYear,
365                                    displayDateHour, displayDateMinute, user.getTimeZone(),
366                                    EntryDisplayDateException.class);
367                    }
368    
369                    Date expirationDate = PortalUtil.getDate(
370                            expirationDateMonth, expirationDateDay, expirationDateYear,
371                            expirationDateHour, expirationDateMinute, user.getTimeZone(),
372                            EntryExpirationDateException.class);
373    
374                    validate(title, content, url);
375    
376                    AnnouncementsEntry entry =
377                            announcementsEntryPersistence.findByPrimaryKey(entryId);
378    
379                    entry.setModifiedDate(now);
380                    entry.setTitle(title);
381                    entry.setContent(content);
382                    entry.setUrl(url);
383                    entry.setType(type);
384                    entry.setDisplayDate(displayDate);
385                    entry.setExpirationDate(expirationDate);
386                    entry.setPriority(priority);
387    
388                    announcementsEntryPersistence.update(entry);
389    
390                    // Flags
391    
392                    announcementsFlagLocalService.deleteFlags(entry.getEntryId());
393    
394                    return entry;
395            }
396    
397            protected void notifyUsers(AnnouncementsEntry entry)
398                    throws PortalException, SystemException {
399    
400                    Company company = companyPersistence.findByPrimaryKey(
401                            entry.getCompanyId());
402    
403                    String className = entry.getClassName();
404                    long classPK = entry.getClassPK();
405    
406                    String toName = PropsValues.ANNOUNCEMENTS_EMAIL_TO_NAME;
407                    String toAddress = PropsValues.ANNOUNCEMENTS_EMAIL_TO_ADDRESS;
408    
409                    long teamId = 0;
410    
411                    LinkedHashMap<String, Object> params =
412                            new LinkedHashMap<String, Object>();
413    
414                    params.put("announcementsDeliveryEmailOrSms", entry.getType());
415    
416                    if (classPK > 0) {
417                            if (className.equals(Group.class.getName())) {
418                                    Group group = groupPersistence.findByPrimaryKey(classPK);
419    
420                                    toName = group.getName();
421    
422                                    params.put("inherit", Boolean.TRUE);
423                                    params.put("usersGroups", classPK);
424                            }
425                            else if (className.equals(Organization.class.getName())) {
426                                    Organization organization =
427                                            organizationPersistence.findByPrimaryKey(classPK);
428    
429                                    toName = organization.getName();
430    
431                                    params.put(
432                                            "usersOrgsTree",
433                                            ListUtil.fromArray(new Organization[] {organization}));
434                            }
435                            else if (className.equals(Role.class.getName())) {
436                                    Role role = rolePersistence.findByPrimaryKey(classPK);
437    
438                                    toName = role.getName();
439    
440                                    if (role.getType() == RoleConstants.TYPE_REGULAR) {
441                                            params.put("inherit", Boolean.TRUE);
442                                            params.put("usersRoles", classPK);
443                                    }
444                                    else if (role.isTeam()) {
445                                            teamId = role.getClassPK();
446                                    }
447                                    else {
448                                            params.put(
449                                                    "userGroupRole", new Long[] {Long.valueOf(0), classPK});
450                                    }
451                            }
452                            else if (className.equals(UserGroup.class.getName())) {
453                                    UserGroup userGroup = userGroupPersistence.findByPrimaryKey(
454                                            classPK);
455    
456                                    toName = userGroup.getName();
457    
458                                    params.put("usersUserGroups", classPK);
459                            }
460                    }
461    
462                    if (className.equals(User.class.getName())) {
463                            User user = userPersistence.findByPrimaryKey(classPK);
464    
465                            if (Validator.isNull(user.getEmailAddress())) {
466                                    return;
467                            }
468    
469                            notifyUsers(
470                                    ListUtil.fromArray(new User[] {user}), entry,
471                                    company.getLocale(), user.getEmailAddress(),
472                                    user.getFullName());
473                    }
474                    else {
475                            int count = 0;
476    
477                            if (teamId > 0) {
478                                    count = userLocalService.getTeamUsersCount(teamId);
479                            }
480                            else {
481                                    count = userLocalService.searchCount(
482                                            company.getCompanyId(), null,
483                                            WorkflowConstants.STATUS_APPROVED, params);
484                            }
485    
486                            int pages = count / Indexer.DEFAULT_INTERVAL;
487    
488                            for (int i = 0; i <= pages; i++) {
489                                    int start = (i * Indexer.DEFAULT_INTERVAL);
490                                    int end = start + Indexer.DEFAULT_INTERVAL;
491    
492                                    List<User> users = null;
493    
494                                    if (teamId > 0) {
495                                            users = userLocalService.getTeamUsers(teamId, start, end);
496                                    }
497                                    else {
498                                            users = userLocalService.search(
499                                                    company.getCompanyId(), null,
500                                                    WorkflowConstants.STATUS_APPROVED, params, start, end,
501                                                    (OrderByComparator)null);
502                                    }
503    
504                                    notifyUsers(
505                                            users, entry, company.getLocale(), toAddress, toName);
506                            }
507                    }
508            }
509    
510            protected void notifyUsers(
511                            List<User> users, AnnouncementsEntry entry, Locale locale,
512                            String toAddress, String toName)
513                    throws PortalException, SystemException {
514    
515                    if (_log.isDebugEnabled()) {
516                            _log.debug("Notifying " + users.size() + " users");
517                    }
518    
519                    boolean notifyUsers = false;
520    
521                    SubscriptionSender subscriptionSender = new SubscriptionSender();
522    
523                    for (User user : users) {
524                            AnnouncementsDelivery announcementsDelivery =
525                                    announcementsDeliveryLocalService.getUserDelivery(
526                                            user.getUserId(), entry.getType());
527    
528                            if (announcementsDelivery.isEmail()) {
529                                    subscriptionSender.addRuntimeSubscribers(
530                                            user.getEmailAddress(), user.getFullName());
531    
532                                    notifyUsers = true;
533                            }
534    
535                            if (announcementsDelivery.isSms()) {
536                                    String smsSn = user.getContact().getSmsSn();
537    
538                                    subscriptionSender.addRuntimeSubscribers(
539                                            smsSn, user.getFullName());
540    
541                                    notifyUsers = true;
542                            }
543                    }
544    
545                    if (!notifyUsers) {
546                            return;
547                    }
548    
549                    String body = ContentUtil.get(PropsValues.ANNOUNCEMENTS_EMAIL_BODY);
550                    String fromAddress = PrefsPropsUtil.getStringFromNames(
551                            entry.getCompanyId(), PropsKeys.ANNOUNCEMENTS_EMAIL_FROM_ADDRESS,
552                            PropsKeys.ADMIN_EMAIL_FROM_ADDRESS);
553                    String fromName = PrefsPropsUtil.getStringFromNames(
554                            entry.getCompanyId(), PropsKeys.ANNOUNCEMENTS_EMAIL_FROM_NAME,
555                            PropsKeys.ADMIN_EMAIL_FROM_NAME);
556                    String subject = ContentUtil.get(
557                            PropsValues.ANNOUNCEMENTS_EMAIL_SUBJECT);
558    
559                    subscriptionSender.setBody(body);
560                    subscriptionSender.setCompanyId(entry.getCompanyId());
561                    subscriptionSender.setContextAttribute(
562                            "[$ENTRY_CONTENT$]", entry.getContent(), false);
563                    subscriptionSender.setContextAttributes(
564                            "[$ENTRY_ID$]", entry.getEntryId(), "[$ENTRY_TITLE$]",
565                            entry.getTitle(), "[$ENTRY_TYPE$]",
566                            LanguageUtil.get(locale, entry.getType()), "[$ENTRY_URL$]",
567                            entry.getUrl(), "[$PORTLET_NAME$]",
568                            LanguageUtil.get(
569                                    locale, (entry.isAlert() ? "alert" : "announcement")));
570                    subscriptionSender.setFrom(fromAddress, fromName);
571                    subscriptionSender.setHtmlFormat(true);
572                    subscriptionSender.setMailId("announcements_entry", entry.getEntryId());
573                    subscriptionSender.setPortletId(PortletKeys.ANNOUNCEMENTS);
574                    subscriptionSender.setScopeGroupId(entry.getGroupId());
575                    subscriptionSender.setSubject(subject);
576                    subscriptionSender.setUserId(entry.getUserId());
577    
578                    subscriptionSender.addRuntimeSubscribers(toAddress, toName);
579    
580                    subscriptionSender.flushNotificationsAsync();
581            }
582    
583            protected void validate(String title, String content, String url)
584                    throws PortalException {
585    
586                    if (Validator.isNull(title)) {
587                            throw new EntryTitleException();
588                    }
589    
590                    if (Validator.isNull(content)) {
591                            throw new EntryContentException();
592                    }
593    
594                    if (Validator.isNotNull(url) && !Validator.isUrl(url)) {
595                            throw new EntryURLException();
596                    }
597            }
598    
599            private static final long _ANNOUNCEMENTS_ENTRY_CHECK_INTERVAL =
600                    PropsValues.ANNOUNCEMENTS_ENTRY_CHECK_INTERVAL * Time.MINUTE;
601    
602            private static Log _log = LogFactoryUtil.getLog(
603                    AnnouncementsEntryLocalServiceImpl.class);
604    
605            private Date _previousCheckDate;
606    
607    }