001
014
015 package com.liferay.portlet.messageboards.service.impl;
016
017 import com.liferay.portal.kernel.exception.PortalException;
018 import com.liferay.portal.kernel.exception.SystemException;
019 import com.liferay.portal.kernel.increment.BufferedIncrement;
020 import com.liferay.portal.kernel.increment.NumberIncrement;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.search.Indexer;
024 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
025 import com.liferay.portal.kernel.util.CharPool;
026 import com.liferay.portal.kernel.util.StringBundler;
027 import com.liferay.portal.kernel.util.StringPool;
028 import com.liferay.portal.kernel.util.StringUtil;
029 import com.liferay.portal.kernel.util.Validator;
030 import com.liferay.portal.kernel.workflow.WorkflowConstants;
031 import com.liferay.portal.model.CompanyConstants;
032 import com.liferay.portal.model.ResourceConstants;
033 import com.liferay.portal.service.ServiceContext;
034 import com.liferay.portlet.documentlibrary.DuplicateDirectoryException;
035 import com.liferay.portlet.documentlibrary.NoSuchDirectoryException;
036 import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
037 import com.liferay.portlet.messageboards.SplitThreadException;
038 import com.liferay.portlet.messageboards.model.MBCategory;
039 import com.liferay.portlet.messageboards.model.MBCategoryConstants;
040 import com.liferay.portlet.messageboards.model.MBMessage;
041 import com.liferay.portlet.messageboards.model.MBMessageDisplay;
042 import com.liferay.portlet.messageboards.model.MBThread;
043 import com.liferay.portlet.messageboards.model.MBThreadConstants;
044 import com.liferay.portlet.messageboards.model.MBTreeWalker;
045 import com.liferay.portlet.messageboards.service.base.MBThreadLocalServiceBaseImpl;
046
047 import java.io.File;
048 import java.io.IOException;
049 import java.io.InputStream;
050
051 import java.util.ArrayList;
052 import java.util.List;
053
054
058 public class MBThreadLocalServiceImpl extends MBThreadLocalServiceBaseImpl {
059
060 public MBThread addThread(long categoryId, MBMessage message)
061 throws PortalException, SystemException {
062
063
064
065 long threadId = message.getThreadId();
066
067 if (!message.isRoot() || (threadId <= 0)) {
068 threadId = counterLocalService.increment();
069 }
070
071 MBThread thread = mbThreadPersistence.create(threadId);
072
073 thread.setGroupId(message.getGroupId());
074 thread.setCompanyId(message.getCompanyId());
075 thread.setCategoryId(categoryId);
076 thread.setRootMessageId(message.getMessageId());
077 thread.setRootMessageUserId(message.getUserId());
078
079 if (message.isAnonymous()) {
080 thread.setLastPostByUserId(0);
081 }
082 else {
083 thread.setLastPostByUserId(message.getUserId());
084 }
085
086 thread.setLastPostDate(message.getCreateDate());
087
088 if (message.getPriority() != MBThreadConstants.PRIORITY_NOT_GIVEN) {
089 thread.setPriority(message.getPriority());
090 }
091
092 thread.setStatus(message.getStatus());
093 thread.setStatusByUserId(message.getStatusByUserId());
094 thread.setStatusByUserName(message.getStatusByUserName());
095 thread.setStatusDate(message.getStatusDate());
096
097 mbThreadPersistence.update(thread, false);
098
099
100
101 if (categoryId >= 0) {
102 assetEntryLocalService.updateEntry(
103 message.getUserId(), message.getGroupId(),
104 MBThread.class.getName(), thread.getThreadId(), null, 0,
105 new long[0], new String[0], false, null, null, null, null, null,
106 String.valueOf(thread.getRootMessageId()), null, null, null,
107 null, 0, 0, null, false);
108 }
109
110 return thread;
111 }
112
113 public void deleteThread(long threadId)
114 throws PortalException, SystemException {
115
116 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
117
118 deleteThread(thread);
119 }
120
121 public void deleteThread(MBThread thread)
122 throws PortalException, SystemException {
123
124 MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
125 thread.getRootMessageId());
126
127
128
129 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
130 MBMessage.class);
131
132 indexer.delete(thread);
133
134
135
136 long companyId = rootMessage.getCompanyId();
137 long repositoryId = CompanyConstants.SYSTEM;
138 String dirName = thread.getAttachmentsDir();
139
140 try {
141 DLStoreUtil.deleteDirectory(companyId, repositoryId, dirName);
142 }
143 catch (NoSuchDirectoryException nsde) {
144 }
145
146
147
148 subscriptionLocalService.deleteSubscriptions(
149 thread.getCompanyId(), MBThread.class.getName(),
150 thread.getThreadId());
151
152
153
154 mbThreadFlagPersistence.removeByThreadId(thread.getThreadId());
155
156
157
158 List<MBMessage> messages = mbMessagePersistence.findByThreadId(
159 thread.getThreadId());
160
161 for (MBMessage message : messages) {
162
163
164
165 ratingsStatsLocalService.deleteStats(
166 message.getWorkflowClassName(), message.getMessageId());
167
168
169
170 assetEntryLocalService.deleteEntry(
171 message.getWorkflowClassName(), message.getMessageId());
172
173
174
175 if (!message.isDiscussion()) {
176 resourceLocalService.deleteResource(
177 message.getCompanyId(), message.getWorkflowClassName(),
178 ResourceConstants.SCOPE_INDIVIDUAL, message.getMessageId());
179 }
180
181
182
183 mbMessagePersistence.remove(message);
184
185
186
187 if (!message.isDiscussion()) {
188 mbStatsUserLocalService.updateStatsUser(
189 message.getGroupId(), message.getUserId());
190 }
191
192
193
194 workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
195 message.getCompanyId(), message.getGroupId(),
196 message.getWorkflowClassName(), message.getMessageId());
197 }
198
199
200
201 if ((rootMessage.getCategoryId() !=
202 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
203 (rootMessage.getCategoryId() !=
204 MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
205
206 MBCategory category = mbCategoryPersistence.findByPrimaryKey(
207 thread.getCategoryId());
208
209 category.setThreadCount(category.getThreadCount() - 1);
210 category.setMessageCount(
211 category.getMessageCount() - thread.getMessageCount());
212
213 mbCategoryPersistence.update(category, false);
214 }
215
216
217
218 assetEntryLocalService.deleteEntry(
219 MBThread.class.getName(), thread.getThreadId());
220
221
222
223 mbThreadPersistence.remove(thread);
224 }
225
226 public void deleteThreads(long groupId, long categoryId)
227 throws PortalException, SystemException {
228
229 List<MBThread> threads = mbThreadPersistence.findByG_C(
230 groupId, categoryId);
231
232 for (MBThread thread : threads) {
233 deleteThread(thread);
234 }
235 }
236
237 public MBThread fetchThread(long threadId) throws SystemException {
238 return mbThreadPersistence.fetchByPrimaryKey(threadId);
239 }
240
241 public int getCategoryThreadsCount(
242 long groupId, long categoryId, int status)
243 throws SystemException {
244
245 if (status == WorkflowConstants.STATUS_ANY) {
246 return mbThreadPersistence.countByG_C(groupId, categoryId);
247 }
248 else {
249 return mbThreadPersistence.countByG_C_S(
250 groupId, categoryId, status);
251 }
252 }
253
254 public List<MBThread> getGroupThreads(
255 long groupId, int status, int start, int end)
256 throws SystemException {
257
258 if (status == WorkflowConstants.STATUS_ANY) {
259 return mbThreadPersistence.findByG_NotC(
260 groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, start,
261 end);
262 }
263 else {
264 return mbThreadPersistence.findByG_NotC_S(
265 groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, status,
266 start, end);
267 }
268 }
269
270 public List<MBThread> getGroupThreads(
271 long groupId, long userId, int status, boolean subscribed,
272 boolean includeAnonymous, int start, int end)
273 throws PortalException, SystemException {
274
275 if (userId <= 0) {
276 if (status == WorkflowConstants.STATUS_ANY) {
277 return mbThreadPersistence.findByG_NotC(
278 groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, start,
279 end);
280 }
281 else {
282 return mbThreadPersistence.findByG_NotC_S(
283 groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, status,
284 start, end);
285 }
286 }
287 else {
288 if (subscribed) {
289 return mbThreadFinder.findByS_G_U_C_S(
290 groupId, userId, null, status, start, end);
291 }
292 else {
293 List<Long> threadIds = null;
294
295 if (includeAnonymous) {
296 threadIds = mbMessageFinder.findByG_U_C_S(
297 groupId, userId, null, status, start, end);
298 }
299 else {
300 threadIds = mbMessageFinder.findByG_U_C_A_S(
301 groupId, userId, null, false, status, start, end);
302 }
303
304 List<MBThread> threads = new ArrayList<MBThread>(
305 threadIds.size());
306
307 for (long threadId : threadIds) {
308 MBThread thread = mbThreadPersistence.findByPrimaryKey(
309 threadId);
310
311 threads.add(thread);
312 }
313
314 return threads;
315 }
316 }
317 }
318
319 public List<MBThread> getGroupThreads(
320 long groupId, long userId, int status, boolean subscribed,
321 int start, int end)
322 throws PortalException, SystemException {
323
324 return getGroupThreads(
325 groupId, userId, status, subscribed, true, start, end);
326 }
327
328 public List<MBThread> getGroupThreads(
329 long groupId, long userId, int status, int start, int end)
330 throws PortalException, SystemException {
331
332 return getGroupThreads(groupId, userId, status, false, start, end);
333 }
334
335 public int getGroupThreadsCount(long groupId, int status)
336 throws SystemException {
337
338 if (status == WorkflowConstants.STATUS_ANY) {
339 return mbThreadPersistence.countByG_NotC(
340 groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID);
341 }
342 else {
343 return mbThreadPersistence.countByG_NotC_S(
344 groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, status);
345 }
346 }
347
348 public int getGroupThreadsCount(long groupId, long userId, int status)
349 throws SystemException {
350
351 return getGroupThreadsCount(groupId, userId, status, false);
352 }
353
354 public int getGroupThreadsCount(
355 long groupId, long userId, int status, boolean subscribed)
356 throws SystemException {
357
358 return getGroupThreadsCount(groupId, userId, status, subscribed, true);
359 }
360
361 public int getGroupThreadsCount(
362 long groupId, long userId, int status, boolean subscribed,
363 boolean includeAnonymous)
364 throws SystemException {
365
366 if (userId <= 0) {
367 if (status == WorkflowConstants.STATUS_ANY) {
368 return mbThreadPersistence.countByG_NotC(
369 groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID);
370 }
371 else {
372 return mbThreadPersistence.countByG_NotC_S(
373 groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID,
374 status);
375 }
376 }
377 else {
378 if (subscribed) {
379 return mbThreadFinder.countByS_G_U_C_S(
380 groupId, userId, null, status);
381 }
382 else {
383 if (includeAnonymous) {
384 return mbMessageFinder.countByG_U_C_S(
385 groupId, userId, null, status);
386 }
387 else {
388 return mbMessageFinder.countByG_U_C_A_S(
389 groupId, userId, null, false, status);
390 }
391 }
392 }
393 }
394
395 public List<MBThread> getNoAssetThreads() throws SystemException {
396 return mbThreadFinder.findByNoAssets();
397 }
398
399 public List<MBThread> getPriorityThreads(long categoryId, double priority)
400 throws PortalException, SystemException {
401
402 return getPriorityThreads(categoryId, priority, false);
403 }
404
405 public List<MBThread> getPriorityThreads(
406 long categoryId, double priority, boolean inherit)
407 throws PortalException, SystemException {
408
409 if (!inherit) {
410 return mbThreadPersistence.findByC_P(categoryId, priority);
411 }
412
413 List<MBThread> threads = new ArrayList<MBThread>();
414
415 while ((categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
416 (categoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
417
418 threads.addAll(
419 0, mbThreadPersistence.findByC_P(categoryId, priority));
420
421 MBCategory category = mbCategoryPersistence.findByPrimaryKey(
422 categoryId);
423
424 categoryId = category.getParentCategoryId();
425 }
426
427 return threads;
428 }
429
430 public MBThread getThread(long threadId)
431 throws PortalException, SystemException {
432
433 return mbThreadPersistence.findByPrimaryKey(threadId);
434 }
435
436 public List<MBThread> getThreads(
437 long groupId, long categoryId, int status, int start, int end)
438 throws SystemException {
439
440 if (status == WorkflowConstants.STATUS_ANY) {
441 return mbThreadPersistence.findByG_C(
442 groupId, categoryId, start, end);
443 }
444 else {
445 return mbThreadPersistence.findByG_C_S(
446 groupId, categoryId, status, start, end);
447 }
448 }
449
450 public int getThreadsCount(long groupId, long categoryId, int status)
451 throws SystemException {
452
453 if (status == WorkflowConstants.STATUS_ANY) {
454 return mbThreadPersistence.countByG_C(groupId, categoryId);
455 }
456 else {
457 return mbThreadPersistence.countByG_C_S(
458 groupId, categoryId, status);
459 }
460 }
461
462 public boolean hasAnswerMessage(long threadId) throws SystemException {
463 int count = mbMessagePersistence.countByT_A(threadId, true);
464
465 if (count > 0) {
466 return true;
467 }
468 else {
469 return false;
470 }
471 }
472
473 @BufferedIncrement(incrementClass = NumberIncrement.class)
474 public MBThread incrementViewCounter(long threadId, int increment)
475 throws PortalException, SystemException {
476
477 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
478
479 thread.setViewCount(thread.getViewCount() + increment);
480
481 mbThreadPersistence.update(thread, false);
482
483 return thread;
484 }
485
486 public MBThread moveThread(long groupId, long categoryId, long threadId)
487 throws PortalException, SystemException {
488
489 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
490
491 long oldCategoryId = thread.getCategoryId();
492
493 MBCategory oldCategory = null;
494
495 if (oldCategoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
496 oldCategory = mbCategoryPersistence.findByPrimaryKey(oldCategoryId);
497 }
498
499 MBCategory category = null;
500
501 if (categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
502 category = mbCategoryPersistence.findByPrimaryKey(categoryId);
503 }
504
505
506
507 List<MBMessage> messages = mbMessagePersistence.findByG_C_T(
508 groupId, oldCategoryId, thread.getThreadId());
509
510 for (MBMessage message : messages) {
511 message.setCategoryId(categoryId);
512
513 mbMessagePersistence.update(message, false);
514
515
516
517 if (!message.isDiscussion()) {
518 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
519 MBMessage.class);
520
521 indexer.reindex(message);
522 }
523 }
524
525
526
527 thread.setCategoryId(categoryId);
528
529 mbThreadPersistence.update(thread, false);
530
531
532
533 if ((oldCategory != null) && (categoryId != oldCategoryId)) {
534 oldCategory.setThreadCount(oldCategory.getThreadCount() - 1);
535 oldCategory.setMessageCount(
536 oldCategory.getMessageCount() - thread.getMessageCount());
537
538 mbCategoryPersistence.update(oldCategory, false);
539 }
540
541 if ((category != null) && (categoryId != oldCategoryId)) {
542 category.setThreadCount(category.getThreadCount() + 1);
543 category.setMessageCount(
544 category.getMessageCount() + thread.getMessageCount());
545
546 mbCategoryPersistence.update(category, false);
547 }
548
549 return thread;
550 }
551
552 public MBThread splitThread(
553 long messageId, String subject, ServiceContext serviceContext)
554 throws PortalException, SystemException {
555
556 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
557
558 if (message.isRoot()) {
559 throw new SplitThreadException();
560 }
561
562 MBCategory category = message.getCategory();
563 MBThread oldThread = message.getThread();
564 MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
565 oldThread.getRootMessageId());
566 String oldAttachmentsDir = message.getAttachmentsDir();
567
568
569
570 mbMessageLocalService.updateAnswer(message, false, true);
571
572
573
574 MBThread thread = addThread(message.getCategoryId(), message);
575
576
577
578 if (Validator.isNotNull(subject)) {
579 MBMessageDisplay messageDisplay =
580 mbMessageService.getMessageDisplay(
581 messageId, WorkflowConstants.STATUS_ANY,
582 MBThreadConstants.THREAD_VIEW_TREE, false);
583
584 MBTreeWalker treeWalker = messageDisplay.getTreeWalker();
585
586 List<MBMessage> messages = treeWalker.getMessages();
587
588 int[] range = treeWalker.getChildrenRange(message);
589
590 for (int i = range[0]; i < range[1]; i++) {
591 MBMessage curMessage = messages.get(i);
592
593 String oldSubject = message.getSubject();
594 String curSubject = curMessage.getSubject();
595
596 if (oldSubject.startsWith("RE: ")) {
597 curSubject = StringUtil.replace(
598 curSubject, rootMessage.getSubject(), subject);
599 }
600 else {
601 curSubject = StringUtil.replace(
602 curSubject, oldSubject, subject);
603 }
604
605 curMessage.setSubject(curSubject);
606
607 mbMessagePersistence.update(curMessage, false);
608 }
609
610 message.setSubject(subject);
611 }
612
613 message.setThreadId(thread.getThreadId());
614 message.setRootMessageId(thread.getRootMessageId());
615 message.setParentMessageId(0);
616 message.setAttachmentsDir(null);
617
618 mbMessagePersistence.update(message, false);
619
620
621
622 moveAttachmentsFromOldThread(message, oldAttachmentsDir);
623
624
625
626 if (!message.isDiscussion()) {
627 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
628 MBMessage.class);
629
630 indexer.reindex(message);
631 }
632
633
634
635 int messagesMoved = 1;
636
637 messagesMoved += moveChildrenMessages(
638 message, category, oldThread.getThreadId());
639
640
641
642 thread.setMessageCount(messagesMoved);
643
644 mbThreadPersistence.update(thread, false);
645
646
647
648 oldThread.setMessageCount(oldThread.getMessageCount() - messagesMoved);
649
650 mbThreadPersistence.update(oldThread, false);
651
652
653
654 if ((message.getCategoryId() !=
655 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
656 (message.getCategoryId() !=
657 MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
658
659 category.setThreadCount(category.getThreadCount() + 1);
660
661 mbCategoryPersistence.update(category, false);
662 }
663
664 return thread;
665 }
666
667 public void updateQuestion(long threadId, boolean question)
668 throws PortalException, SystemException {
669
670 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
671
672 if (thread.isQuestion() == question) {
673 return;
674 }
675
676 thread.setQuestion(question);
677
678 mbThreadPersistence.update(thread, false);
679
680 if (!question) {
681 MBMessage message = mbMessagePersistence.findByPrimaryKey(
682 thread.getRootMessageId());
683
684 mbMessageLocalService.updateAnswer(message, false, true);
685 }
686 }
687
688
691 public MBThread updateThread(long threadId, int viewCount)
692 throws PortalException, SystemException {
693
694 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
695
696 thread.setViewCount(viewCount);
697
698 mbThreadPersistence.update(thread, false);
699
700 return thread;
701 }
702
703 protected void moveAttachmentFromOldThread(
704 long companyId, String fileName, String newAttachmentsDir)
705 throws PortalException, SystemException {
706
707 long repositoryId = CompanyConstants.SYSTEM;
708
709 StringBundler sb = new StringBundler(4);
710
711 sb.append(newAttachmentsDir);
712 sb.append(StringPool.SLASH);
713 sb.append(StringUtil.extractLast(fileName, CharPool.SLASH));
714
715 String newFileName = sb.toString();
716
717 try {
718 File file = DLStoreUtil.getFile(companyId, repositoryId, fileName);
719
720 DLStoreUtil.addFile(
721 companyId, repositoryId, newFileName, false, file);
722 }
723 catch (UnsupportedOperationException uoe) {
724 InputStream is = DLStoreUtil.getFileAsStream(
725 companyId, repositoryId, fileName);
726
727 try {
728 DLStoreUtil.addFile(
729 companyId, repositoryId, newFileName, false, is);
730 }
731 finally {
732 try {
733 is.close();
734 }
735 catch (IOException ioe) {
736 _log.error(ioe);
737 }
738 }
739 }
740
741 DLStoreUtil.deleteFile(companyId, repositoryId, fileName);
742 }
743
744 protected void moveAttachmentsFromOldThread(
745 MBMessage message, String oldAttachmentsDir)
746 throws PortalException, SystemException {
747
748 if (!message.getAttachments()) {
749 return;
750 }
751
752 long companyId = message.getCompanyId();
753 long repositoryId = CompanyConstants.SYSTEM;
754 String newAttachmentsDir = message.getAttachmentsDir();
755
756 try {
757 DLStoreUtil.addDirectory(
758 companyId, repositoryId, newAttachmentsDir);
759 }
760 catch (DuplicateDirectoryException dde) {
761 }
762
763 String[] fileNames = DLStoreUtil.getFileNames(
764 companyId, repositoryId, oldAttachmentsDir);
765
766 for (String fileName : fileNames) {
767 moveAttachmentFromOldThread(companyId, fileName, newAttachmentsDir);
768 }
769
770 try {
771 DLStoreUtil.deleteDirectory(
772 companyId, repositoryId, oldAttachmentsDir);
773 }
774 catch (NoSuchDirectoryException nsde) {
775 }
776 }
777
778 protected int moveChildrenMessages(
779 MBMessage parentMessage, MBCategory category, long oldThreadId)
780 throws PortalException, SystemException {
781
782 int messagesMoved = 0;
783
784 List<MBMessage> messages = mbMessagePersistence.findByT_P(
785 oldThreadId, parentMessage.getMessageId());
786
787 for (MBMessage message : messages) {
788 String oldAttachmentsDir = message.getAttachmentsDir();
789
790 message.setCategoryId(parentMessage.getCategoryId());
791 message.setThreadId(parentMessage.getThreadId());
792 message.setRootMessageId(parentMessage.getRootMessageId());
793 message.setAttachmentsDir(null);
794
795 mbMessagePersistence.update(message, false);
796
797 moveAttachmentsFromOldThread(message, oldAttachmentsDir);
798
799 if (!message.isDiscussion()) {
800 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
801 MBMessage.class);
802
803 indexer.reindex(message);
804 }
805
806 messagesMoved++;
807
808 messagesMoved += moveChildrenMessages(
809 message, category, oldThreadId);
810 }
811
812 return messagesMoved;
813 }
814
815 private static Log _log = LogFactoryUtil.getLog(
816 MBThreadLocalServiceImpl.class);
817
818 }