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