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