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