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