1   /**
2    * Copyright (c) 2000-2008 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.search.SearchException;
30  import com.liferay.portal.kernel.util.StringPool;
31  import com.liferay.portal.kernel.util.StringUtil;
32  import com.liferay.portal.model.CompanyConstants;
33  import com.liferay.portal.model.ResourceConstants;
34  import com.liferay.portal.model.User;
35  import com.liferay.portal.model.impl.GroupImpl;
36  import com.liferay.portal.theme.ThemeDisplay;
37  import com.liferay.portlet.messageboards.model.MBCategory;
38  import com.liferay.portlet.messageboards.model.MBMessage;
39  import com.liferay.portlet.messageboards.model.MBThread;
40  import com.liferay.portlet.messageboards.model.impl.MBThreadImpl;
41  import com.liferay.portlet.messageboards.service.base.MBThreadLocalServiceBaseImpl;
42  import com.liferay.portlet.messageboards.util.Indexer;
43  
44  import java.rmi.RemoteException;
45  
46  import java.util.List;
47  
48  import javax.portlet.PortletPreferences;
49  
50  import org.apache.commons.logging.Log;
51  import org.apache.commons.logging.LogFactory;
52  
53  /**
54   * <a href="MBThreadLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
55   *
56   * @author Brian Wing Shun Chan
57   *
58   */
59  public class MBThreadLocalServiceImpl extends MBThreadLocalServiceBaseImpl {
60  
61      public void deleteThread(long threadId)
62          throws PortalException, SystemException {
63  
64          MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
65  
66          deleteThread(thread);
67      }
68  
69      public void deleteThread(MBThread thread)
70          throws PortalException, SystemException {
71  
72          MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
73              thread.getRootMessageId());
74  
75          // Lucene
76  
77          try {
78              Indexer.deleteMessages(
79                  rootMessage.getCompanyId(), thread.getThreadId());
80          }
81          catch (SearchException se) {
82              _log.error("Deleting index " + thread.getThreadId(), se);
83          }
84  
85          // Attachments
86  
87          long companyId = rootMessage.getCompanyId();
88          String portletId = CompanyConstants.SYSTEM_STRING;
89          long repositoryId = CompanyConstants.SYSTEM;
90          String dirName = thread.getAttachmentsDir();
91  
92          try {
93              dlService.deleteDirectory(
94                  companyId, portletId, repositoryId, dirName);
95          }
96          catch (NoSuchDirectoryException nsde) {
97          }
98          catch (RemoteException re) {
99              throw new SystemException(re);
100         }
101 
102         // Messages
103 
104         List<MBMessage> messages = mbMessagePersistence.findByThreadId(
105             thread.getThreadId());
106 
107         for (MBMessage message : messages) {
108 
109             // Tags
110 
111             tagsAssetLocalService.deleteAsset(
112                 MBMessage.class.getName(), message.getMessageId());
113 
114             // Social
115 
116             socialActivityLocalService.deleteActivities(
117                 MBMessage.class.getName(), message.getMessageId());
118 
119             // Ratings
120 
121             ratingsStatsLocalService.deleteStats(
122                 MBMessage.class.getName(), message.getMessageId());
123 
124             // Message flags
125 
126             mbMessageFlagPersistence.removeByMessageId(message.getMessageId());
127 
128             // Resources
129 
130             if (!message.isDiscussion()) {
131                 resourceLocalService.deleteResource(
132                     message.getCompanyId(), MBMessage.class.getName(),
133                     ResourceConstants.SCOPE_INDIVIDUAL, message.getMessageId());
134             }
135 
136             // Message
137 
138             mbMessagePersistence.remove(message.getMessageId());
139         }
140 
141         // Thread
142 
143         mbThreadPersistence.remove(thread.getThreadId());
144     }
145 
146     public void deleteThreads(long categoryId)
147         throws PortalException, SystemException {
148 
149         List<MBThread> threads = mbThreadPersistence.findByCategoryId(
150             categoryId);
151 
152         for (MBThread thread : threads) {
153             deleteThread(thread);
154         }
155     }
156 
157     public int getCategoriesThreadsCount(List<Long> categoryIds)
158         throws SystemException {
159 
160         return mbThreadFinder.countByCategoryIds(categoryIds);
161     }
162 
163     public List<MBThread> getGroupThreads(long groupId, int start, int end)
164         throws SystemException {
165 
166         return mbThreadFinder.findByGroupId(groupId, start, end);
167     }
168 
169     public List<MBThread> getGroupThreads(
170             long groupId, long userId, int start, int end)
171         throws SystemException {
172 
173         return getGroupThreads(groupId, userId, false, start, end);
174     }
175 
176     public List<MBThread> getGroupThreads(
177             long groupId, long userId, boolean subscribed, int start, int end)
178         throws SystemException {
179 
180         if (userId <= 0) {
181             return mbThreadFinder.findByGroupId(groupId, start, end);
182         }
183         else {
184             if (subscribed) {
185                 return mbThreadFinder.findByS_G_U(groupId, userId, start, end);
186             }
187             else {
188                 return mbThreadFinder.findByG_U(groupId, userId, start, end);
189             }
190         }
191     }
192 
193     public int getGroupThreadsCount(long groupId) throws SystemException {
194         return mbThreadFinder.countByGroupId(groupId);
195     }
196 
197     public int getGroupThreadsCount(long groupId, long userId)
198         throws SystemException {
199 
200         return getGroupThreadsCount(groupId, userId, false);
201     }
202 
203     public int getGroupThreadsCount(
204             long groupId, long userId, boolean subscribed)
205         throws SystemException {
206 
207         if (userId <= 0) {
208             return mbThreadFinder.countByGroupId(groupId);
209         }
210         else {
211             if (subscribed) {
212                 return mbThreadFinder.countByS_G_U(groupId, userId);
213             }
214             else {
215                 return mbThreadFinder.countByG_U(groupId, userId);
216             }
217         }
218     }
219 
220     public MBThread getThread(long threadId)
221         throws PortalException, SystemException {
222 
223         return mbThreadPersistence.findByPrimaryKey(threadId);
224     }
225 
226     public List<MBThread> getThreads(long categoryId, int start, int end)
227         throws SystemException {
228 
229         return mbThreadPersistence.findByCategoryId(categoryId, start, end);
230     }
231 
232     public int getThreadsCount(long categoryId) throws SystemException {
233         return mbThreadPersistence.countByCategoryId(categoryId);
234     }
235 
236     public boolean hasReadThread(long userId, long threadId)
237         throws PortalException, SystemException {
238 
239         User user = userPersistence.findByPrimaryKey(userId);
240 
241         if (user.isDefaultUser()) {
242             return true;
243         }
244 
245         int total = mbMessagePersistence.countByThreadId(threadId);
246         int read = mbMessageFlagFinder.countByU_T(userId, threadId);
247 
248         if (total != read) {
249             return false;
250         }
251         else {
252             return true;
253         }
254     }
255 
256     public MBThread moveThread(long categoryId, long threadId)
257         throws PortalException, SystemException {
258 
259         MBThread thread = mbThreadPersistence.findByPrimaryKey(
260             threadId);
261 
262         long oldCategoryId = thread.getCategoryId();
263 
264         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
265             categoryId);
266 
267         // Messages
268 
269         List<MBMessage> messages = mbMessagePersistence.findByC_T(
270             oldCategoryId, thread.getThreadId());
271 
272         for (MBMessage message : messages) {
273             message.setCategoryId(category.getCategoryId());
274 
275             mbMessagePersistence.update(message, false);
276 
277             // Lucene
278 
279             try {
280                 if (!category.isDiscussion()) {
281                     Indexer.updateMessage(
282                         message.getCompanyId(), category.getGroupId(),
283                         message.getUserName(), category.getCategoryId(),
284                         message.getThreadId(), message.getMessageId(),
285                         message.getSubject(), message.getBody(),
286                         message.getTagsEntries());
287                 }
288             }
289             catch (SearchException se) {
290                 _log.error("Indexing " + message.getMessageId(), se);
291             }
292         }
293 
294         // Thread
295 
296         thread.setCategoryId(category.getCategoryId());
297 
298         mbThreadPersistence.update(thread, false);
299 
300         return thread;
301     }
302 
303     public MBThread splitThread(
304             long messageId, PortletPreferences prefs, ThemeDisplay themeDisplay)
305         throws PortalException, SystemException {
306 
307         MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
308 
309         MBCategory category = message.getCategory();
310         long oldThreadId = message.getThreadId();
311         String oldAttachmentsDir = message.getAttachmentsDir();
312 
313         // Create new thread
314 
315         MBThread thread = addThread(message.getCategoryId(), message);
316 
317         // Update message
318 
319         message.setThreadId(thread.getThreadId());
320         message.setParentMessageId(0);
321         message.setAttachmentsDir(null);
322 
323         mbMessagePersistence.update(message, false);
324 
325         // Attachments
326 
327         moveAttachmentsFromOldThread(message, oldAttachmentsDir);
328 
329         // Lucene
330 
331         try {
332             if (!category.isDiscussion()) {
333                 Indexer.updateMessage(
334                     message.getCompanyId(), category.getGroupId(),
335                     message.getUserName(), category.getCategoryId(),
336                     message.getThreadId(), message.getMessageId(),
337                     message.getSubject(), message.getBody(),
338                     message.getTagsEntries());
339             }
340         }
341         catch (SearchException se) {
342             _log.error("Indexing " + message.getMessageId(), se);
343         }
344 
345         // Update children
346 
347         int messagesMoved = 1;
348 
349         messagesMoved += moveChildrenMessages(
350             message, category, oldThreadId);
351 
352         // Update new thread
353 
354         thread.setMessageCount(messagesMoved);
355 
356         mbThreadPersistence.update(thread, false);
357 
358         // Update old thread
359 
360         MBThread oldThread = mbThreadPersistence.findByPrimaryKey(oldThreadId);
361 
362         oldThread.setMessageCount(oldThread.getMessageCount() - messagesMoved);
363 
364         mbThreadPersistence.update(oldThread, false);
365 
366         return thread;
367     }
368 
369     public MBThread updateThread(long threadId, int viewCount)
370         throws PortalException, SystemException {
371 
372         MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
373 
374         thread.setViewCount(viewCount);
375 
376         mbThreadPersistence.update(thread, false);
377 
378         return thread;
379     }
380 
381     protected MBThread addThread(long categoryId, MBMessage message)
382         throws SystemException, PortalException {
383 
384         long threadId = counterLocalService.increment();
385 
386         MBThread thread = mbThreadPersistence.create(threadId);
387 
388         thread.setCategoryId(categoryId);
389         thread.setRootMessageId(message.getMessageId());
390 
391         thread.setMessageCount(thread.getMessageCount() + 1);
392 
393         if (message.isAnonymous()) {
394             thread.setLastPostByUserId(0);
395         }
396         else {
397             thread.setLastPostByUserId(message.getUserId());
398         }
399 
400         thread.setLastPostDate(message.getCreateDate());
401 
402         if (message.getPriority() != MBThreadImpl.PRIORITY_NOT_GIVEN) {
403             thread.setPriority(message.getPriority());
404         }
405 
406         mbThreadPersistence.update(thread, false);
407 
408         return thread;
409     }
410 
411     protected void moveAttachmentsFromOldThread(
412             MBMessage message, String oldAttachmentsDir)
413         throws PortalException, SystemException {
414 
415         if (!message.getAttachments()) {
416             return;
417         }
418 
419         long companyId = message.getCompanyId();
420         String portletId = CompanyConstants.SYSTEM_STRING;
421         long groupId = GroupImpl.DEFAULT_PARENT_GROUP_ID;
422         long repositoryId = CompanyConstants.SYSTEM;
423         String newAttachmentsDir = message.getAttachmentsDir();
424 
425         try {
426             try {
427                 dlService.addDirectory(
428                     companyId, repositoryId, newAttachmentsDir);
429             }
430             catch (DuplicateDirectoryException dde) {
431             }
432 
433             String[] fileNames = dlService.getFileNames(
434                 companyId, repositoryId, oldAttachmentsDir);
435 
436             for (String fileName : fileNames) {
437                 String name = StringUtil.extractLast(
438                     fileName, StringPool.SLASH);
439                 byte[] fileBytes = dlService.getFile(
440                     companyId, repositoryId, fileName);
441 
442                 dlService.addFile(
443                     companyId, portletId, groupId, repositoryId,
444                     newAttachmentsDir + "/" + name, StringPool.BLANK,
445                     new String[0], fileBytes);
446 
447                 dlService.deleteFile(
448                     companyId, portletId, repositoryId, fileName);
449             }
450 
451             try {
452                 dlService.deleteDirectory(
453                     companyId, portletId, repositoryId, oldAttachmentsDir);
454             }
455             catch (NoSuchDirectoryException nsde) {
456             }
457         }
458         catch (RemoteException re) {
459             throw new SystemException(re);
460         }
461     }
462 
463     protected int moveChildrenMessages(
464             MBMessage parentMessage, MBCategory category, long oldThreadId)
465         throws SystemException, PortalException {
466 
467         int messagesMoved = 0;
468 
469         List<MBMessage> messages = mbMessagePersistence.findByT_P(
470             oldThreadId, parentMessage.getMessageId());
471 
472         for (MBMessage message : messages) {
473             String oldAttachmentsDir = message.getAttachmentsDir();
474 
475             message.setCategoryId(parentMessage.getCategoryId());
476             message.setThreadId(parentMessage.getThreadId());
477             message.setAttachmentsDir(null);
478 
479             mbMessagePersistence.update(message, false);
480 
481             moveAttachmentsFromOldThread(message, oldAttachmentsDir);
482 
483             try {
484                 if (!category.isDiscussion()) {
485                     Indexer.updateMessage(
486                         message.getCompanyId(), category.getGroupId(),
487                         message.getUserName(), category.getCategoryId(),
488                         message.getThreadId(), message.getMessageId(),
489                         message.getSubject(), message.getBody(),
490                         message.getTagsEntries());
491                 }
492             }
493             catch (SearchException se) {
494                 _log.error("Indexing " + message.getMessageId(), se);
495             }
496 
497             messagesMoved++;
498 
499             messagesMoved += moveChildrenMessages(
500                 message, category, oldThreadId);
501         }
502 
503         return messagesMoved;
504     }
505 
506     private static Log _log = LogFactory.getLog(MBThreadLocalServiceImpl.class);
507 
508 }