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