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