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.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, displayDate, expirationDate);
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 void deleteEntries(long classNameId, long classPK)
208                    throws PortalException, SystemException {
209    
210                    List<AnnouncementsEntry> entries =
211                                    announcementsEntryPersistence.findByC_C(classNameId, classPK);
212    
213                    for (AnnouncementsEntry entry : entries) {
214                            deleteEntry(entry);
215                    }
216            }
217    
218            @Override
219            public List<AnnouncementsEntry> getEntries(
220                            long userId, LinkedHashMap<Long, long[]> scopes, boolean alert,
221                            int flagValue, int start, int end)
222                    throws SystemException {
223    
224                    return getEntries(
225                            userId, scopes, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, alert, flagValue,
226                            start, end);
227            }
228    
229            @Override
230            public List<AnnouncementsEntry> getEntries(
231                            long userId, LinkedHashMap<Long, long[]> scopes,
232                            int displayDateMonth, int displayDateDay, int displayDateYear,
233                            int displayDateHour, int displayDateMinute, int expirationDateMonth,
234                            int expirationDateDay, int expirationDateYear,
235                            int expirationDateHour, int expirationDateMinute, boolean alert,
236                            int flagValue, int start, int end)
237                    throws SystemException {
238    
239                    return announcementsEntryFinder.findByScopes(
240                            userId, scopes, displayDateMonth, displayDateDay, displayDateYear,
241                            displayDateHour, displayDateMinute, expirationDateMonth,
242                            expirationDateDay, expirationDateYear, expirationDateHour,
243                            expirationDateMinute, alert, flagValue, start, end);
244            }
245    
246            @Override
247            public List<AnnouncementsEntry> getEntries(
248                            long classNameId, long classPK, boolean alert, int start, int end)
249                    throws SystemException {
250    
251                    return announcementsEntryPersistence.findByC_C_A(
252                            classNameId, classPK, alert, start, end);
253            }
254    
255            @Override
256            public List<AnnouncementsEntry> getEntries(
257                            long userId, long classNameId, long[] classPKs,
258                            int displayDateMonth, int displayDateDay, int displayDateYear,
259                            int displayDateHour, int displayDateMinute, int expirationDateMonth,
260                            int expirationDateDay, int expirationDateYear,
261                            int expirationDateHour, int expirationDateMinute, boolean alert,
262                            int flagValue, int start, int end)
263                    throws SystemException {
264    
265                    return announcementsEntryFinder.findByScope(
266                            userId, classNameId, classPKs, displayDateMonth, displayDateDay,
267                            displayDateYear, displayDateHour, displayDateMinute,
268                            expirationDateMonth, expirationDateDay, expirationDateYear,
269                            expirationDateHour, expirationDateMinute, alert, flagValue, start,
270                            end);
271            }
272    
273            @Override
274            public int getEntriesCount(
275                            long userId, LinkedHashMap<Long, long[]> scopes, boolean alert,
276                            int flagValue)
277                    throws SystemException {
278    
279                    return getEntriesCount(
280                            userId, scopes, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, alert, flagValue);
281            }
282    
283            @Override
284            public int getEntriesCount(
285                            long userId, LinkedHashMap<Long, long[]> scopes,
286                            int displayDateMonth, int displayDateDay, int displayDateYear,
287                            int displayDateHour, int displayDateMinute, int expirationDateMonth,
288                            int expirationDateDay, int expirationDateYear,
289                            int expirationDateHour, int expirationDateMinute, boolean alert,
290                            int flagValue)
291                    throws SystemException {
292    
293                    return announcementsEntryFinder.countByScopes(
294                            userId, scopes, displayDateMonth, displayDateDay, displayDateYear,
295                            displayDateHour, displayDateMinute, expirationDateMonth,
296                            expirationDateDay, expirationDateYear, expirationDateHour,
297                            expirationDateMinute, alert, flagValue);
298            }
299    
300            @Override
301            public int getEntriesCount(long classNameId, long classPK, boolean alert)
302                    throws SystemException {
303    
304                    return announcementsEntryPersistence.countByC_C_A(
305                            classNameId, classPK, alert);
306            }
307    
308            @Override
309            public int getEntriesCount(
310                            long userId, long classNameId, long[] classPKs, boolean alert,
311                            int flagValue)
312                    throws SystemException {
313    
314                    return getEntriesCount(
315                            userId, classNameId, classPKs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, alert,
316                            flagValue);
317            }
318    
319            @Override
320            public int getEntriesCount(
321                            long userId, long classNameId, long[] classPKs,
322                            int displayDateMonth, int displayDateDay, int displayDateYear,
323                            int displayDateHour, int displayDateMinute, int expirationDateMonth,
324                            int expirationDateDay, int expirationDateYear,
325                            int expirationDateHour, int expirationDateMinute, boolean alert,
326                            int flagValue)
327                    throws SystemException {
328    
329                    return announcementsEntryFinder.countByScope(
330                            userId, classNameId, classPKs, displayDateMonth, displayDateDay,
331                            displayDateYear, displayDateHour, displayDateMinute,
332                            expirationDateMonth, expirationDateDay, expirationDateYear,
333                            expirationDateHour, expirationDateMinute, alert, flagValue);
334            }
335    
336            @Override
337            public AnnouncementsEntry getEntry(long entryId)
338                    throws PortalException, SystemException {
339    
340                    return announcementsEntryPersistence.findByPrimaryKey(entryId);
341            }
342    
343            @Override
344            public List<AnnouncementsEntry> getUserEntries(
345                            long userId, int start, int end)
346                    throws SystemException {
347    
348                    return announcementsEntryPersistence.findByUserId(userId, start, end);
349            }
350    
351            @Override
352            public int getUserEntriesCount(long userId) throws SystemException {
353                    return announcementsEntryPersistence.countByUserId(userId);
354            }
355    
356            @Override
357            public AnnouncementsEntry updateEntry(
358                            long userId, long entryId, String title, String content, String url,
359                            String type, int displayDateMonth, int displayDateDay,
360                            int displayDateYear, int displayDateHour, int displayDateMinute,
361                            boolean displayImmediately, int expirationDateMonth,
362                            int expirationDateDay, int expirationDateYear,
363                            int expirationDateHour, int expirationDateMinute, int priority)
364                    throws PortalException, SystemException {
365    
366                    // Entry
367    
368                    User user = userPersistence.findByPrimaryKey(userId);
369    
370                    Date now = new Date();
371    
372                    Date displayDate = now;
373    
374                    if (!displayImmediately) {
375                            displayDate = PortalUtil.getDate(
376                                    displayDateMonth, displayDateDay, displayDateYear,
377                                    displayDateHour, displayDateMinute, user.getTimeZone(),
378                                    EntryDisplayDateException.class);
379                    }
380    
381                    Date expirationDate = PortalUtil.getDate(
382                            expirationDateMonth, expirationDateDay, expirationDateYear,
383                            expirationDateHour, expirationDateMinute, user.getTimeZone(),
384                            EntryExpirationDateException.class);
385    
386                    validate(title, content, url, displayDate, expirationDate);
387    
388                    AnnouncementsEntry entry =
389                            announcementsEntryPersistence.findByPrimaryKey(entryId);
390    
391                    entry.setModifiedDate(now);
392                    entry.setTitle(title);
393                    entry.setContent(content);
394                    entry.setUrl(url);
395                    entry.setType(type);
396                    entry.setDisplayDate(displayDate);
397                    entry.setExpirationDate(expirationDate);
398                    entry.setPriority(priority);
399    
400                    announcementsEntryPersistence.update(entry);
401    
402                    // Flags
403    
404                    announcementsFlagLocalService.deleteFlags(entry.getEntryId());
405    
406                    return entry;
407            }
408    
409            protected void notifyUsers(AnnouncementsEntry entry)
410                    throws PortalException, SystemException {
411    
412                    Company company = companyPersistence.findByPrimaryKey(
413                            entry.getCompanyId());
414    
415                    String className = entry.getClassName();
416                    long classPK = entry.getClassPK();
417    
418                    String toName = PropsValues.ANNOUNCEMENTS_EMAIL_TO_NAME;
419                    String toAddress = PropsValues.ANNOUNCEMENTS_EMAIL_TO_ADDRESS;
420    
421                    long teamId = 0;
422    
423                    LinkedHashMap<String, Object> params =
424                            new LinkedHashMap<String, Object>();
425    
426                    params.put("announcementsDeliveryEmailOrSms", entry.getType());
427    
428                    if (classPK > 0) {
429                            if (className.equals(Group.class.getName())) {
430                                    Group group = groupPersistence.findByPrimaryKey(classPK);
431    
432                                    toName = group.getName();
433    
434                                    params.put("inherit", Boolean.TRUE);
435                                    params.put("usersGroups", classPK);
436                            }
437                            else if (className.equals(Organization.class.getName())) {
438                                    Organization organization =
439                                            organizationPersistence.findByPrimaryKey(classPK);
440    
441                                    toName = organization.getName();
442    
443                                    params.put(
444                                            "usersOrgsTree",
445                                            ListUtil.fromArray(new Organization[] {organization}));
446                            }
447                            else if (className.equals(Role.class.getName())) {
448                                    Role role = rolePersistence.findByPrimaryKey(classPK);
449    
450                                    toName = role.getName();
451    
452                                    if (role.getType() == RoleConstants.TYPE_REGULAR) {
453                                            params.put("inherit", Boolean.TRUE);
454                                            params.put("usersRoles", classPK);
455                                    }
456                                    else if (role.isTeam()) {
457                                            teamId = role.getClassPK();
458                                    }
459                                    else {
460                                            params.put(
461                                                    "userGroupRole", new Long[] {Long.valueOf(0), classPK});
462                                    }
463                            }
464                            else if (className.equals(UserGroup.class.getName())) {
465                                    UserGroup userGroup = userGroupPersistence.findByPrimaryKey(
466                                            classPK);
467    
468                                    toName = userGroup.getName();
469    
470                                    params.put("usersUserGroups", classPK);
471                            }
472                    }
473    
474                    if (className.equals(User.class.getName())) {
475                            User user = userPersistence.findByPrimaryKey(classPK);
476    
477                            if (Validator.isNull(user.getEmailAddress())) {
478                                    return;
479                            }
480    
481                            notifyUsers(
482                                    ListUtil.fromArray(new User[] {user}), entry,
483                                    company.getLocale(), user.getEmailAddress(),
484                                    user.getFullName());
485                    }
486                    else {
487                            int count = 0;
488    
489                            if (teamId > 0) {
490                                    count = userLocalService.getTeamUsersCount(teamId);
491                            }
492                            else {
493                                    count = userLocalService.searchCount(
494                                            company.getCompanyId(), null,
495                                            WorkflowConstants.STATUS_APPROVED, params);
496                            }
497    
498                            int pages = count / Indexer.DEFAULT_INTERVAL;
499    
500                            for (int i = 0; i <= pages; i++) {
501                                    int start = (i * Indexer.DEFAULT_INTERVAL);
502                                    int end = start + Indexer.DEFAULT_INTERVAL;
503    
504                                    List<User> users = null;
505    
506                                    if (teamId > 0) {
507                                            users = userLocalService.getTeamUsers(teamId, start, end);
508                                    }
509                                    else {
510                                            users = userLocalService.search(
511                                                    company.getCompanyId(), null,
512                                                    WorkflowConstants.STATUS_APPROVED, params, start, end,
513                                                    (OrderByComparator)null);
514                                    }
515    
516                                    notifyUsers(
517                                            users, entry, company.getLocale(), toAddress, toName);
518                            }
519                    }
520            }
521    
522            protected void notifyUsers(
523                            List<User> users, AnnouncementsEntry entry, Locale locale,
524                            String toAddress, String toName)
525                    throws PortalException, SystemException {
526    
527                    if (_log.isDebugEnabled()) {
528                            _log.debug("Notifying " + users.size() + " users");
529                    }
530    
531                    boolean notifyUsers = false;
532    
533                    SubscriptionSender subscriptionSender = new SubscriptionSender();
534    
535                    for (User user : users) {
536                            AnnouncementsDelivery announcementsDelivery =
537                                    announcementsDeliveryLocalService.getUserDelivery(
538                                            user.getUserId(), entry.getType());
539    
540                            if (announcementsDelivery.isEmail()) {
541                                    subscriptionSender.addRuntimeSubscribers(
542                                            user.getEmailAddress(), user.getFullName());
543    
544                                    notifyUsers = true;
545                            }
546    
547                            if (announcementsDelivery.isSms()) {
548                                    String smsSn = user.getContact().getSmsSn();
549    
550                                    subscriptionSender.addRuntimeSubscribers(
551                                            smsSn, user.getFullName());
552    
553                                    notifyUsers = true;
554                            }
555                    }
556    
557                    if (!notifyUsers) {
558                            return;
559                    }
560    
561                    String body = ContentUtil.get(PropsValues.ANNOUNCEMENTS_EMAIL_BODY);
562                    String fromAddress = PrefsPropsUtil.getStringFromNames(
563                            entry.getCompanyId(), PropsKeys.ANNOUNCEMENTS_EMAIL_FROM_ADDRESS,
564                            PropsKeys.ADMIN_EMAIL_FROM_ADDRESS);
565                    String fromName = PrefsPropsUtil.getStringFromNames(
566                            entry.getCompanyId(), PropsKeys.ANNOUNCEMENTS_EMAIL_FROM_NAME,
567                            PropsKeys.ADMIN_EMAIL_FROM_NAME);
568                    String subject = ContentUtil.get(
569                            PropsValues.ANNOUNCEMENTS_EMAIL_SUBJECT);
570    
571                    subscriptionSender.setBody(body);
572                    subscriptionSender.setCompanyId(entry.getCompanyId());
573                    subscriptionSender.setContextAttribute(
574                            "[$ENTRY_CONTENT$]", entry.getContent(), false);
575                    subscriptionSender.setContextAttributes(
576                            "[$ENTRY_ID$]", entry.getEntryId(), "[$ENTRY_TITLE$]",
577                            entry.getTitle(), "[$ENTRY_TYPE$]",
578                            LanguageUtil.get(locale, entry.getType()), "[$ENTRY_URL$]",
579                            entry.getUrl(), "[$PORTLET_NAME$]",
580                            LanguageUtil.get(
581                                    locale, (entry.isAlert() ? "alert" : "announcement")));
582                    subscriptionSender.setFrom(fromAddress, fromName);
583                    subscriptionSender.setHtmlFormat(true);
584                    subscriptionSender.setMailId("announcements_entry", entry.getEntryId());
585                    subscriptionSender.setPortletId(PortletKeys.ANNOUNCEMENTS);
586                    subscriptionSender.setScopeGroupId(entry.getGroupId());
587                    subscriptionSender.setSubject(subject);
588                    subscriptionSender.setUserId(entry.getUserId());
589    
590                    subscriptionSender.addRuntimeSubscribers(toAddress, toName);
591    
592                    subscriptionSender.flushNotificationsAsync();
593            }
594    
595            protected void validate(
596                            String title, String content, String url, Date displayDate,
597                            Date expirationDate)
598                    throws PortalException {
599    
600                    if (Validator.isNull(title)) {
601                            throw new EntryTitleException();
602                    }
603    
604                    if (Validator.isNull(content)) {
605                            throw new EntryContentException();
606                    }
607    
608                    if (Validator.isNotNull(url) && !Validator.isUrl(url)) {
609                            throw new EntryURLException();
610                    }
611    
612                    if ((expirationDate != null) &&
613                            (expirationDate.before(new Date()) ||
614                             ((displayDate != null) && expirationDate.before(displayDate)))) {
615    
616                            throw new EntryExpirationDateException(
617                                    "Expiration date " + expirationDate + " is in the past");
618                    }
619            }
620    
621            private static final long _ANNOUNCEMENTS_ENTRY_CHECK_INTERVAL =
622                    PropsValues.ANNOUNCEMENTS_ENTRY_CHECK_INTERVAL * Time.MINUTE;
623    
624            private static Log _log = LogFactoryUtil.getLog(
625                    AnnouncementsEntryLocalServiceImpl.class);
626    
627            private Date _previousCheckDate;
628    
629    }