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