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(
483 threadId);
484
485 long oldCategoryId = thread.getCategoryId();
486
487 MBCategory oldCategory = null;
488
489 if (oldCategoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
490 oldCategory = mbCategoryPersistence.findByPrimaryKey(
491 oldCategoryId);
492 }
493
494 MBCategory category = null;
495
496 if (categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
497 category = mbCategoryPersistence.findByPrimaryKey(
498 categoryId);
499 }
500
501
502
503 List<MBMessage> messages = mbMessagePersistence.findByG_C_T(
504 groupId, oldCategoryId, thread.getThreadId());
505
506 for (MBMessage message : messages) {
507 message.setCategoryId(categoryId);
508
509 mbMessagePersistence.update(message, false);
510
511
512
513 if (!message.isDiscussion()) {
514 Indexer indexer = IndexerRegistryUtil.getIndexer(
515 MBMessage.class);
516
517 indexer.reindex(message);
518 }
519 }
520
521
522
523 thread.setCategoryId(categoryId);
524
525 mbThreadPersistence.update(thread, false);
526
527
528
529 if ((oldCategory != null) && (categoryId != oldCategoryId)) {
530 oldCategory.setThreadCount(oldCategory.getThreadCount() - 1);
531 oldCategory.setMessageCount(
532 oldCategory.getMessageCount() - thread.getMessageCount());
533
534 mbCategoryPersistence.update(oldCategory, false);
535 }
536
537 if ((category != null) && (categoryId != oldCategoryId)) {
538 category.setThreadCount(category.getThreadCount() + 1);
539 category.setMessageCount(
540 category.getMessageCount() + thread.getMessageCount());
541
542 mbCategoryPersistence.update(category, false);
543 }
544
545 return thread;
546 }
547
548 public MBThread splitThread(
549 long messageId, String subject, ServiceContext serviceContext)
550 throws PortalException, SystemException {
551
552 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
553
554 if (message.isRoot()) {
555 throw new SplitThreadException();
556 }
557
558 MBCategory category = message.getCategory();
559 MBThread oldThread = message.getThread();
560 MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
561 oldThread.getRootMessageId());
562 String oldAttachmentsDir = message.getAttachmentsDir();
563
564
565
566 mbMessageLocalService.updateAnswer(message, false, true);
567
568
569
570 MBThread thread = addThread(message.getCategoryId(), message);
571
572
573
574 if (Validator.isNotNull(subject)) {
575 MBMessageDisplay messageDisplay =
576 mbMessageService.getMessageDisplay(
577 messageId, WorkflowConstants.STATUS_ANY,
578 MBThreadConstants.THREAD_VIEW_TREE, false);
579
580 MBTreeWalker treeWalker = messageDisplay.getTreeWalker();
581
582 List<MBMessage> messages = treeWalker.getMessages();
583
584 int[] range = treeWalker.getChildrenRange(message);
585
586 for (int i = range[0]; i < range[1]; i++) {
587 MBMessage curMessage = messages.get(i);
588
589 String oldSubject = message.getSubject();
590 String curSubject = curMessage.getSubject();
591
592 if (oldSubject.startsWith("RE: ")) {
593 curSubject = StringUtil.replace(
594 curSubject, rootMessage.getSubject(), subject);
595 }
596 else {
597 curSubject = StringUtil.replace(
598 curSubject, oldSubject, subject);
599 }
600
601 curMessage.setSubject(curSubject);
602
603 mbMessagePersistence.update(curMessage, false);
604 }
605
606 message.setSubject(subject);
607 }
608
609 message.setThreadId(thread.getThreadId());
610 message.setRootMessageId(thread.getRootMessageId());
611 message.setParentMessageId(0);
612 message.setAttachmentsDir(null);
613
614 mbMessagePersistence.update(message, false);
615
616
617
618 moveAttachmentsFromOldThread(message, oldAttachmentsDir);
619
620
621
622 if (!message.isDiscussion()) {
623 Indexer indexer = IndexerRegistryUtil.getIndexer(MBMessage.class);
624
625 indexer.reindex(message);
626 }
627
628
629
630 int messagesMoved = 1;
631
632 messagesMoved += moveChildrenMessages(
633 message, category, oldThread.getThreadId());
634
635
636
637 thread.setMessageCount(messagesMoved);
638
639 mbThreadPersistence.update(thread, false);
640
641
642
643 oldThread.setMessageCount(oldThread.getMessageCount() - messagesMoved);
644
645 mbThreadPersistence.update(oldThread, false);
646
647
648
649 if ((message.getCategoryId() !=
650 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
651 (message.getCategoryId() !=
652 MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
653
654 category.setThreadCount(category.getThreadCount() + 1);
655
656 mbCategoryPersistence.update(category, false);
657 }
658
659 return thread;
660 }
661
662 public void updateQuestion(long threadId, boolean question)
663 throws PortalException, SystemException {
664
665 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
666
667 if (thread.isQuestion() == question) {
668 return;
669 }
670
671 thread.setQuestion(question);
672
673 mbThreadPersistence.update(thread, false);
674
675 if (!question) {
676 MBMessage message = mbMessagePersistence.findByPrimaryKey(
677 thread.getRootMessageId());
678
679 mbMessageLocalService.updateAnswer(message, false, true);
680 }
681 }
682
683
686 public MBThread updateThread(long threadId, int viewCount)
687 throws PortalException, SystemException {
688
689 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
690
691 thread.setViewCount(viewCount);
692
693 mbThreadPersistence.update(thread, false);
694
695 return thread;
696 }
697
698 protected void moveAttachmentFromOldThread(
699 long companyId, String fileName, String newAttachmentsDir)
700 throws PortalException, SystemException {
701
702 long repositoryId = CompanyConstants.SYSTEM;
703
704 StringBundler sb = new StringBundler(4);
705
706 sb.append(newAttachmentsDir);
707 sb.append(StringPool.SLASH);
708 sb.append(StringUtil.extractLast(fileName, CharPool.SLASH));
709
710 String newFileName = sb.toString();
711
712 try {
713 File file = DLStoreUtil.getFile(
714 companyId, repositoryId, fileName);
715
716 DLStoreUtil.addFile(
717 companyId, repositoryId, newFileName, false, file);
718 }
719 catch (UnsupportedOperationException uoe) {
720 InputStream is = DLStoreUtil.getFileAsStream(
721 companyId, repositoryId, fileName);
722
723 try {
724 DLStoreUtil.addFile(
725 companyId, repositoryId, newFileName, false, is);
726 }
727 finally {
728 try {
729 is.close();
730 }
731 catch (IOException ioe) {
732 _log.error(ioe);
733 }
734 }
735 }
736
737 DLStoreUtil.deleteFile(companyId, repositoryId, fileName);
738 }
739
740 protected void moveAttachmentsFromOldThread(
741 MBMessage message, String oldAttachmentsDir)
742 throws PortalException, SystemException {
743
744 if (!message.getAttachments()) {
745 return;
746 }
747
748 long companyId = message.getCompanyId();
749 long repositoryId = CompanyConstants.SYSTEM;
750 String newAttachmentsDir = message.getAttachmentsDir();
751
752 try {
753 DLStoreUtil.addDirectory(
754 companyId, repositoryId, newAttachmentsDir);
755 }
756 catch (DuplicateDirectoryException dde) {
757 }
758
759 String[] fileNames = DLStoreUtil.getFileNames(
760 companyId, repositoryId, oldAttachmentsDir);
761
762 for (String fileName : fileNames) {
763 moveAttachmentFromOldThread(companyId, fileName, newAttachmentsDir);
764 }
765
766 try {
767 DLStoreUtil.deleteDirectory(
768 companyId, repositoryId, oldAttachmentsDir);
769 }
770 catch (NoSuchDirectoryException nsde) {
771 }
772 }
773
774 protected int moveChildrenMessages(
775 MBMessage parentMessage, MBCategory category, long oldThreadId)
776 throws PortalException, SystemException {
777
778 int messagesMoved = 0;
779
780 List<MBMessage> messages = mbMessagePersistence.findByT_P(
781 oldThreadId, parentMessage.getMessageId());
782
783 for (MBMessage message : messages) {
784 String oldAttachmentsDir = message.getAttachmentsDir();
785
786 message.setCategoryId(parentMessage.getCategoryId());
787 message.setThreadId(parentMessage.getThreadId());
788 message.setRootMessageId(parentMessage.getRootMessageId());
789 message.setAttachmentsDir(null);
790
791 mbMessagePersistence.update(message, false);
792
793 moveAttachmentsFromOldThread(message, oldAttachmentsDir);
794
795 if (!message.isDiscussion()) {
796 Indexer indexer = IndexerRegistryUtil.getIndexer(
797 MBMessage.class);
798
799 indexer.reindex(message);
800 }
801
802 messagesMoved++;
803
804 messagesMoved += moveChildrenMessages(
805 message, category, oldThreadId);
806 }
807
808 return messagesMoved;
809 }
810
811 private static Log _log = LogFactoryUtil.getLog(
812 MBThreadLocalServiceImpl.class);
813
814 }