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                    LinkedHashMap<String, Object> params =
410                            new LinkedHashMap<String, Object>();
411    
412                    params.put("announcementsDeliveryEmailOrSms", entry.getType());
413    
414                    if (classPK > 0) {
415                            if (className.equals(Group.class.getName())) {
416                                    Group group = groupPersistence.findByPrimaryKey(classPK);
417    
418                                    toName = group.getName();
419    
420                                    params.put("inherit", Boolean.TRUE);
421                                    params.put("usersGroups", classPK);
422                            }
423                            else if (className.equals(Organization.class.getName())) {
424                                    Organization organization =
425                                            organizationPersistence.findByPrimaryKey(classPK);
426    
427                                    toName = organization.getName();
428    
429                                    params.put(
430                                            "usersOrgsTree",
431                                            ListUtil.fromArray(new Organization[] {organization}));
432                            }
433                            else if (className.equals(Role.class.getName())) {
434                                    Role role = rolePersistence.findByPrimaryKey(classPK);
435    
436                                    toName = role.getName();
437    
438                                    if (role.getType() == RoleConstants.TYPE_REGULAR) {
439                                            params.put("inherit", Boolean.TRUE);
440                                            params.put("usersRoles", classPK);
441                                    }
442                                    else {
443                                            params.put(
444                                                    "userGroupRole", new Long[] {Long.valueOf(0), classPK});
445                                    }
446                            }
447                            else if (className.equals(UserGroup.class.getName())) {
448                                    UserGroup userGroup = userGroupPersistence.findByPrimaryKey(
449                                            classPK);
450    
451                                    toName = userGroup.getName();
452    
453                                    params.put("usersUserGroups", classPK);
454                            }
455                    }
456    
457                    if (className.equals(User.class.getName())) {
458                            User user = userPersistence.findByPrimaryKey(classPK);
459    
460                            if (Validator.isNull(user.getEmailAddress())) {
461                                    return;
462                            }
463    
464                            notifyUsers(
465                                    ListUtil.fromArray(new User[] {user}), entry,
466                                    company.getLocale(), user.getEmailAddress(),
467                                    user.getFullName());
468                    }
469                    else {
470                            int count = userLocalService.searchCount(
471                                    company.getCompanyId(), null, WorkflowConstants.STATUS_APPROVED,
472                                    params);
473    
474                            int pages = count / Indexer.DEFAULT_INTERVAL;
475    
476                            for (int i = 0; i <= pages; i++) {
477                                    int start = (i * Indexer.DEFAULT_INTERVAL);
478                                    int end = start + Indexer.DEFAULT_INTERVAL;
479    
480                                    List<User> users = userLocalService.search(
481                                            company.getCompanyId(), null,
482                                            WorkflowConstants.STATUS_APPROVED, params, start, end,
483                                            (OrderByComparator)null);
484    
485                                    notifyUsers(
486                                            users, entry, company.getLocale(), toAddress, toName);
487                            }
488                    }
489            }
490    
491            protected void notifyUsers(
492                            List<User> users, AnnouncementsEntry entry, Locale locale,
493                            String toAddress, String toName)
494                    throws PortalException, SystemException {
495    
496                    if (_log.isDebugEnabled()) {
497                            _log.debug("Notifying " + users.size() + " users");
498                    }
499    
500                    boolean notifyUsers = false;
501    
502                    SubscriptionSender subscriptionSender = new SubscriptionSender();
503    
504                    for (User user : users) {
505                            AnnouncementsDelivery announcementsDelivery =
506                                    announcementsDeliveryLocalService.getUserDelivery(
507                                            user.getUserId(), entry.getType());
508    
509                            if (announcementsDelivery.isEmail()) {
510                                    subscriptionSender.addRuntimeSubscribers(
511                                            user.getEmailAddress(), user.getFullName());
512    
513                                    notifyUsers = true;
514                            }
515    
516                            if (announcementsDelivery.isSms()) {
517                                    String smsSn = user.getContact().getSmsSn();
518    
519                                    subscriptionSender.addRuntimeSubscribers(
520                                            smsSn, user.getFullName());
521    
522                                    notifyUsers = true;
523                            }
524                    }
525    
526                    if (!notifyUsers) {
527                            return;
528                    }
529    
530                    String body = ContentUtil.get(PropsValues.ANNOUNCEMENTS_EMAIL_BODY);
531                    String fromAddress = PrefsPropsUtil.getStringFromNames(
532                            entry.getCompanyId(), PropsKeys.ANNOUNCEMENTS_EMAIL_FROM_ADDRESS,
533                            PropsKeys.ADMIN_EMAIL_FROM_ADDRESS);
534                    String fromName = PrefsPropsUtil.getStringFromNames(
535                            entry.getCompanyId(), PropsKeys.ANNOUNCEMENTS_EMAIL_FROM_NAME,
536                            PropsKeys.ADMIN_EMAIL_FROM_NAME);
537                    String subject = ContentUtil.get(
538                            PropsValues.ANNOUNCEMENTS_EMAIL_SUBJECT);
539    
540                    subscriptionSender.setBody(body);
541                    subscriptionSender.setCompanyId(entry.getCompanyId());
542                    subscriptionSender.setContextAttribute(
543                            "[$ENTRY_CONTENT$]", entry.getContent(), false);
544                    subscriptionSender.setContextAttributes(
545                            "[$ENTRY_ID$]", entry.getEntryId(), "[$ENTRY_TITLE$]",
546                            entry.getTitle(), "[$ENTRY_TYPE$]",
547                            LanguageUtil.get(locale, entry.getType()), "[$ENTRY_URL$]",
548                            entry.getUrl(), "[$PORTLET_NAME$]",
549                            LanguageUtil.get(
550                                    locale, (entry.isAlert() ? "alert" : "announcement")));
551                    subscriptionSender.setFrom(fromAddress, fromName);
552                    subscriptionSender.setHtmlFormat(true);
553                    subscriptionSender.setMailId("announcements_entry", entry.getEntryId());
554                    subscriptionSender.setPortletId(PortletKeys.ANNOUNCEMENTS);
555                    subscriptionSender.setScopeGroupId(entry.getGroupId());
556                    subscriptionSender.setSubject(subject);
557                    subscriptionSender.setUserId(entry.getUserId());
558    
559                    subscriptionSender.addRuntimeSubscribers(toAddress, toName);
560    
561                    subscriptionSender.flushNotificationsAsync();
562            }
563    
564            protected void validate(String title, String content, String url)
565                    throws PortalException {
566    
567                    if (Validator.isNull(title)) {
568                            throw new EntryTitleException();
569                    }
570    
571                    if (Validator.isNull(content)) {
572                            throw new EntryContentException();
573                    }
574    
575                    if (Validator.isNotNull(url) && !Validator.isUrl(url)) {
576                            throw new EntryURLException();
577                    }
578            }
579    
580            private static final long _ANNOUNCEMENTS_ENTRY_CHECK_INTERVAL =
581                    PropsValues.ANNOUNCEMENTS_ENTRY_CHECK_INTERVAL * Time.MINUTE;
582    
583            private static Log _log = LogFactoryUtil.getLog(
584                    AnnouncementsEntryLocalServiceImpl.class);
585    
586            private Date _previousCheckDate;
587    
588    }