1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.messageboards.service.impl;
24  
25  import com.liferay.documentlibrary.DuplicateDirectoryException;
26  import com.liferay.documentlibrary.NoSuchDirectoryException;
27  import com.liferay.portal.PortalException;
28  import com.liferay.portal.SystemException;
29  import com.liferay.portal.kernel.log.Log;
30  import com.liferay.portal.kernel.log.LogFactoryUtil;
31  import com.liferay.portal.kernel.search.SearchException;
32  import com.liferay.portal.kernel.util.StringPool;
33  import com.liferay.portal.kernel.util.StringUtil;
34  import com.liferay.portal.model.CompanyConstants;
35  import com.liferay.portal.model.GroupConstants;
36  import com.liferay.portal.model.ResourceConstants;
37  import com.liferay.portal.model.User;
38  import com.liferay.portal.service.ServiceContext;
39  import com.liferay.portlet.messageboards.model.MBCategory;
40  import com.liferay.portlet.messageboards.model.MBMessage;
41  import com.liferay.portlet.messageboards.model.MBThread;
42  import com.liferay.portlet.messageboards.model.impl.MBMessageFlagImpl;
43  import com.liferay.portlet.messageboards.model.impl.MBThreadImpl;
44  import com.liferay.portlet.messageboards.service.base.MBThreadLocalServiceBaseImpl;
45  import com.liferay.portlet.messageboards.util.Indexer;
46  
47  import java.util.List;
48  
49  /**
50   * <a href="MBThreadLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
51   *
52   * @author Brian Wing Shun Chan
53   *
54   */
55  public class MBThreadLocalServiceImpl extends MBThreadLocalServiceBaseImpl {
56  
57      public void deleteThread(long threadId)
58          throws PortalException, SystemException {
59  
60          MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
61  
62          deleteThread(thread);
63      }
64  
65      public void deleteThread(MBThread thread)
66          throws PortalException, SystemException {
67  
68          MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
69              thread.getRootMessageId());
70  
71          // Indexer
72  
73          try {
74              Indexer.deleteMessages(
75                  rootMessage.getCompanyId(), thread.getThreadId());
76          }
77          catch (SearchException se) {
78              _log.error("Deleting index " + thread.getThreadId(), se);
79          }
80  
81          // Attachments
82  
83          long companyId = rootMessage.getCompanyId();
84          String portletId = CompanyConstants.SYSTEM_STRING;
85          long repositoryId = CompanyConstants.SYSTEM;
86          String dirName = thread.getAttachmentsDir();
87  
88          try {
89              dlService.deleteDirectory(
90                  companyId, portletId, repositoryId, dirName);
91          }
92          catch (NoSuchDirectoryException nsde) {
93          }
94  
95          // Messages
96  
97          List<MBMessage> messages = mbMessagePersistence.findByThreadId(
98              thread.getThreadId());
99  
100         for (MBMessage message : messages) {
101 
102             // Tags
103 
104             tagsAssetLocalService.deleteAsset(
105                 MBMessage.class.getName(), message.getMessageId());
106 
107             // Social
108 
109             socialActivityLocalService.deleteActivities(
110                 MBMessage.class.getName(), message.getMessageId());
111 
112             // Ratings
113 
114             ratingsStatsLocalService.deleteStats(
115                 MBMessage.class.getName(), message.getMessageId());
116 
117             // Message flags
118 
119             mbMessageFlagPersistence.removeByMessageId(message.getMessageId());
120 
121             // Resources
122 
123             if (!message.isDiscussion()) {
124                 resourceLocalService.deleteResource(
125                     message.getCompanyId(), MBMessage.class.getName(),
126                     ResourceConstants.SCOPE_INDIVIDUAL, message.getMessageId());
127             }
128 
129             // Message
130 
131             mbMessagePersistence.remove(message);
132         }
133 
134         // Thread
135 
136         mbThreadPersistence.remove(thread);
137     }
138 
139     public void deleteThreads(long categoryId)
140         throws PortalException, SystemException {
141 
142         List<MBThread> threads = mbThreadPersistence.findByCategoryId(
143             categoryId);
144 
145         for (MBThread thread : threads) {
146             deleteThread(thread);
147         }
148     }
149 
150     public int getCategoriesThreadsCount(List<Long> categoryIds)
151         throws SystemException {
152 
153         return mbThreadFinder.countByCategoryIds(categoryIds);
154     }
155 
156     public List<MBThread> getGroupThreads(long groupId, int start, int end)
157         throws SystemException {
158 
159         return mbThreadFinder.findByGroupId(groupId, start, end);
160     }
161 
162     public List<MBThread> getGroupThreads(
163             long groupId, long userId, int start, int end)
164         throws SystemException {
165 
166         return getGroupThreads(groupId, userId, false, start, end);
167     }
168 
169     public List<MBThread> getGroupThreads(
170             long groupId, long userId, boolean subscribed, int start, int end)
171         throws SystemException {
172 
173         return getGroupThreads(groupId, userId, subscribed, true, start, end);
174     }
175 
176     public List<MBThread> getGroupThreads(
177             long groupId, long userId, boolean subscribed,
178             boolean includeAnonymous, int start, int end)
179         throws SystemException {
180 
181         if (userId <= 0) {
182             return mbThreadFinder.findByGroupId(groupId, start, end);
183         }
184         else {
185             if (subscribed) {
186                 return mbThreadFinder.findByS_G_U(groupId, userId, start, end);
187             }
188             else {
189                 if (includeAnonymous) {
190                     return mbThreadFinder.findByG_U(
191                         groupId, userId, start, end);
192                 }
193                 else {
194                     return mbThreadFinder.findByG_U_A(
195                         groupId, userId, false, start, end);
196                 }
197             }
198         }
199     }
200 
201     public int getGroupThreadsCount(long groupId) throws SystemException {
202         return mbThreadFinder.countByGroupId(groupId);
203     }
204 
205     public int getGroupThreadsCount(long groupId, long userId)
206         throws SystemException {
207 
208         return getGroupThreadsCount(groupId, userId, false);
209     }
210 
211     public int getGroupThreadsCount(
212             long groupId, long userId, boolean subscribed)
213         throws SystemException {
214 
215         return getGroupThreadsCount(groupId, userId, subscribed, true);
216     }
217 
218     public int getGroupThreadsCount(
219             long groupId, long userId, boolean subscribed,
220             boolean includeAnonymous)
221         throws SystemException {
222 
223         if (userId <= 0) {
224             return mbThreadFinder.countByGroupId(groupId);
225         }
226         else {
227             if (subscribed) {
228                 return mbThreadFinder.countByS_G_U(groupId, userId);
229             }
230             else {
231                 if (includeAnonymous) {
232                     return mbThreadFinder.countByG_U(groupId, userId);
233                 }
234                 else {
235                     return mbThreadFinder.countByG_U_A(groupId, userId, false);
236                 }
237             }
238         }
239     }
240 
241     public MBThread getThread(long threadId)
242         throws PortalException, SystemException {
243 
244         return mbThreadPersistence.findByPrimaryKey(threadId);
245     }
246 
247     public List<MBThread> getThreads(long categoryId, int start, int end)
248         throws SystemException {
249 
250         return mbThreadPersistence.findByCategoryId(categoryId, start, end);
251     }
252 
253     public int getThreadsCount(long categoryId) throws SystemException {
254         return mbThreadPersistence.countByCategoryId(categoryId);
255     }
256 
257     public boolean hasReadThread(long userId, long threadId)
258         throws PortalException, SystemException {
259 
260         User user = userPersistence.findByPrimaryKey(userId);
261 
262         if (user.isDefaultUser()) {
263             return true;
264         }
265 
266         int total = mbMessagePersistence.countByThreadId(threadId);
267         int read = mbMessageFlagFinder.countByU_T_F(
268             userId, threadId, MBMessageFlagImpl.READ_FLAG);
269 
270         if (total != read) {
271             return false;
272         }
273         else {
274             return true;
275         }
276     }
277 
278     public MBThread moveThread(long categoryId, long threadId)
279         throws PortalException, SystemException {
280 
281         MBThread thread = mbThreadPersistence.findByPrimaryKey(
282             threadId);
283 
284         long oldCategoryId = thread.getCategoryId();
285 
286         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
287             categoryId);
288 
289         // Messages
290 
291         List<MBMessage> messages = mbMessagePersistence.findByC_T(
292             oldCategoryId, thread.getThreadId());
293 
294         for (MBMessage message : messages) {
295             message.setCategoryId(category.getCategoryId());
296 
297             mbMessagePersistence.update(message, false);
298 
299             // Indexer
300 
301             try {
302                 if (!category.isDiscussion()) {
303                     Indexer.updateMessage(
304                         message.getCompanyId(), category.getGroupId(),
305                         message.getUserId(), message.getUserName(),
306                         category.getCategoryId(), message.getThreadId(),
307                         message.getMessageId(), message.getSubject(),
308                         message.getBody(), message.isAnonymous(),
309                         message.getModifiedDate(), message.getTagsEntries(),
310                         message.getExpandoBridge());
311                 }
312             }
313             catch (SearchException se) {
314                 _log.error("Indexing " + message.getMessageId(), se);
315             }
316         }
317 
318         // Thread
319 
320         thread.setCategoryId(category.getCategoryId());
321 
322         mbThreadPersistence.update(thread, false);
323 
324         return thread;
325     }
326 
327     public MBThread splitThread(long messageId, ServiceContext serviceContext)
328         throws PortalException, SystemException {
329 
330         MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
331 
332         MBCategory category = message.getCategory();
333         long oldThreadId = message.getThreadId();
334         String oldAttachmentsDir = message.getAttachmentsDir();
335 
336         // Message flags
337 
338         mbMessageFlagLocalService.deleteQuestionAndAnswerFlags(oldThreadId);
339 
340         // Create new thread
341 
342         MBThread thread = addThread(message.getCategoryId(), message);
343 
344         // Update message
345 
346         message.setThreadId(thread.getThreadId());
347         message.setParentMessageId(0);
348         message.setAttachmentsDir(null);
349 
350         mbMessagePersistence.update(message, false);
351 
352         // Attachments
353 
354         moveAttachmentsFromOldThread(message, oldAttachmentsDir);
355 
356         // Indexer
357 
358         try {
359             if (!category.isDiscussion()) {
360                 Indexer.updateMessage(
361                     message.getCompanyId(), category.getGroupId(),
362                     message.getUserId(), message.getUserName(),
363                     category.getCategoryId(), message.getThreadId(),
364                     message.getMessageId(), message.getSubject(),
365                     message.getBody(), message.isAnonymous(),
366                     message.getModifiedDate(), message.getTagsEntries(),
367                     message.getExpandoBridge());
368             }
369         }
370         catch (SearchException se) {
371             _log.error("Indexing " + message.getMessageId(), se);
372         }
373 
374         // Update children
375 
376         int messagesMoved = 1;
377 
378         messagesMoved += moveChildrenMessages(
379             message, category, oldThreadId);
380 
381         // Update new thread
382 
383         thread.setMessageCount(messagesMoved);
384 
385         mbThreadPersistence.update(thread, false);
386 
387         // Update old thread
388 
389         MBThread oldThread = mbThreadPersistence.findByPrimaryKey(oldThreadId);
390 
391         oldThread.setMessageCount(oldThread.getMessageCount() - messagesMoved);
392 
393         mbThreadPersistence.update(oldThread, false);
394 
395         return thread;
396     }
397 
398     public MBThread updateThread(long threadId, int viewCount)
399         throws PortalException, SystemException {
400 
401         MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
402 
403         thread.setViewCount(viewCount);
404 
405         mbThreadPersistence.update(thread, false);
406 
407         return thread;
408     }
409 
410     protected MBThread addThread(long categoryId, MBMessage message)
411         throws SystemException, PortalException {
412 
413         long threadId = counterLocalService.increment();
414 
415         MBThread thread = mbThreadPersistence.create(threadId);
416 
417         thread.setCategoryId(categoryId);
418         thread.setRootMessageId(message.getMessageId());
419 
420         thread.setMessageCount(thread.getMessageCount() + 1);
421 
422         if (message.isAnonymous()) {
423             thread.setLastPostByUserId(0);
424         }
425         else {
426             thread.setLastPostByUserId(message.getUserId());
427         }
428 
429         thread.setLastPostDate(message.getCreateDate());
430 
431         if (message.getPriority() != MBThreadImpl.PRIORITY_NOT_GIVEN) {
432             thread.setPriority(message.getPriority());
433         }
434 
435         mbThreadPersistence.update(thread, false);
436 
437         return thread;
438     }
439 
440     protected void moveAttachmentsFromOldThread(
441             MBMessage message, String oldAttachmentsDir)
442         throws PortalException, SystemException {
443 
444         if (!message.getAttachments()) {
445             return;
446         }
447 
448         long companyId = message.getCompanyId();
449         String portletId = CompanyConstants.SYSTEM_STRING;
450         long groupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
451         long repositoryId = CompanyConstants.SYSTEM;
452         String newAttachmentsDir = message.getAttachmentsDir();
453 
454         try {
455             dlService.addDirectory(companyId, repositoryId, newAttachmentsDir);
456         }
457         catch (DuplicateDirectoryException dde) {
458         }
459 
460         String[] fileNames = dlService.getFileNames(
461             companyId, repositoryId, oldAttachmentsDir);
462 
463         for (String fileName : fileNames) {
464             String name = StringUtil.extractLast(fileName, StringPool.SLASH);
465             byte[] fileBytes = dlService.getFile(
466                 companyId, repositoryId, fileName);
467 
468             dlService.addFile(
469                 companyId, portletId, groupId, repositoryId,
470                 newAttachmentsDir + "/" + name, 0, StringPool.BLANK,
471                 message.getModifiedDate(), new String[0], fileBytes);
472 
473             dlService.deleteFile(companyId, portletId, repositoryId, fileName);
474         }
475 
476         try {
477             dlService.deleteDirectory(
478                 companyId, portletId, repositoryId, oldAttachmentsDir);
479         }
480         catch (NoSuchDirectoryException nsde) {
481         }
482     }
483 
484     protected int moveChildrenMessages(
485             MBMessage parentMessage, MBCategory category, long oldThreadId)
486         throws SystemException, PortalException {
487 
488         int messagesMoved = 0;
489 
490         List<MBMessage> messages = mbMessagePersistence.findByT_P(
491             oldThreadId, parentMessage.getMessageId());
492 
493         for (MBMessage message : messages) {
494             String oldAttachmentsDir = message.getAttachmentsDir();
495 
496             message.setCategoryId(parentMessage.getCategoryId());
497             message.setThreadId(parentMessage.getThreadId());
498             message.setAttachmentsDir(null);
499 
500             mbMessagePersistence.update(message, false);
501 
502             moveAttachmentsFromOldThread(message, oldAttachmentsDir);
503 
504             try {
505                 if (!category.isDiscussion()) {
506                     Indexer.updateMessage(
507                         message.getCompanyId(), category.getGroupId(),
508                         message.getUserId(), message.getUserName(),
509                         category.getCategoryId(), message.getThreadId(),
510                         message.getMessageId(), message.getSubject(),
511                         message.getBody(), message.isAnonymous(),
512                         message.getModifiedDate(), message.getTagsEntries(),
513                         message.getExpandoBridge());
514                 }
515             }
516             catch (SearchException se) {
517                 _log.error("Indexing " + message.getMessageId(), se);
518             }
519 
520             messagesMoved++;
521 
522             messagesMoved += moveChildrenMessages(
523                 message, category, oldThreadId);
524         }
525 
526         return messagesMoved;
527     }
528 
529     private static Log _log =
530          LogFactoryUtil.getLog(MBThreadLocalServiceImpl.class);
531 
532 }