001    /**
002     * Copyright (c) 2000-2010 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.messageboards.service.impl;
016    
017    import com.liferay.documentlibrary.DuplicateDirectoryException;
018    import com.liferay.documentlibrary.DuplicateFileException;
019    import com.liferay.documentlibrary.NoSuchDirectoryException;
020    import com.liferay.portal.NoSuchUserException;
021    import com.liferay.portal.kernel.dao.orm.QueryUtil;
022    import com.liferay.portal.kernel.exception.PortalException;
023    import com.liferay.portal.kernel.exception.SystemException;
024    import com.liferay.portal.kernel.json.JSONFactoryUtil;
025    import com.liferay.portal.kernel.json.JSONObject;
026    import com.liferay.portal.kernel.language.LanguageUtil;
027    import com.liferay.portal.kernel.log.Log;
028    import com.liferay.portal.kernel.log.LogFactoryUtil;
029    import com.liferay.portal.kernel.mail.MailMessage;
030    import com.liferay.portal.kernel.messaging.DestinationNames;
031    import com.liferay.portal.kernel.messaging.MessageBusUtil;
032    import com.liferay.portal.kernel.search.Indexer;
033    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
034    import com.liferay.portal.kernel.util.ContentTypes;
035    import com.liferay.portal.kernel.util.GetterUtil;
036    import com.liferay.portal.kernel.util.ListUtil;
037    import com.liferay.portal.kernel.util.LocaleUtil;
038    import com.liferay.portal.kernel.util.ObjectValuePair;
039    import com.liferay.portal.kernel.util.OrderByComparator;
040    import com.liferay.portal.kernel.util.PropsKeys;
041    import com.liferay.portal.kernel.util.StringPool;
042    import com.liferay.portal.kernel.util.StringUtil;
043    import com.liferay.portal.kernel.util.Validator;
044    import com.liferay.portal.kernel.workflow.WorkflowConstants;
045    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
046    import com.liferay.portal.kernel.workflow.WorkflowThreadLocal;
047    import com.liferay.portal.model.Company;
048    import com.liferay.portal.model.CompanyConstants;
049    import com.liferay.portal.model.Group;
050    import com.liferay.portal.model.GroupConstants;
051    import com.liferay.portal.model.ModelHintsUtil;
052    import com.liferay.portal.model.ResourceConstants;
053    import com.liferay.portal.model.User;
054    import com.liferay.portal.security.auth.PrincipalException;
055    import com.liferay.portal.security.permission.ActionKeys;
056    import com.liferay.portal.service.ServiceContext;
057    import com.liferay.portal.service.ServiceContextUtil;
058    import com.liferay.portal.util.Portal;
059    import com.liferay.portal.util.PortalUtil;
060    import com.liferay.portal.util.PortletKeys;
061    import com.liferay.portal.util.PrefsPropsUtil;
062    import com.liferay.portal.util.PropsValues;
063    import com.liferay.portlet.blogs.model.BlogsEntry;
064    import com.liferay.portlet.blogs.social.BlogsActivityKeys;
065    import com.liferay.portlet.blogs.util.LinkbackProducerUtil;
066    import com.liferay.portlet.expando.model.ExpandoBridge;
067    import com.liferay.portlet.messageboards.MessageBodyException;
068    import com.liferay.portlet.messageboards.MessageSubjectException;
069    import com.liferay.portlet.messageboards.NoSuchDiscussionException;
070    import com.liferay.portlet.messageboards.RequiredMessageException;
071    import com.liferay.portlet.messageboards.model.MBCategory;
072    import com.liferay.portlet.messageboards.model.MBCategoryConstants;
073    import com.liferay.portlet.messageboards.model.MBDiscussion;
074    import com.liferay.portlet.messageboards.model.MBMessage;
075    import com.liferay.portlet.messageboards.model.MBMessageConstants;
076    import com.liferay.portlet.messageboards.model.MBMessageDisplay;
077    import com.liferay.portlet.messageboards.model.MBThread;
078    import com.liferay.portlet.messageboards.model.MBThreadConstants;
079    import com.liferay.portlet.messageboards.model.impl.MBCategoryImpl;
080    import com.liferay.portlet.messageboards.model.impl.MBMessageDisplayImpl;
081    import com.liferay.portlet.messageboards.service.base.MBMessageLocalServiceBaseImpl;
082    import com.liferay.portlet.messageboards.social.MBActivityKeys;
083    import com.liferay.portlet.messageboards.util.MBUtil;
084    import com.liferay.portlet.messageboards.util.MailingListThreadLocal;
085    import com.liferay.portlet.messageboards.util.comparator.MessageThreadComparator;
086    import com.liferay.portlet.messageboards.util.comparator.ThreadLastPostDateComparator;
087    import com.liferay.portlet.social.model.SocialActivity;
088    
089    import java.io.IOException;
090    
091    import java.util.ArrayList;
092    import java.util.Comparator;
093    import java.util.Date;
094    import java.util.HashSet;
095    import java.util.Iterator;
096    import java.util.List;
097    import java.util.Set;
098    
099    import javax.mail.internet.InternetAddress;
100    
101    import javax.portlet.PortletPreferences;
102    
103    import net.htmlparser.jericho.Source;
104    import net.htmlparser.jericho.StartTag;
105    
106    /**
107     * @author Brian Wing Shun Chan
108     * @author Raymond Augé
109     * @author Mika Koivisto
110     * @author Jorge Ferrer
111     */
112    public class MBMessageLocalServiceImpl extends MBMessageLocalServiceBaseImpl {
113    
114            public MBMessage addDiscussionMessage(
115                            long userId, String userName, long groupId, String className,
116                            long classPK, int workflowAction)
117                    throws PortalException, SystemException {
118    
119                    long threadId = 0;
120                    long parentMessageId = 0;
121                    String subject = String.valueOf(classPK);
122                    String body = subject;
123    
124                    ServiceContext serviceContext = new ServiceContext();
125    
126                    serviceContext.setWorkflowAction(workflowAction);
127    
128                    boolean workflowEnabled = WorkflowThreadLocal.isEnabled();
129    
130                    WorkflowThreadLocal.setEnabled(false);
131    
132                    try {
133                            return addDiscussionMessage(
134                                    userId, userName, groupId, className, classPK, threadId,
135                                    parentMessageId, subject, body, serviceContext);
136                    }
137                    finally {
138                            WorkflowThreadLocal.setEnabled(workflowEnabled);
139                    }
140            }
141    
142            public MBMessage addDiscussionMessage(
143                            long userId, String userName, long groupId, String className,
144                            long classPK, long threadId, long parentMessageId, String subject,
145                            String body, ServiceContext serviceContext)
146                    throws PortalException, SystemException {
147    
148                    // Message
149    
150                    long categoryId = MBCategoryConstants.DISCUSSION_CATEGORY_ID;
151    
152                    if (Validator.isNull(subject)) {
153                            subject = body.substring(0, Math.min(body.length(), 50)) + "...";
154                    }
155    
156                    List<ObjectValuePair<String, byte[]>> files =
157                            new ArrayList<ObjectValuePair<String, byte[]>>();
158                    boolean anonymous = false;
159                    double priority = 0.0;
160                    boolean allowPingbacks = false;
161    
162                    serviceContext.setAddCommunityPermissions(true);
163                    serviceContext.setAddGuestPermissions(true);
164                    serviceContext.setAttribute("className", className);
165                    serviceContext.setAttribute("classPK", String.valueOf(classPK));
166    
167                    MBMessage message = addMessage(
168                            userId, userName, groupId, categoryId, threadId, parentMessageId,
169                            subject, body, files, anonymous, priority, allowPingbacks,
170                            serviceContext);
171    
172                    // Discussion
173    
174                    if (parentMessageId == MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) {
175                            long classNameId = PortalUtil.getClassNameId(className);
176    
177                            MBDiscussion discussion = mbDiscussionPersistence.fetchByC_C(
178                                    classNameId, classPK);
179    
180                            if (discussion == null) {
181                                    discussion = mbDiscussionLocalService.addDiscussion(
182                                            classNameId, classPK, message.getThreadId());
183                            }
184                    }
185    
186                    return message;
187            }
188    
189            public MBMessage addMessage(
190                            long userId, String userName, long groupId, long categoryId,
191                            long threadId, long parentMessageId, String subject, String body,
192                            List<ObjectValuePair<String, byte[]>> files, boolean anonymous,
193                            double priority, boolean allowPingbacks,
194                            ServiceContext serviceContext)
195                    throws PortalException, SystemException {
196    
197                    // Message
198    
199                    User user = userPersistence.findByPrimaryKey(userId);
200                    userName = user.isDefaultUser() ? userName : user.getFullName();
201                    subject = ModelHintsUtil.trimString(
202                            MBMessage.class.getName(), "subject", subject);
203    
204                    PortletPreferences preferences =
205                            ServiceContextUtil.getPortletPreferences(serviceContext);
206    
207                    if (preferences != null) {
208                            if (!MBUtil.isAllowAnonymousPosting(preferences)) {
209                                    if (anonymous || user.isDefaultUser()) {
210                                            throw new PrincipalException();
211                                    }
212                            }
213                    }
214    
215                    if (user.isDefaultUser()) {
216                            anonymous = true;
217                    }
218    
219                    Date now = new Date();
220    
221                    validate(subject, body);
222    
223                    long messageId = counterLocalService.increment();
224    
225                    MBMessage message = mbMessagePersistence.create(messageId);
226    
227                    message.setUuid(serviceContext.getUuid());
228                    message.setGroupId(groupId);
229                    message.setCompanyId(user.getCompanyId());
230                    message.setUserId(user.getUserId());
231                    message.setUserName(userName);
232                    message.setCreateDate(serviceContext.getCreateDate(now));
233                    message.setModifiedDate(serviceContext.getModifiedDate(now));
234                    message.setAllowPingbacks(allowPingbacks);
235                    message.setStatus(WorkflowConstants.STATUS_DRAFT);
236                    message.setStatusByUserId(user.getUserId());
237                    message.setStatusByUserName(userName);
238                    message.setStatusDate(serviceContext.getModifiedDate(now));
239    
240                    // Thread
241    
242                    if (parentMessageId != MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) {
243                            MBMessage parentMessage = mbMessagePersistence.fetchByPrimaryKey(
244                                    parentMessageId);
245    
246                            if (parentMessage == null) {
247                                    parentMessageId = MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID;
248                            }
249                    }
250    
251                    MBThread thread = null;
252    
253                    if (threadId > 0) {
254                            thread = mbThreadPersistence.fetchByPrimaryKey(threadId);
255                    }
256    
257                    if ((thread == null) ||
258                            (parentMessageId == MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID)) {
259    
260                            threadId = counterLocalService.increment();
261    
262                            thread = mbThreadPersistence.create(threadId);
263    
264                            thread.setGroupId(groupId);
265                            thread.setCategoryId(categoryId);
266                            thread.setRootMessageId(messageId);
267                            thread.setStatus(WorkflowConstants.STATUS_DRAFT);
268                            thread.setStatusByUserId(user.getUserId());
269                            thread.setStatusByUserName(userName);
270                            thread.setStatusDate(serviceContext.getModifiedDate(now));
271                    }
272    
273                    if ((priority != MBThreadConstants.PRIORITY_NOT_GIVEN) &&
274                            (thread.getPriority() != priority)) {
275    
276                            thread.setPriority(priority);
277    
278                            updatePriorities(thread.getThreadId(), priority);
279                    }
280    
281                    // Message
282    
283                    message.setCategoryId(categoryId);
284                    message.setThreadId(threadId);
285                    message.setRootMessageId(thread.getRootMessageId());
286                    message.setParentMessageId(parentMessageId);
287                    message.setSubject(subject);
288                    message.setBody(body);
289                    message.setAttachments(!files.isEmpty());
290                    message.setAnonymous(anonymous);
291    
292                    if (priority != MBThreadConstants.PRIORITY_NOT_GIVEN) {
293                            message.setPriority(priority);
294                    }
295    
296                    if (message.isDiscussion()) {
297                            long classNameId = PortalUtil.getClassNameId(
298                                    (String)serviceContext.getAttribute("className"));
299                            long classPK = GetterUtil.getLong(
300                                    (String)serviceContext.getAttribute("classPK"));
301    
302                            message.setClassNameId(classNameId);
303                            message.setClassPK(classPK);
304                    }
305    
306                    // Attachments
307    
308                    if (files.size() > 0) {
309                            long companyId = message.getCompanyId();
310                            String portletId = CompanyConstants.SYSTEM_STRING;
311                            long dlGroupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
312                            long repositoryId = CompanyConstants.SYSTEM;
313                            String dirName = message.getAttachmentsDir();
314    
315                            try {
316                                    dlService.deleteDirectory(
317                                            companyId, portletId, repositoryId, dirName);
318                            }
319                            catch (NoSuchDirectoryException nsde) {
320                                    if (_log.isDebugEnabled()) {
321                                            _log.debug(nsde.getMessage());
322                                    }
323                            }
324    
325                            dlService.addDirectory(companyId, repositoryId, dirName);
326    
327                            for (int i = 0; i < files.size(); i++) {
328                                    ObjectValuePair<String, byte[]> ovp = files.get(i);
329    
330                                    String fileName = ovp.getKey();
331                                    byte[] bytes = ovp.getValue();
332    
333                                    try {
334                                            dlService.addFile(
335                                                    companyId, portletId, dlGroupId, repositoryId,
336                                                    dirName + "/" + fileName, 0, StringPool.BLANK,
337                                                    message.getModifiedDate(), new ServiceContext(), bytes);
338                                    }
339                                    catch (DuplicateFileException dfe) {
340                                            if (_log.isDebugEnabled()) {
341                                                    _log.debug(dfe.getMessage());
342                                            }
343                                    }
344                            }
345                    }
346    
347                    // Commit
348    
349                    mbThreadPersistence.update(thread, false);
350                    mbMessagePersistence.update(message, false);
351    
352                    // Resources
353    
354                    if (!message.isDiscussion()) {
355                            if (user.isDefaultUser()) {
356                                    addMessageResources(message, true, true);
357                            }
358                            if (serviceContext.getAddCommunityPermissions() ||
359                                    serviceContext.getAddGuestPermissions()) {
360    
361                                    addMessageResources(
362                                            message, serviceContext.getAddCommunityPermissions(),
363                                            serviceContext.getAddGuestPermissions());
364                            }
365                            else {
366                                    addMessageResources(
367                                            message, serviceContext.getCommunityPermissions(),
368                                            serviceContext.getGuestPermissions());
369                            }
370                    }
371    
372                    // Asset
373    
374                    updateAsset(
375                            userId, message, serviceContext.getAssetCategoryIds(),
376                            serviceContext.getAssetTagNames());
377    
378                    // Expando
379    
380                    ExpandoBridge expandoBridge = message.getExpandoBridge();
381    
382                    expandoBridge.setAttributes(serviceContext);
383    
384                    // Workflow
385    
386                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
387                            user.getCompanyId(), groupId, userId,
388                            message.getWorkflowClassName(), message.getMessageId(), message,
389                            serviceContext);
390    
391                    // Testing roll back
392    
393                    /*if (true) {
394                            throw new SystemException("Testing roll back");
395                    }*/
396    
397                    return message;
398            }
399    
400            public MBMessage addMessage(
401                            long userId, String userName, long groupId, long categoryId,
402                            String subject, String body,
403                            List<ObjectValuePair<String, byte[]>> files, boolean anonymous,
404                            double priority, boolean allowPingbacks,
405                            ServiceContext serviceContext)
406                    throws PortalException, SystemException {
407    
408                    long threadId = 0;
409                    long parentMessageId = 0;
410    
411                    return addMessage(
412                            userId, userName, groupId, categoryId, threadId, parentMessageId,
413                            subject, body, files, anonymous, priority, allowPingbacks,
414                            serviceContext);
415            }
416    
417            public void addMessageResources(
418                            long messageId, boolean addCommunityPermissions,
419                            boolean addGuestPermissions)
420                    throws PortalException, SystemException {
421    
422                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
423    
424                    addMessageResources(
425                            message, addCommunityPermissions, addGuestPermissions);
426            }
427    
428            public void addMessageResources(
429                            long messageId, String[] communityPermissions,
430                            String[] guestPermissions)
431                    throws PortalException, SystemException {
432    
433                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
434    
435                    addMessageResources(message, communityPermissions, guestPermissions);
436            }
437    
438            public void addMessageResources(
439                            MBMessage message, boolean addCommunityPermissions,
440                            boolean addGuestPermissions)
441                    throws PortalException, SystemException {
442    
443                    resourceLocalService.addResources(
444                            message.getCompanyId(), message.getGroupId(), message.getUserId(),
445                            MBMessage.class.getName(), message.getMessageId(),
446                            false, addCommunityPermissions, addGuestPermissions);
447            }
448    
449            public void addMessageResources(
450                            MBMessage message, String[] communityPermissions,
451                            String[] guestPermissions)
452                    throws PortalException, SystemException {
453    
454                    resourceLocalService.addModelResources(
455                            message.getCompanyId(), message.getGroupId(), message.getUserId(),
456                            MBMessage.class.getName(), message.getMessageId(),
457                            communityPermissions, guestPermissions);
458            }
459    
460            public void deleteDiscussionMessage(long messageId)
461                    throws PortalException, SystemException {
462    
463                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
464    
465                    List<MBMessage> messages = new ArrayList<MBMessage>();
466    
467                    messages.add(message);
468    
469                    deleteDiscussionSocialActivities(BlogsEntry.class.getName(), messages);
470    
471                    deleteMessage(message);
472            }
473    
474            public void deleteDiscussionMessages(String className, long classPK)
475                    throws PortalException, SystemException {
476    
477                    try {
478                            long classNameId = PortalUtil.getClassNameId(className);
479    
480                            MBDiscussion discussion = mbDiscussionPersistence.findByC_C(
481                                    classNameId, classPK);
482    
483                            List<MBMessage> messages = mbMessagePersistence.findByT_P(
484                                    discussion.getThreadId(),
485                                    MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID, 0, 1);
486    
487                            deleteDiscussionSocialActivities(
488                                    BlogsEntry.class.getName(), messages);
489    
490                            if (messages.size() > 0) {
491                                    MBMessage message = messages.get(0);
492    
493                                    mbThreadLocalService.deleteThread(message.getThreadId());
494                            }
495    
496                            mbDiscussionPersistence.remove(discussion);
497                    }
498                    catch (NoSuchDiscussionException nsde) {
499                            if (_log.isDebugEnabled()) {
500                                    _log.debug(nsde.getMessage());
501                            }
502                    }
503            }
504    
505            public void deleteMessage(long messageId)
506                    throws PortalException, SystemException {
507    
508                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
509    
510                    deleteMessage(message);
511            }
512    
513            public void deleteMessage(MBMessage message)
514                    throws PortalException, SystemException {
515    
516                    // Indexer
517    
518                    Indexer indexer = IndexerRegistryUtil.getIndexer(MBMessage.class);
519    
520                    indexer.delete(message);
521    
522                    // Attachments
523    
524                    if (message.isAttachments()) {
525                            long companyId = message.getCompanyId();
526                            String portletId = CompanyConstants.SYSTEM_STRING;
527                            long repositoryId = CompanyConstants.SYSTEM;
528                            String dirName = message.getAttachmentsDir();
529    
530                            try {
531                                    dlService.deleteDirectory(
532                                            companyId, portletId, repositoryId, dirName);
533                            }
534                            catch (NoSuchDirectoryException nsde) {
535                                    if (_log.isDebugEnabled()) {
536                                            _log.debug(nsde.getMessage());
537                                    }
538                            }
539                    }
540    
541                    // Thread
542    
543                    int count = mbMessagePersistence.countByThreadId(message.getThreadId());
544    
545                    // Message flags
546    
547                    if (message.isRoot()) {
548                            mbMessageFlagLocalService.deleteQuestionAndAnswerFlags(
549                                    message.getThreadId());
550                    }
551                    else if (mbMessageFlagLocalService.hasAnswerFlag(
552                                            message.getMessageId())) {
553    
554                            mbMessageFlagService.deleteAnswerFlag(message.getMessageId());
555                    }
556    
557                    if (count == 1) {
558    
559                            // Attachments
560    
561                            long companyId = message.getCompanyId();
562                            String portletId = CompanyConstants.SYSTEM_STRING;
563                            long repositoryId = CompanyConstants.SYSTEM;
564                            String dirName = message.getThreadAttachmentsDir();
565    
566                            try {
567                                    dlService.deleteDirectory(
568                                            companyId, portletId, repositoryId, dirName);
569                            }
570                            catch (NoSuchDirectoryException nsde) {
571                                    if (_log.isDebugEnabled()) {
572                                            _log.debug(nsde.getMessage());
573                                    }
574                            }
575    
576                            // Subscriptions
577    
578                            subscriptionLocalService.deleteSubscriptions(
579                                    message.getCompanyId(), MBThread.class.getName(),
580                                    message.getThreadId());
581    
582                            // Thread
583    
584                            mbThreadPersistence.remove(message.getThreadId());
585    
586                            // Category
587    
588                            if ((message.getCategoryId() !=
589                                            MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
590                                    (message.getCategoryId() !=
591                                            MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
592    
593                                    MBCategory category = mbCategoryPersistence.findByPrimaryKey(
594                                            message.getCategoryId());
595    
596                                    category.setThreadCount(category.getThreadCount() - 1);
597                                    category.setMessageCount(category.getMessageCount() - 1);
598    
599                                    mbCategoryPersistence.update(category, false);
600                            }
601                    }
602                    else if (count > 1) {
603                            MBThread thread = mbThreadPersistence.findByPrimaryKey(
604                                    message.getThreadId());
605    
606                            // Message is a root message
607    
608                            if (thread.getRootMessageId() == message.getMessageId()) {
609                                    List<MBMessage> childrenMessages =
610                                            mbMessagePersistence.findByT_P(
611                                                    message.getThreadId(), message.getMessageId());
612    
613                                    if (childrenMessages.size() > 1) {
614                                            throw new RequiredMessageException(
615                                                    String.valueOf(message.getMessageId()));
616                                    }
617                                    else if (childrenMessages.size() == 1) {
618                                            MBMessage childMessage = childrenMessages.get(0);
619    
620                                            childMessage.setRootMessageId(childMessage.getMessageId());
621                                            childMessage.setParentMessageId(
622                                                    MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID);
623    
624                                            mbMessagePersistence.update(childMessage, false);
625    
626                                            thread.setRootMessageId(childMessage.getMessageId());
627    
628                                            mbThreadPersistence.update(thread, false);
629                                    }
630                            }
631    
632                            // Message is a child message
633    
634                            else {
635                                    List<MBMessage> childrenMessages =
636                                            mbMessagePersistence.findByT_P(
637                                                    message.getThreadId(), message.getMessageId());
638    
639                                    // Message has children messages
640    
641                                    if (childrenMessages.size() > 0) {
642                                            Iterator<MBMessage> itr = childrenMessages.iterator();
643    
644                                            while (itr.hasNext()) {
645                                                    MBMessage childMessage = itr.next();
646    
647                                                    childMessage.setParentMessageId(
648                                                            message.getParentMessageId());
649    
650                                                    mbMessagePersistence.update(childMessage, false);
651                                            }
652                                    }
653                            }
654    
655                            // Thread
656    
657                            thread.setMessageCount(count - 1);
658    
659                            mbThreadPersistence.update(thread, false);
660    
661                            // Category
662    
663                            if ((message.getCategoryId() !=
664                                            MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
665                                    (message.getCategoryId() !=
666                                            MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
667    
668                                    MBCategory category = mbCategoryPersistence.findByPrimaryKey(
669                                            message.getCategoryId());
670    
671                                    category.setMessageCount(category.getMessageCount() - 1);
672    
673                                    mbCategoryPersistence.update(category, false);
674                            }
675                    }
676    
677                    // Asset
678    
679                    assetEntryLocalService.deleteEntry(
680                            MBMessage.class.getName(), message.getMessageId());
681    
682                    // Expando
683    
684                    expandoValueLocalService.deleteValues(
685                            MBMessage.class.getName(), message.getMessageId());
686    
687                    // Social
688    
689                    socialActivityLocalService.deleteActivities(
690                            MBMessage.class.getName(), message.getMessageId());
691    
692                    // Ratings
693    
694                    ratingsStatsLocalService.deleteStats(
695                            MBMessage.class.getName(), message.getMessageId());
696    
697                    // Statistics
698    
699                    if (!message.isDiscussion()) {
700                            mbStatsUserLocalService.updateStatsUser(
701                                    message.getGroupId(), message.getUserId());
702                    }
703    
704                    // Message flags
705    
706                    mbMessageFlagPersistence.removeByMessageId(message.getMessageId());
707    
708                    // Resources
709    
710                    if (!message.isDiscussion()) {
711                            resourceLocalService.deleteResource(
712                                    message.getCompanyId(), MBMessage.class.getName(),
713                                    ResourceConstants.SCOPE_INDIVIDUAL, message.getMessageId());
714                    }
715    
716                    // Message
717    
718                    mbMessagePersistence.remove(message);
719    
720                    // Workflow
721    
722                    workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
723                            message.getCompanyId(), message.getGroupId(),
724                            message.getWorkflowClassName(), message.getMessageId());
725            }
726    
727            public List<MBMessage> getCategoryMessages(
728                            long groupId, long categoryId, int status, int start, int end)
729                    throws SystemException {
730    
731                    if (status == WorkflowConstants.STATUS_ANY) {
732                            return mbMessagePersistence.findByG_C(
733                                    groupId, categoryId, start, end);
734                    }
735                    else {
736                            return mbMessagePersistence.findByG_C_S(
737                                    groupId, categoryId, status, start, end);
738                    }
739            }
740    
741            public List<MBMessage> getCategoryMessages(
742                            long groupId, long categoryId, int status, int start, int end,
743                            OrderByComparator obc)
744                    throws SystemException {
745    
746                    if (status == WorkflowConstants.STATUS_ANY) {
747                            return mbMessagePersistence.findByG_C(
748                                    groupId, categoryId, start, end, obc);
749                    }
750                    else {
751                            return mbMessagePersistence.findByG_C_S(
752                                    groupId, categoryId, status, start, end, obc);
753                    }
754            }
755    
756            public int getCategoryMessagesCount(
757                            long groupId, long categoryId, int status)
758                    throws SystemException {
759    
760                    if (status == WorkflowConstants.STATUS_ANY) {
761                            return mbMessagePersistence.countByG_C(groupId, categoryId);
762                    }
763                    else {
764                            return mbMessagePersistence.countByG_C_S(
765                                    groupId, categoryId, status);
766                    }
767            }
768    
769            public List<MBMessage> getCompanyMessages(
770                            long companyId, int status, int start, int end)
771                    throws SystemException {
772    
773                    if (status == WorkflowConstants.STATUS_ANY) {
774                            return mbMessagePersistence.findByCompanyId(companyId, start, end);
775                    }
776                    else {
777                            return mbMessagePersistence.findByC_S(
778                                    companyId, status, start, end);
779                    }
780            }
781    
782            public List<MBMessage> getCompanyMessages(
783                            long companyId, int status, int start, int end,
784                            OrderByComparator obc)
785                    throws SystemException {
786    
787                    if (status == WorkflowConstants.STATUS_ANY) {
788                            return mbMessagePersistence.findByCompanyId(
789                                    companyId, start, end, obc);
790                    }
791                    else {
792                            return mbMessagePersistence.findByC_S(
793                                    companyId, status, start, end, obc);
794                    }
795            }
796    
797            public int getCompanyMessagesCount(long companyId, int status)
798                    throws SystemException {
799    
800                    if (status == WorkflowConstants.STATUS_ANY) {
801                            return mbMessagePersistence.countByCompanyId(companyId);
802                    }
803                    else {
804                            return mbMessagePersistence.countByC_S(companyId, status);
805                    }
806            }
807    
808            public MBMessageDisplay getDiscussionMessageDisplay(
809                            long userId, long groupId, String className, long classPK,
810                            int status)
811                    throws PortalException, SystemException {
812    
813                    return getDiscussionMessageDisplay(
814                            userId, groupId, className, classPK, status,
815                            MBThreadConstants.THREAD_VIEW_COMBINATION);
816            }
817    
818            public MBMessageDisplay getDiscussionMessageDisplay(
819                            long userId, long groupId, String className, long classPK,
820                            int status, String threadView)
821                    throws PortalException, SystemException {
822    
823                    long classNameId = PortalUtil.getClassNameId(className);
824    
825                    MBMessage message = null;
826    
827                    MBDiscussion discussion = mbDiscussionPersistence.fetchByC_C(
828                            classNameId, classPK);
829    
830                    if (discussion != null) {
831                            List<MBMessage> messages = mbMessagePersistence.findByT_P(
832                                    discussion.getThreadId(),
833                                    MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID);
834    
835                            message = messages.get(0);
836                    }
837                    else {
838                            boolean workflowEnabled = WorkflowThreadLocal.isEnabled();
839    
840                            WorkflowThreadLocal.setEnabled(false);
841    
842                            try {
843                                    String subject = String.valueOf(classPK);
844                                    //String body = subject;
845    
846                                    message = addDiscussionMessage(
847                                            userId, null, groupId, className, classPK, 0,
848                                            MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID, subject,
849                                            subject, new ServiceContext());
850                            }
851                            catch (SystemException se) {
852                                    if (_log.isWarnEnabled()) {
853                                            _log.warn(
854                                                    "Add failed, fetch {threadId=0, parentMessageId=" +
855                                                            MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID + "}");
856                                    }
857    
858                                    List<MBMessage> messages = mbMessagePersistence.findByT_P(
859                                            0, MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID);
860    
861                                    if (messages.isEmpty()) {
862                                            throw se;
863                                    }
864    
865                                    message = messages.get(0);
866                            }
867                            finally {
868                                    WorkflowThreadLocal.setEnabled(workflowEnabled);
869                            }
870                    }
871    
872                    return getMessageDisplay(message, status, threadView, false);
873            }
874    
875            public int getDiscussionMessagesCount(
876                            long classNameId, long classPK, int status)
877                    throws SystemException {
878    
879                    MBDiscussion discussion = mbDiscussionPersistence.fetchByC_C(
880                            classNameId, classPK);
881    
882                    if (discussion == null) {
883                            return 0;
884                    }
885    
886                    int count = 0;
887    
888                    if (status == WorkflowConstants.STATUS_ANY) {
889                            count = mbMessagePersistence.countByThreadId(
890                                    discussion.getThreadId());
891                    }
892                    else {
893                            count = mbMessagePersistence.countByT_S(
894                                    discussion.getThreadId(), status);
895                    }
896    
897                    if (count >= 1) {
898                            return count - 1;
899                    }
900                    else {
901                            return 0;
902                    }
903            }
904    
905            public int getDiscussionMessagesCount(
906                            String className, long classPK, int status)
907                    throws SystemException {
908    
909                    long classNameId = PortalUtil.getClassNameId(className);
910    
911                    return getDiscussionMessagesCount(classNameId, classPK, status);
912            }
913    
914            public List<MBDiscussion> getDiscussions(String className)
915                    throws SystemException {
916    
917                    long classNameId = PortalUtil.getClassNameId(className);
918    
919                    return mbDiscussionPersistence.findByClassNameId(classNameId);
920            }
921    
922            public List<MBMessage> getGroupMessages(
923                            long groupId, int status, int start, int end)
924                    throws SystemException {
925    
926                    if (status == WorkflowConstants.STATUS_ANY) {
927                            return mbMessagePersistence.findByGroupId(groupId, start, end);
928                    }
929                    else {
930                            return mbMessagePersistence.findByG_S(groupId, status, start, end);
931                    }
932            }
933    
934            public List<MBMessage> getGroupMessages(
935                            long groupId, int status, int start, int end, OrderByComparator obc)
936                    throws SystemException {
937    
938                    if (status == WorkflowConstants.STATUS_ANY) {
939                            return mbMessagePersistence.findByGroupId(groupId, start, end, obc);
940                    }
941                    else {
942                            return mbMessagePersistence.findByG_S(
943                                    groupId, status, start, end, obc);
944                    }
945            }
946    
947            public List<MBMessage> getGroupMessages(
948                            long groupId, long userId, int status, int start, int end)
949                    throws SystemException {
950    
951                    if (status == WorkflowConstants.STATUS_ANY) {
952                            return mbMessagePersistence.findByG_U(groupId, userId, start, end);
953                    }
954                    else {
955                            return mbMessagePersistence.findByG_U_S(
956                                    groupId, userId, status, start, end);
957                    }
958            }
959    
960            public List<MBMessage> getGroupMessages(
961                            long groupId, long userId, int status, int start, int end,
962                            OrderByComparator obc)
963                    throws SystemException {
964    
965                    if (status == WorkflowConstants.STATUS_ANY) {
966                            return mbMessagePersistence.findByG_U(
967                                    groupId, userId, start, end, obc);
968                    }
969                    else {
970                            return mbMessagePersistence.findByG_U_S(
971                                    groupId, userId, status, start, end, obc);
972                    }
973            }
974    
975            public int getGroupMessagesCount(long groupId, int status)
976                    throws SystemException {
977    
978                    if (status == WorkflowConstants.STATUS_ANY) {
979                            return mbMessagePersistence.countByGroupId(groupId);
980                    }
981                    else {
982                            return mbMessagePersistence.countByG_S(groupId, status);
983                    }
984            }
985    
986            public int getGroupMessagesCount(long groupId, long userId, int status)
987                    throws SystemException {
988    
989                    if (status == WorkflowConstants.STATUS_ANY) {
990                            return mbMessagePersistence.countByG_U(groupId, userId);
991                    }
992                    else {
993                            return mbMessagePersistence.countByG_U_S(groupId, userId, status);
994                    }
995            }
996    
997            public MBMessage getMessage(long messageId)
998                    throws PortalException, SystemException {
999    
1000                    return mbMessagePersistence.findByPrimaryKey(messageId);
1001            }
1002    
1003            public MBMessageDisplay getMessageDisplay(
1004                            long messageId, int status, String threadView,
1005                            boolean includePrevAndNext)
1006                    throws PortalException, SystemException {
1007    
1008                    MBMessage message = getMessage(messageId);
1009    
1010                    return getMessageDisplay(
1011                            message, status, threadView, includePrevAndNext);
1012            }
1013    
1014            public MBMessageDisplay getMessageDisplay(
1015                            MBMessage message, int status, String threadView,
1016                            boolean includePrevAndNext)
1017                    throws PortalException, SystemException {
1018    
1019                    MBCategory category = null;
1020    
1021                    if ((message.getCategoryId() !=
1022                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
1023                            (message.getCategoryId() !=
1024                                    MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
1025    
1026                            category = mbCategoryPersistence.findByPrimaryKey(
1027                                    message.getCategoryId());
1028                    }
1029                    else {
1030                            category = new MBCategoryImpl();
1031    
1032                            category.setCategoryId(message.getCategoryId());
1033                    }
1034    
1035                    MBMessage parentMessage = null;
1036    
1037                    if (message.isReply()) {
1038                            parentMessage = mbMessagePersistence.findByPrimaryKey(
1039                                    message.getParentMessageId());
1040                    }
1041    
1042                    MBThread thread = mbThreadPersistence.findByPrimaryKey(
1043                            message.getThreadId());
1044    
1045                    if (!message.isDiscussion() &&
1046                            (message.getStatus() == WorkflowConstants.STATUS_APPROVED)) {
1047    
1048                            mbThreadLocalService.updateThread(
1049                                    thread.getThreadId(), thread.getViewCount() + 1);
1050                    }
1051    
1052                    MBThread previousThread = null;
1053                    MBThread nextThread = null;
1054    
1055                    if ((message.getStatus() == WorkflowConstants.STATUS_APPROVED) &&
1056                            includePrevAndNext) {
1057    
1058                            ThreadLastPostDateComparator comparator =
1059                                    new ThreadLastPostDateComparator(false);
1060    
1061                            MBThread[] prevAndNextThreads =
1062                                    mbThreadPersistence.findByG_C_PrevAndNext(
1063                                            message.getThreadId(), message.getGroupId(),
1064                                            message.getCategoryId(), comparator);
1065    
1066                            previousThread = prevAndNextThreads[0];
1067                            nextThread = prevAndNextThreads[2];
1068                    }
1069    
1070                    return new MBMessageDisplayImpl(
1071                            message, parentMessage, category, thread,
1072                            previousThread, nextThread, status, threadView);
1073            }
1074    
1075            public List<MBMessage> getMessages(
1076                            String className, long classPK, int status)
1077                    throws SystemException {
1078    
1079                    long classNameId = PortalUtil.getClassNameId(className);
1080    
1081                    if (status == WorkflowConstants.STATUS_ANY) {
1082                            return mbMessagePersistence.findByC_C(classNameId, classPK);
1083                    }
1084                    else {
1085                            return mbMessagePersistence.findByC_C_S(
1086                                    classNameId, classPK, status);
1087                    }
1088            }
1089    
1090            public List<MBMessage> getNoAssetMessages() throws SystemException {
1091                    return mbMessageFinder.findByNoAssets();
1092            }
1093    
1094            public int getPositionInThread(long messageId)
1095                    throws PortalException, SystemException {
1096    
1097                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1098    
1099                    return mbMessageFinder.countByC_T(
1100                            message.getCreateDate(), message.getThreadId());
1101            }
1102    
1103            public List<MBMessage> getThreadMessages(long threadId, int status)
1104                    throws SystemException {
1105    
1106                    return getThreadMessages(
1107                            threadId, status, new MessageThreadComparator());
1108            }
1109    
1110            public List<MBMessage> getThreadMessages(
1111                            long threadId, int status, Comparator<MBMessage> comparator)
1112                    throws SystemException {
1113    
1114                    List<MBMessage> messages = null;
1115    
1116                    if (status == WorkflowConstants.STATUS_ANY) {
1117                            messages = mbMessagePersistence.findByThreadId(threadId);
1118                    }
1119                    else {
1120                            messages = mbMessagePersistence.findByT_S(threadId, status);
1121                    }
1122    
1123                    return ListUtil.sort(messages, comparator);
1124            }
1125    
1126            public List<MBMessage> getThreadMessages(
1127                            long threadId, int status, int start, int end)
1128                    throws SystemException {
1129    
1130                    if (status == WorkflowConstants.STATUS_ANY) {
1131                            return mbMessagePersistence.findByThreadId(threadId, start, end);
1132                    }
1133                    else {
1134                            return mbMessagePersistence.findByT_S(threadId, status, start, end);
1135                    }
1136            }
1137    
1138            public int getThreadMessagesCount(long threadId, int status)
1139                    throws SystemException {
1140    
1141                    if (status == WorkflowConstants.STATUS_ANY) {
1142                            return mbMessagePersistence.countByThreadId(threadId);
1143                    }
1144                    else {
1145                            return mbMessagePersistence.countByT_S(threadId, status);
1146                    }
1147            }
1148    
1149            public List<MBMessage> getThreadRepliesMessages(
1150                            long threadId, int status, int start, int end)
1151                    throws SystemException {
1152    
1153                    if (status == WorkflowConstants.STATUS_ANY) {
1154                            return mbMessagePersistence.findByThreadReplies(
1155                                    threadId, start, end);
1156                    }
1157                    else {
1158                            return mbMessagePersistence.findByTR_S(
1159                                    threadId, status, start, end);
1160                    }
1161            }
1162    
1163            public void subscribeMessage(long userId, long messageId)
1164                    throws PortalException, SystemException {
1165    
1166                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1167    
1168                    subscriptionLocalService.addSubscription(
1169                            userId, MBThread.class.getName(), message.getThreadId());
1170            }
1171    
1172            public void unsubscribeMessage(long userId, long messageId)
1173                    throws PortalException, SystemException {
1174    
1175                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1176    
1177                    subscriptionLocalService.deleteSubscription(
1178                            userId, MBThread.class.getName(), message.getThreadId());
1179            }
1180    
1181            public void updateAsset(
1182                            long userId, MBMessage message, long[] assetCategoryIds,
1183                            String[] assetTagNames)
1184                    throws PortalException, SystemException {
1185    
1186                    boolean visible = false;
1187    
1188                    if (message.getStatus() == WorkflowConstants.STATUS_APPROVED) {
1189                            visible = true;
1190                    }
1191    
1192                    assetEntryLocalService.updateEntry(
1193                            userId, message.getGroupId(), message.getWorkflowClassName(),
1194                            message.getMessageId(), message.getUuid(), assetCategoryIds,
1195                            assetTagNames, visible, null, null, null, null,
1196                            ContentTypes.TEXT_HTML, message.getSubject(), null, null, null, 0,
1197                            0, null, false);
1198            }
1199    
1200            public MBMessage updateDiscussionMessage(
1201                            long userId, long messageId, String subject, String body,
1202                            int workflowAction)
1203                    throws PortalException, SystemException {
1204    
1205                    if (Validator.isNull(subject)) {
1206                            subject = body.substring(0, Math.min(body.length(), 50)) + "...";
1207                    }
1208    
1209                    List<ObjectValuePair<String, byte[]>> files =
1210                            new ArrayList<ObjectValuePair<String, byte[]>>();
1211                    List<String> existingFiles = new ArrayList<String>();
1212                    double priority = 0.0;
1213                    boolean allowPingbacks = false;
1214    
1215                    ServiceContext serviceContext = new ServiceContext();
1216    
1217                    serviceContext.setWorkflowAction(workflowAction);
1218    
1219                    return updateMessage(
1220                            userId, messageId, subject, body, files, existingFiles, priority,
1221                            allowPingbacks, serviceContext);
1222            }
1223    
1224            public MBMessage updateMessage(
1225                            long userId, long messageId, String subject, String body,
1226                            List<ObjectValuePair<String, byte[]>> files,
1227                            List<String> existingFiles, double priority, boolean allowPingbacks,
1228                            ServiceContext serviceContext)
1229                    throws PortalException, SystemException {
1230    
1231                    // Message
1232    
1233                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1234    
1235                    subject = ModelHintsUtil.trimString(
1236                            MBMessage.class.getName(), "subject", subject);
1237                    Date now = new Date();
1238    
1239                    validate(subject, body);
1240    
1241                    message.setModifiedDate(serviceContext.getModifiedDate(now));
1242                    message.setSubject(subject);
1243                    message.setBody(body);
1244                    message.setAttachments(!files.isEmpty() || !existingFiles.isEmpty());
1245                    message.setAllowPingbacks(allowPingbacks);
1246    
1247                    if (priority != MBThreadConstants.PRIORITY_NOT_GIVEN) {
1248                            message.setPriority(priority);
1249                    }
1250    
1251                    // Attachments
1252    
1253                    long companyId = message.getCompanyId();
1254                    String portletId = CompanyConstants.SYSTEM_STRING;
1255                    long groupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
1256                    long repositoryId = CompanyConstants.SYSTEM;
1257                    String dirName = message.getAttachmentsDir();
1258    
1259                    if (!files.isEmpty() || !existingFiles.isEmpty()) {
1260                            try {
1261                                    dlService.addDirectory(companyId, repositoryId, dirName);
1262                            }
1263                            catch (DuplicateDirectoryException dde) {
1264                            }
1265    
1266                            String[] fileNames = dlService.getFileNames(
1267                                    companyId, repositoryId, dirName);
1268    
1269                            for (String fileName: fileNames) {
1270                                    if (!existingFiles.contains(fileName)) {
1271                                            dlService.deleteFile(
1272                                                    companyId, portletId, repositoryId, fileName);
1273                                    }
1274                            }
1275    
1276                            for (int i = 0; i < files.size(); i++) {
1277                                    ObjectValuePair<String, byte[]> ovp = files.get(i);
1278    
1279                                    String fileName = ovp.getKey();
1280                                    byte[] bytes = ovp.getValue();
1281    
1282                                    try {
1283                                            dlService.addFile(
1284                                                    companyId, portletId, groupId, repositoryId,
1285                                                    dirName + "/" + fileName, 0, StringPool.BLANK,
1286                                                    message.getModifiedDate(), new ServiceContext(), bytes);
1287                                    }
1288                                    catch (DuplicateFileException dfe) {
1289                                    }
1290                            }
1291                    }
1292                    else {
1293                            try {
1294                                    dlService.deleteDirectory(
1295                                            companyId, portletId, repositoryId, dirName);
1296                            }
1297                            catch (NoSuchDirectoryException nsde) {
1298                            }
1299                    }
1300    
1301                    mbMessagePersistence.update(message, false);
1302    
1303                    // Thread
1304    
1305                    MBThread thread = mbThreadPersistence.findByPrimaryKey(
1306                            message.getThreadId());
1307    
1308                    if ((priority != MBThreadConstants.PRIORITY_NOT_GIVEN) &&
1309                            (thread.getPriority() != priority)) {
1310    
1311                            thread.setPriority(priority);
1312    
1313                            mbThreadPersistence.update(thread, false);
1314    
1315                            updatePriorities(thread.getThreadId(), priority);
1316                    }
1317    
1318                    // Asset
1319    
1320                    updateAsset(
1321                            userId, message, serviceContext.getAssetCategoryIds(),
1322                            serviceContext.getAssetTagNames());
1323    
1324                    // Expando
1325    
1326                    ExpandoBridge expandoBridge = message.getExpandoBridge();
1327    
1328                    expandoBridge.setAttributes(serviceContext);
1329    
1330                    // Workflow
1331    
1332                    serviceContext.setAttribute("update", Boolean.TRUE.toString());
1333    
1334                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
1335                            companyId, message.getGroupId(), userId,
1336                            message.getWorkflowClassName(), message.getMessageId(), message,
1337                            serviceContext);
1338    
1339                    return message;
1340            }
1341    
1342            public MBMessage updateMessage(long messageId, String body)
1343                    throws PortalException, SystemException {
1344    
1345                    MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1346    
1347                    message.setBody(body);
1348    
1349                    mbMessagePersistence.update(message, false);
1350    
1351                    return message;
1352            }
1353    
1354            public MBMessage updateStatus(
1355                            long userId, long messageId, int status,
1356                            ServiceContext serviceContext)
1357                    throws PortalException, SystemException {
1358    
1359                    MBMessage message = getMessage(messageId);
1360    
1361                    int oldStatus = message.getStatus();
1362    
1363                    User user = userPersistence.findByPrimaryKey(userId);
1364                    Date now = new Date();
1365    
1366                    message.setStatus(status);
1367                    message.setStatusByUserId(userId);
1368                    message.setStatusByUserName(user.getFullName());
1369                    message.setStatusDate(serviceContext.getModifiedDate(now));
1370    
1371                    mbMessagePersistence.update(message, false);
1372    
1373                    // Thread
1374    
1375                    MBThread thread = mbThreadPersistence.findByPrimaryKey(
1376                            message.getThreadId());
1377    
1378                    MBCategory category = null;
1379    
1380                    if ((thread.getCategoryId() !=
1381                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
1382                            (thread.getCategoryId() !=
1383                                    MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
1384    
1385                            category = mbCategoryPersistence.findByPrimaryKey(
1386                                    thread.getCategoryId());
1387                    }
1388    
1389                    if ((thread.getRootMessageId() == message.getMessageId()) &&
1390                            (oldStatus != status)) {
1391    
1392                            thread.setStatus(status);
1393                            thread.setStatusByUserId(userId);
1394                            thread.setStatusByUserName(user.getFullName());
1395                            thread.setStatusDate(serviceContext.getModifiedDate(now));
1396                    }
1397    
1398                    Indexer indexer = IndexerRegistryUtil.getIndexer(MBMessage.class);
1399    
1400                    if (status == WorkflowConstants.STATUS_APPROVED) {
1401                            if (oldStatus != WorkflowConstants.STATUS_APPROVED) {
1402    
1403                                    // Thread
1404    
1405                                    if ((category != null) &&
1406                                            (thread.getRootMessageId() == message.getMessageId())) {
1407    
1408                                            category.setThreadCount(category.getThreadCount() + 1);
1409    
1410                                            mbCategoryPersistence.update(category, false);
1411                                    }
1412    
1413                                    thread.setMessageCount(thread.getMessageCount() + 1);
1414    
1415                                    if (message.isAnonymous()) {
1416                                            thread.setLastPostByUserId(0);
1417                                    }
1418                                    else {
1419                                            thread.setLastPostByUserId(message.getUserId());
1420                                    }
1421    
1422                                    thread.setLastPostDate(serviceContext.getModifiedDate(now));
1423    
1424                                    // Category
1425    
1426                                    if (category != null) {
1427                                            category.setMessageCount(category.getMessageCount() + 1);
1428                                            category.setLastPostDate(
1429                                                    serviceContext.getModifiedDate(now));
1430    
1431                                            mbCategoryPersistence.update(category, false);
1432    
1433                                    }
1434    
1435                                    if (!message.isDiscussion()) {
1436    
1437                                            // Asset
1438    
1439                                            assetEntryLocalService.updateVisible(
1440                                                    MBMessage.class.getName(), message.getMessageId(),
1441                                                    true);
1442    
1443                                            // Social
1444    
1445                                            if (!message.isAnonymous() && !user.isDefaultUser()) {
1446                                                    int activityType = MBActivityKeys.ADD_MESSAGE;
1447                                                    long receiverUserId = 0;
1448                                                    String actionId = ActionKeys.ADD_MESSAGE;
1449    
1450                                                    MBMessage parentMessage =
1451                                                            mbMessagePersistence.fetchByPrimaryKey(
1452                                                                    message.getParentMessageId());
1453    
1454                                                    if (parentMessage != null) {
1455                                                            activityType = MBActivityKeys.REPLY_MESSAGE;
1456                                                            receiverUserId = parentMessage.getUserId();
1457    
1458                                                            if (receiverUserId != userId) {
1459                                                                    actionId = ActionKeys.REPLY_TO_MESSAGE;
1460                                                            }
1461                                                    }
1462    
1463                                                    socialActivityLocalService.addActivity(
1464                                                            userId, message.getGroupId(),
1465                                                            MBMessage.class.getName(), message.getMessageId(),
1466                                                            activityType, StringPool.BLANK, receiverUserId);
1467    
1468                                                    socialEquityLogLocalService.addEquityLogs(
1469                                                            userId, MBMessage.class.getName(), messageId,
1470                                                            actionId);
1471                                            }
1472                                    }
1473    
1474                                    // Subscriptions
1475    
1476                                    notifySubscribers(message, serviceContext);
1477                            }
1478    
1479                            // Indexer
1480    
1481                            if (!message.isDiscussion()) {
1482                                    indexer.reindex(message);
1483                            }
1484    
1485                            // Ping
1486    
1487                            pingPingback(message, serviceContext);
1488    
1489                            // Workflow
1490    
1491                            if (message.isDiscussion()) {
1492                                    updateDiscussionMessageStatus(
1493                                            userId, messageId, status, oldStatus, serviceContext);
1494                            }
1495                    }
1496                    else if ((oldStatus == WorkflowConstants.STATUS_APPROVED) &&
1497                                     (status != WorkflowConstants.STATUS_APPROVED)) {
1498    
1499                            // Thread
1500    
1501                            if ((category != null) &&
1502                                    (thread.getRootMessageId() == message.getMessageId())) {
1503    
1504                                    category.setThreadCount(category.getThreadCount() - 1);
1505    
1506                                    mbCategoryPersistence.update(category, false);
1507                            }
1508    
1509                            thread.setMessageCount(thread.getMessageCount() - 1);
1510    
1511                            // Category
1512    
1513                            if (category != null) {
1514                                    category.setMessageCount(category.getMessageCount() - 1);
1515    
1516                                    mbCategoryPersistence.update(category, false);
1517                            }
1518    
1519                            if (!message.isDiscussion()) {
1520    
1521                                    // Asset
1522    
1523                                    assetEntryLocalService.updateVisible(
1524                                            MBMessage.class.getName(), message.getMessageId(), false);
1525    
1526                                    // Indexer
1527    
1528                                    indexer.delete(message);
1529                            }
1530    
1531                    }
1532    
1533                    if (status != oldStatus) {
1534                            mbThreadPersistence.update(thread, false);
1535                    }
1536    
1537                    // Statistics
1538    
1539                    if (!message.isDiscussion()) {
1540                            mbStatsUserLocalService.updateStatsUser(
1541                                    message.getGroupId(), userId,
1542                                    serviceContext.getModifiedDate(now));
1543                    }
1544    
1545                    return message;
1546            }
1547    
1548            public void updateUserName(long userId, String userName)
1549                    throws SystemException {
1550    
1551                    List<MBMessage> messages = mbMessagePersistence.findByUserId(userId);
1552    
1553                    for (MBMessage message : messages) {
1554                            message.setUserName(userName);
1555    
1556                            mbMessagePersistence.update(message, false);
1557                    }
1558            }
1559    
1560            protected void deleteDiscussionSocialActivities(
1561                            String className, List<MBMessage> messages)
1562                    throws PortalException, SystemException {
1563    
1564                    if (messages.size() == 0) {
1565                            return;
1566                    }
1567    
1568                    MBMessage message = messages.get(0);
1569    
1570                    MBDiscussion discussion = mbDiscussionPersistence.findByThreadId(
1571                            message.getThreadId());
1572    
1573                    long classNameId = PortalUtil.getClassNameId(className);
1574                    long classPK = discussion.getClassPK();
1575    
1576                    if (discussion.getClassNameId() != classNameId) {
1577                            return;
1578                    }
1579    
1580                    Set<Long> messageIds = new HashSet<Long>();
1581    
1582                    for (MBMessage curMessage : messages) {
1583                            messageIds.add(curMessage.getMessageId());
1584                    }
1585    
1586                    List<SocialActivity> socialActivities =
1587                            socialActivityLocalService.getActivities(
1588                                    0, className, classPK, QueryUtil.ALL_POS, QueryUtil.ALL_POS);
1589    
1590                    for (SocialActivity socialActivity : socialActivities) {
1591                            if (Validator.isNull(socialActivity.getExtraData())) {
1592                                    continue;
1593                            }
1594    
1595                            JSONObject extraData = JSONFactoryUtil.createJSONObject(
1596                                    socialActivity.getExtraData());
1597    
1598                            long extraDataMessageId = extraData.getLong("messageId");
1599    
1600                            if (messageIds.contains(extraDataMessageId)) {
1601                                    socialActivityLocalService.deleteActivity(
1602                                            socialActivity.getActivityId());
1603                            }
1604                    }
1605            }
1606    
1607            protected void notifySubscribers(
1608                            MBMessage message, ServiceContext serviceContext)
1609                    throws PortalException, SystemException {
1610    
1611                    if (message.getStatus() != WorkflowConstants.STATUS_APPROVED) {
1612                            return;
1613                    }
1614    
1615                    String layoutFullURL = serviceContext.getLayoutFullURL();
1616    
1617                    if (Validator.isNull(layoutFullURL) || message.isDiscussion()) {
1618                            return;
1619                    }
1620    
1621                    PortletPreferences preferences =
1622                            ServiceContextUtil.getPortletPreferences(serviceContext);
1623    
1624                    if (preferences == null) {
1625                            long ownerId = message.getGroupId();
1626                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
1627                            long plid = PortletKeys.PREFS_PLID_SHARED;
1628                            String portletId = PortletKeys.MESSAGE_BOARDS;
1629                            String defaultPreferences = null;
1630    
1631                            preferences = portletPreferencesLocalService.getPreferences(
1632                                    message.getCompanyId(), ownerId, ownerType, plid, portletId,
1633                                    defaultPreferences);
1634                    }
1635    
1636                    boolean update = GetterUtil.getBoolean(
1637                            (String)serviceContext.getAttribute("update"));
1638    
1639                    if (!update && MBUtil.getEmailMessageAddedEnabled(preferences)) {
1640                    }
1641                    else if (update && MBUtil.getEmailMessageUpdatedEnabled(preferences)) {
1642                    }
1643                    else {
1644                            return;
1645                    }
1646    
1647                    Company company = companyPersistence.findByPrimaryKey(
1648                            message.getCompanyId());
1649    
1650                    Group group = groupPersistence.findByPrimaryKey(message.getGroupId());
1651    
1652                    String emailAddress = StringPool.BLANK;
1653                    String fullName = message.getUserName();
1654    
1655                    try {
1656                            User user = userPersistence.findByPrimaryKey(message.getUserId());
1657    
1658                            emailAddress = user.getEmailAddress();
1659                            fullName = user.getFullName();
1660                    }
1661                    catch (NoSuchUserException nsue) {
1662                    }
1663    
1664                    MBCategory category = message.getCategory();
1665    
1666                    if (message.isAnonymous()) {
1667                            emailAddress = StringPool.BLANK;
1668                            fullName = LanguageUtil.get(
1669                                    ServiceContextUtil.getLocale(serviceContext), "anonymous");
1670                    }
1671    
1672                    List<Long> categoryIds = new ArrayList<Long>();
1673    
1674                    categoryIds.add(message.getCategoryId());
1675    
1676                    if ((message.getCategoryId() !=
1677                                    MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
1678                            (message.getCategoryId() !=
1679                                    MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
1680    
1681                            categoryIds.addAll(category.getAncestorCategoryIds());
1682                    }
1683    
1684                    String messageURL =
1685                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR +
1686                                    "message_boards/view_message/" + message.getMessageId();
1687    
1688                    String portletName = PortalUtil.getPortletTitle(
1689                            PortletKeys.MESSAGE_BOARDS, LocaleUtil.getDefault());
1690    
1691                    String fromName = MBUtil.getEmailFromName(preferences);
1692                    String fromAddress = MBUtil.getEmailFromAddress(preferences);
1693    
1694                    String mailingListAddress = StringPool.BLANK;
1695    
1696                    if (PropsValues.POP_SERVER_NOTIFICATIONS_ENABLED) {
1697                            mailingListAddress = MBUtil.getMailingListAddress(
1698                                    message.getGroupId(), message.getCategoryId(),
1699                                    message.getMessageId(), company.getMx(), fromAddress);
1700                    }
1701    
1702                    String replyToAddress = mailingListAddress;
1703                    String mailId = MBUtil.getMailId(
1704                            company.getMx(), message.getCategoryId(), message.getMessageId());
1705    
1706                    fromName = StringUtil.replace(
1707                            fromName,
1708                            new String[] {
1709                                    "[$COMPANY_ID$]",
1710                                    "[$COMPANY_MX$]",
1711                                    "[$COMPANY_NAME$]",
1712                                    "[$COMMUNITY_NAME$]",
1713                                    "[$MAILING_LIST_ADDRESS$]",
1714                                    "[$MESSAGE_USER_ADDRESS$]",
1715                                    "[$MESSAGE_USER_NAME$]",
1716                                    "[$PORTLET_NAME$]"
1717                            },
1718                            new String[] {
1719                                    String.valueOf(company.getCompanyId()),
1720                                    company.getMx(),
1721                                    company.getName(),
1722                                    group.getName(),
1723                                    mailingListAddress,
1724                                    emailAddress,
1725                                    fullName,
1726                                    portletName
1727                            });
1728    
1729                    fromAddress = StringUtil.replace(
1730                            fromAddress,
1731                            new String[] {
1732                                    "[$COMPANY_ID$]",
1733                                    "[$COMPANY_MX$]",
1734                                    "[$COMPANY_NAME$]",
1735                                    "[$COMMUNITY_NAME$]",
1736                                    "[$MAILING_LIST_ADDRESS$]",
1737                                    "[$MESSAGE_USER_ADDRESS$]",
1738                                    "[$MESSAGE_USER_NAME$]",
1739                                    "[$PORTLET_NAME$]"
1740                            },
1741                            new String[] {
1742                                    String.valueOf(company.getCompanyId()),
1743                                    company.getMx(),
1744                                    company.getName(),
1745                                    group.getName(),
1746                                    mailingListAddress,
1747                                    emailAddress,
1748                                    fullName,
1749                                    portletName
1750                            });
1751    
1752                    String subjectPrefix = null;
1753                    String body = null;
1754                    String signature = null;
1755                    boolean htmlFormat = MBUtil.getEmailHtmlFormat(preferences);
1756    
1757                    if (update) {
1758                            subjectPrefix = MBUtil.getEmailMessageUpdatedSubjectPrefix(
1759                                    preferences);
1760                            body = MBUtil.getEmailMessageUpdatedBody(preferences);
1761                            signature = MBUtil.getEmailMessageUpdatedSignature(preferences);
1762                    }
1763                    else {
1764                            subjectPrefix = MBUtil.getEmailMessageAddedSubjectPrefix(
1765                                    preferences);
1766                            body = MBUtil.getEmailMessageAddedBody(preferences);
1767                            signature = MBUtil.getEmailMessageAddedSignature(preferences);
1768                    }
1769    
1770                    if (Validator.isNotNull(signature)) {
1771                            body +=  "\n--\n" + signature;
1772                    }
1773    
1774                    subjectPrefix = StringUtil.replace(
1775                            subjectPrefix,
1776                            new String[] {
1777                                    "[$CATEGORY_NAME$]",
1778                                    "[$COMPANY_ID$]",
1779                                    "[$COMPANY_MX$]",
1780                                    "[$COMPANY_NAME$]",
1781                                    "[$COMMUNITY_NAME$]",
1782                                    "[$FROM_ADDRESS$]",
1783                                    "[$FROM_NAME$]",
1784                                    "[$MAILING_LIST_ADDRESS$]",
1785                                    "[$MESSAGE_BODY$]",
1786                                    "[$MESSAGE_ID$]",
1787                                    "[$MESSAGE_SUBJECT$]",
1788                                    "[$MESSAGE_USER_ADDRESS$]",
1789                                    "[$MESSAGE_USER_NAME$]",
1790                                    "[$PORTAL_URL$]",
1791                                    "[$PORTLET_NAME$]"
1792                            },
1793                            new String[] {
1794                                    category.getName(),
1795                                    String.valueOf(company.getCompanyId()),
1796                                    company.getMx(),
1797                                    company.getName(),
1798                                    group.getName(),
1799                                    fromAddress,
1800                                    fromName,
1801                                    mailingListAddress,
1802                                    message.getBody(),
1803                                    String.valueOf(message.getMessageId()),
1804                                    message.getSubject(),
1805                                    emailAddress,
1806                                    fullName,
1807                                    company.getVirtualHost(),
1808                                    portletName
1809                            });
1810    
1811                    body = StringUtil.replace(
1812                            body,
1813                            new String[] {
1814                                    "[$CATEGORY_NAME$]",
1815                                    "[$COMPANY_ID$]",
1816                                    "[$COMPANY_MX$]",
1817                                    "[$COMPANY_NAME$]",
1818                                    "[$COMMUNITY_NAME$]",
1819                                    "[$FROM_ADDRESS$]",
1820                                    "[$FROM_NAME$]",
1821                                    "[$MAILING_LIST_ADDRESS$]",
1822                                    "[$MESSAGE_BODY$]",
1823                                    "[$MESSAGE_ID$]",
1824                                    "[$MESSAGE_SUBJECT$]",
1825                                    "[$MESSAGE_URL$]",
1826                                    "[$MESSAGE_USER_ADDRESS$]",
1827                                    "[$MESSAGE_USER_NAME$]",
1828                                    "[$PORTAL_URL$]",
1829                                    "[$PORTLET_NAME$]"
1830                            },
1831                            new String[] {
1832                                    category.getName(),
1833                                    String.valueOf(company.getCompanyId()),
1834                                    company.getMx(),
1835                                    company.getName(),
1836                                    group.getName(),
1837                                    fromAddress,
1838                                    fromName,
1839                                    mailingListAddress,
1840                                    message.getBody(),
1841                                    String.valueOf(message.getMessageId()),
1842                                    message.getSubject(),
1843                                    messageURL,
1844                                    emailAddress,
1845                                    fullName,
1846                                    company.getVirtualHost(),
1847                                    portletName
1848                            });
1849    
1850                    String subject = message.getSubject();
1851    
1852                    if (subject.indexOf(subjectPrefix) == -1) {
1853                            subject = subjectPrefix.trim() + " " + subject.trim();
1854                    }
1855    
1856                    String inReplyTo = null;
1857    
1858                    if (message.getParentMessageId() !=
1859                                    MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) {
1860    
1861                            inReplyTo = MBUtil.getMailId(
1862                                    company.getMx(), message.getCategoryId(),
1863                                    message.getParentMessageId());
1864                    }
1865    
1866                    com.liferay.portal.kernel.messaging.Message messagingObj =
1867                            new com.liferay.portal.kernel.messaging.Message();
1868    
1869                    messagingObj.put("companyId", message.getCompanyId());
1870                    messagingObj.put("userId", message.getUserId());
1871                    messagingObj.put("groupId", message.getGroupId());
1872                    messagingObj.put("categoryIds", StringUtil.merge(categoryIds));
1873                    messagingObj.put("threadId", message.getThreadId());
1874                    messagingObj.put("fromName", fromName);
1875                    messagingObj.put("fromAddress", fromAddress);
1876                    messagingObj.put("subject", subject);
1877                    messagingObj.put("body", body);
1878                    messagingObj.put("replyToAddress", replyToAddress);
1879                    messagingObj.put("mailId", mailId);
1880                    messagingObj.put("inReplyTo", inReplyTo);
1881                    messagingObj.put("htmlFormat", htmlFormat);
1882                    messagingObj.put(
1883                            "sourceMailingList", MailingListThreadLocal.isSourceMailingList());
1884    
1885                    MessageBusUtil.sendMessage(
1886                            DestinationNames.MESSAGE_BOARDS, messagingObj);
1887            }
1888    
1889            protected void pingPingback(
1890                    MBMessage message, ServiceContext serviceContext) {
1891    
1892                    if (!PropsValues.BLOGS_PINGBACK_ENABLED ||
1893                            !message.isAllowPingbacks() ||
1894                            (message.getStatus() != WorkflowConstants.STATUS_APPROVED)) {
1895    
1896                            return;
1897                    }
1898    
1899                    String layoutFullURL = serviceContext.getLayoutFullURL();
1900    
1901                    if (Validator.isNull(layoutFullURL)) {
1902                            return;
1903                    }
1904    
1905                    String sourceUri =
1906                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR +
1907                                    "message_boards/view_message/" + message.getMessageId();
1908    
1909                    Source source = new Source(message.getBody(true));
1910    
1911                    List<StartTag> startTags = source.getAllStartTags("a");
1912    
1913                    for (StartTag startTag : startTags) {
1914                            String targetUri = startTag.getAttributeValue("href");
1915    
1916                            if (Validator.isNotNull(targetUri)) {
1917                                    try {
1918                                            LinkbackProducerUtil.sendPingback(sourceUri, targetUri);
1919                                    }
1920                                    catch (Exception e) {
1921                                            _log.error("Error while sending pingback " + targetUri, e);
1922                                    }
1923                            }
1924                    }
1925            }
1926    
1927            protected void sendBlogsCommentsEmail(
1928                            long userId, BlogsEntry entry, MBMessage message,
1929                            ServiceContext serviceContext)
1930                    throws IOException, PortalException, SystemException {
1931    
1932                    long companyId = message.getCompanyId();
1933    
1934                    if (!PrefsPropsUtil.getBoolean(
1935                                    companyId, PropsKeys.BLOGS_EMAIL_COMMENTS_ADDED_ENABLED)) {
1936    
1937                            return;
1938                    }
1939    
1940                    String layoutFullURL = serviceContext.getLayoutFullURL();
1941    
1942                    String blogsEntryURL =
1943                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
1944                                    entry.getUrlTitle();
1945    
1946                    User user = userPersistence.findByPrimaryKey(userId);
1947    
1948                    String fromName = PrefsPropsUtil.getString(
1949                            companyId, PropsKeys.ADMIN_EMAIL_FROM_NAME);
1950                    String fromAddress = PrefsPropsUtil.getString(
1951                            companyId, PropsKeys.ADMIN_EMAIL_FROM_ADDRESS);
1952    
1953                    String subject = PrefsPropsUtil.getContent(
1954                            companyId, PropsKeys.BLOGS_EMAIL_COMMENTS_ADDED_SUBJECT);
1955                    String body = PrefsPropsUtil.getContent(
1956                            companyId, PropsKeys.BLOGS_EMAIL_COMMENTS_ADDED_BODY);
1957    
1958                    subject = StringUtil.replace(
1959                            subject,
1960                            new String[] {
1961                                    "[$BLOGS_COMMENTS_BODY$]",
1962                                    "[$BLOGS_COMMENTS_USER_ADDRESS$]",
1963                                    "[$BLOGS_COMMENTS_USER_NAME$]",
1964                                    "[$BLOGS_ENTRY_URL$]",
1965                                    "[$FROM_ADDRESS$]",
1966                                    "[$FROM_NAME$]"
1967                            },
1968                            new String[] {
1969                                    message.getBody(),
1970                                    user.getEmailAddress(),
1971                                    user.getFullName(),
1972                                    blogsEntryURL,
1973                                    fromAddress,
1974                                    fromName
1975                            });
1976    
1977                    body = StringUtil.replace(
1978                            body,
1979                            new String[] {
1980                                    "[$BLOGS_COMMENTS_BODY$]",
1981                                    "[$BLOGS_COMMENTS_USER_ADDRESS$]",
1982                                    "[$BLOGS_COMMENTS_USER_NAME$]",
1983                                    "[$BLOGS_ENTRY_URL$]",
1984                                    "[$FROM_ADDRESS$]",
1985                                    "[$FROM_NAME$]"
1986                            },
1987                            new String[] {
1988                                    message.getBody(),
1989                                    user.getEmailAddress(),
1990                                    user.getFullName(),
1991                                    blogsEntryURL,
1992                                    fromAddress,
1993                                    fromName
1994                            });
1995    
1996                    Set<Long> sent = new HashSet<Long>();
1997    
1998                    List<MBMessage> messages = mbMessagePersistence.findByThreadId(
1999                            message.getThreadId());
2000    
2001                    for (MBMessage curMessage : messages) {
2002                            long curMessageUserId = curMessage.getUserId();
2003    
2004                            if (curMessageUserId == userId) {
2005                                    continue;
2006                            }
2007    
2008                            if (sent.contains(curMessageUserId)) {
2009                                    if (_log.isDebugEnabled()) {
2010                                            _log.debug(
2011                                                    "Do not send a duplicate email to user " +
2012                                                            curMessageUserId);
2013                                    }
2014    
2015                                    continue;
2016                            }
2017                            else {
2018                                    if (_log.isDebugEnabled()) {
2019                                            _log.debug(
2020                                                    "Add user " + curMessageUserId +
2021                                                            " to the list of users who have received an email");
2022                                    }
2023    
2024                                    sent.add(curMessageUserId);
2025                            }
2026    
2027                            User curMessageUser = null;
2028    
2029                            try {
2030                                    curMessageUser = userLocalService.getUserById(curMessageUserId);
2031                            }
2032                            catch (NoSuchUserException nsue) {
2033                                    continue;
2034                            }
2035    
2036                            if (!curMessageUser.isActive()) {
2037                                    continue;
2038                            }
2039    
2040                            InternetAddress from = new InternetAddress(fromAddress, fromName);
2041    
2042                            InternetAddress to = new InternetAddress(
2043                                    curMessageUser.getEmailAddress(), curMessageUser.getFullName());
2044    
2045                            String curSubject = StringUtil.replace(
2046                                    subject,
2047                                    new String[] {
2048                                            "[$TO_ADDRESS$]",
2049                                            "[$TO_NAME$]"
2050                                    },
2051                                    new String[] {
2052                                            curMessageUser.getFullName(),
2053                                            curMessageUser.getEmailAddress()
2054                                    });
2055    
2056                            String curBody = StringUtil.replace(
2057                                    body,
2058                                    new String[] {
2059                                            "[$TO_ADDRESS$]",
2060                                            "[$TO_NAME$]"
2061                                    },
2062                                    new String[] {
2063                                            curMessageUser.getFullName(),
2064                                            curMessageUser.getEmailAddress()
2065                                    });
2066    
2067                            MailMessage mailMessage = new MailMessage(
2068                                    from, to, curSubject, curBody, true);
2069    
2070                            mailService.sendEmail(mailMessage);
2071                    }
2072            }
2073    
2074            protected void updateDiscussionMessageStatus(
2075                            long userId, long messageId, int status, int oldStatus,
2076                            ServiceContext serviceContext)
2077                    throws PortalException, SystemException {
2078    
2079                    String className = (String)serviceContext.getAttribute("className");
2080                    long classPK = GetterUtil.getLong(
2081                            (String)serviceContext.getAttribute("classPK"));
2082    
2083                    MBMessage message = getMessage(messageId);
2084    
2085                    if ((oldStatus != WorkflowConstants.STATUS_APPROVED) &&
2086                            (status == WorkflowConstants.STATUS_APPROVED)) {
2087    
2088                            // Social
2089    
2090                            if (!message.isRoot()) {
2091                                    socialEquityLogLocalService.addEquityLogs(
2092                                            userId, className, classPK, ActionKeys.ADD_DISCUSSION);
2093                            }
2094    
2095                            long parentMessageId = message.getParentMessageId();
2096    
2097                            if (className.equals(BlogsEntry.class.getName()) &&
2098                                    (parentMessageId !=
2099                                            MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID)) {
2100    
2101                                    // Social
2102    
2103                                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(
2104                                            classPK);
2105    
2106                                    JSONObject extraData = JSONFactoryUtil.createJSONObject();
2107    
2108                                    extraData.put("messageId", message.getMessageId());
2109    
2110                                    socialActivityLocalService.addActivity(
2111                                            userId, entry.getGroupId(), BlogsEntry.class.getName(),
2112                                            classPK, BlogsActivityKeys.ADD_COMMENT,
2113                                            extraData.toString(), entry.getUserId());
2114    
2115                                    // Email
2116    
2117                                    try {
2118                                            sendBlogsCommentsEmail(
2119                                                    userId, entry, message, serviceContext);
2120                                    }
2121                                    catch (Exception e) {
2122                                            _log.error(e, e);
2123                                    }
2124                            }
2125                    }
2126            }
2127    
2128            protected void updatePriorities(long threadId, double priority)
2129                    throws SystemException {
2130    
2131                    List<MBMessage> messages = mbMessagePersistence.findByThreadId(
2132                            threadId);
2133    
2134                    for (MBMessage message : messages) {
2135                            if (message.getPriority() != priority) {
2136                                    message.setPriority(priority);
2137    
2138                                    mbMessagePersistence.update(message, false);
2139                            }
2140                    }
2141            }
2142    
2143            protected void validate(String subject, String body)
2144                    throws PortalException {
2145    
2146                    if (Validator.isNull(subject)) {
2147                            throw new MessageSubjectException();
2148                    }
2149    
2150                    if (Validator.isNull(body)) {
2151                            throw new MessageBodyException();
2152                    }
2153            }
2154    
2155            private static Log _log = LogFactoryUtil.getLog(
2156                    MBMessageLocalServiceImpl.class);
2157    
2158    }