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.portal.PortalException;
26  import com.liferay.portal.SystemException;
27  import com.liferay.portal.kernel.log.Log;
28  import com.liferay.portal.kernel.log.LogFactoryUtil;
29  import com.liferay.portal.kernel.search.BooleanClauseOccur;
30  import com.liferay.portal.kernel.search.BooleanQuery;
31  import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
32  import com.liferay.portal.kernel.search.Field;
33  import com.liferay.portal.kernel.search.Hits;
34  import com.liferay.portal.kernel.search.SearchEngineUtil;
35  import com.liferay.portal.kernel.search.SearchException;
36  import com.liferay.portal.kernel.search.TermQuery;
37  import com.liferay.portal.kernel.search.TermQueryFactoryUtil;
38  import com.liferay.portal.kernel.util.GetterUtil;
39  import com.liferay.portal.kernel.util.Validator;
40  import com.liferay.portal.model.CompanyConstants;
41  import com.liferay.portal.model.ResourceConstants;
42  import com.liferay.portal.model.User;
43  import com.liferay.portal.service.ServiceContext;
44  import com.liferay.portlet.messageboards.CategoryNameException;
45  import com.liferay.portlet.messageboards.NoSuchMailingListException;
46  import com.liferay.portlet.messageboards.model.MBCategory;
47  import com.liferay.portlet.messageboards.model.MBMailingList;
48  import com.liferay.portlet.messageboards.model.MBMessage;
49  import com.liferay.portlet.messageboards.model.MBThread;
50  import com.liferay.portlet.messageboards.model.impl.MBCategoryImpl;
51  import com.liferay.portlet.messageboards.service.base.MBCategoryLocalServiceBaseImpl;
52  import com.liferay.portlet.messageboards.util.Indexer;
53  
54  import java.util.ArrayList;
55  import java.util.Date;
56  import java.util.List;
57  
58  /**
59   * <a href="MBCategoryLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
60   *
61   * @author Brian Wing Shun Chan
62   *
63   */
64  public class MBCategoryLocalServiceImpl extends MBCategoryLocalServiceBaseImpl {
65  
66      public MBCategory addCategory(
67              long userId, long parentCategoryId, String name, String description,
68              String emailAddress, String inProtocol, String inServerName,
69              int inServerPort, boolean inUseSSL, String inUserName,
70              String inPassword, int inReadInterval, String outEmailAddress,
71              boolean outCustom, String outServerName, int outServerPort,
72              boolean outUseSSL, String outUserName, String outPassword,
73              boolean mailingListActive, ServiceContext serviceContext)
74          throws PortalException, SystemException {
75  
76          return addCategory(
77              null, userId, parentCategoryId, name, description, emailAddress,
78              inProtocol, inServerName, inServerPort, inUseSSL, inUserName,
79              inPassword, inReadInterval, outEmailAddress, outCustom,
80              outServerName, outServerPort, outUseSSL, outUserName, outPassword,
81              mailingListActive, serviceContext);
82      }
83  
84      public MBCategory addCategory(
85              String uuid, long userId, long parentCategoryId,
86              String name, String description, String emailAddress,
87              String inProtocol, String inServerName, int inServerPort,
88              boolean inUseSSL, String inUserName, String inPassword,
89              int inReadInterval, String outEmailAddress, boolean outCustom,
90              String outServerName, int outServerPort, boolean outUseSSL,
91              String outUserName, String outPassword, boolean mailingListActive,
92              ServiceContext serviceContext)
93          throws PortalException, SystemException {
94  
95          // Category
96  
97          User user = userPersistence.findByPrimaryKey(userId);
98          long groupId = serviceContext.getScopeGroupId();
99          parentCategoryId = getParentCategoryId(groupId, parentCategoryId);
100         Date now = new Date();
101 
102         validate(name);
103 
104         long categoryId = counterLocalService.increment();
105 
106         MBCategory category = mbCategoryPersistence.create(categoryId);
107 
108         category.setUuid(uuid);
109         category.setGroupId(groupId);
110         category.setCompanyId(user.getCompanyId());
111         category.setUserId(user.getUserId());
112         category.setUserName(user.getFullName());
113         category.setCreateDate(now);
114         category.setModifiedDate(now);
115         category.setParentCategoryId(parentCategoryId);
116         category.setName(name);
117         category.setDescription(description);
118 
119         mbCategoryPersistence.update(category, false);
120 
121         // Resources
122 
123         if (serviceContext.getAddCommunityPermissions() ||
124             serviceContext.getAddGuestPermissions()) {
125 
126             addCategoryResources(
127                 category, serviceContext.getAddCommunityPermissions(),
128                 serviceContext.getAddGuestPermissions());
129         }
130         else {
131             addCategoryResources(
132                 category, serviceContext.getCommunityPermissions(),
133                 serviceContext.getGuestPermissions());
134         }
135 
136         // Mailing list
137 
138         mbMailingListLocalService.addMailingList(
139             null, userId, category.getCategoryId(), emailAddress, inProtocol,
140             inServerName, inServerPort, inUseSSL, inUserName, inPassword,
141             inReadInterval, outEmailAddress, outCustom, outServerName,
142             outServerPort, outUseSSL, outUserName, outPassword,
143             mailingListActive);
144 
145         return category;
146     }
147 
148     public void addCategoryResources(
149             long categoryId, boolean addCommunityPermissions,
150             boolean addGuestPermissions)
151         throws PortalException, SystemException {
152 
153         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
154             categoryId);
155 
156         addCategoryResources(
157             category, addCommunityPermissions, addGuestPermissions);
158     }
159 
160     public void addCategoryResources(
161             MBCategory category, boolean addCommunityPermissions,
162             boolean addGuestPermissions)
163         throws PortalException, SystemException {
164 
165         resourceLocalService.addResources(
166             category.getCompanyId(), category.getGroupId(),
167             category.getUserId(), MBCategory.class.getName(),
168             category.getCategoryId(), false, addCommunityPermissions,
169             addGuestPermissions);
170     }
171 
172     public void addCategoryResources(
173             long categoryId, String[] communityPermissions,
174             String[] guestPermissions)
175         throws PortalException, SystemException {
176 
177         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
178             categoryId);
179 
180         addCategoryResources(category, communityPermissions, guestPermissions);
181     }
182 
183     public void addCategoryResources(
184             MBCategory category, String[] communityPermissions,
185             String[] guestPermissions)
186         throws PortalException, SystemException {
187 
188         resourceLocalService.addModelResources(
189             category.getCompanyId(), category.getGroupId(),
190             category.getUserId(), MBCategory.class.getName(),
191             category.getCategoryId(), communityPermissions, guestPermissions);
192     }
193 
194     public void deleteCategories(long groupId)
195         throws PortalException, SystemException {
196 
197         List<MBCategory> categories = mbCategoryPersistence.findByG_P(
198             groupId, MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID);
199 
200         for (MBCategory category : categories) {
201             deleteCategory(category);
202         }
203     }
204 
205     public void deleteCategory(long categoryId)
206         throws PortalException, SystemException {
207 
208         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
209             categoryId);
210 
211         deleteCategory(category);
212     }
213 
214     public void deleteCategory(MBCategory category)
215         throws PortalException, SystemException {
216 
217         // Categories
218 
219         List<MBCategory> categories = mbCategoryPersistence.findByG_P(
220             category.getGroupId(), category.getCategoryId());
221 
222         for (MBCategory curCategory : categories) {
223             deleteCategory(curCategory);
224         }
225 
226         // Indexer
227 
228         try {
229             Indexer.deleteMessages(
230                 category.getCompanyId(), category.getCategoryId());
231         }
232         catch (SearchException se) {
233             _log.error("Deleting index " + category.getCategoryId(), se);
234         }
235 
236         // Threads
237 
238         mbThreadLocalService.deleteThreads(category.getCategoryId());
239 
240         // Mailing list
241 
242         try {
243             mbMailingListLocalService.deleteCategoryMailingList(
244                 category.getCategoryId());
245         }
246         catch (NoSuchMailingListException nsmle) {
247         }
248 
249         // Resources
250 
251         resourceLocalService.deleteResource(
252             category.getCompanyId(), MBCategory.class.getName(),
253             ResourceConstants.SCOPE_INDIVIDUAL, category.getCategoryId());
254 
255         // Category
256 
257         mbCategoryPersistence.remove(category);
258     }
259 
260     public List<MBCategory> getCategories(long groupId) throws SystemException {
261         return mbCategoryPersistence.findByGroupId(groupId);
262     }
263 
264     public List<MBCategory> getCategories(long groupId, long parentCategoryId)
265         throws SystemException {
266 
267         return mbCategoryPersistence.findByG_P(groupId, parentCategoryId);
268     }
269 
270     public List<MBCategory> getCategories(
271             long groupId, long parentCategoryId, int start, int end)
272         throws SystemException {
273 
274         return mbCategoryPersistence.findByG_P(
275             groupId, parentCategoryId, start, end);
276     }
277 
278     public int getCategoriesCount(long groupId) throws SystemException {
279         return mbCategoryPersistence.countByGroupId(groupId);
280     }
281 
282     public int getCategoriesCount(long groupId, long parentCategoryId)
283         throws SystemException {
284 
285         return mbCategoryPersistence.countByG_P(groupId, parentCategoryId);
286     }
287 
288     public MBCategory getCategory(long categoryId)
289         throws PortalException, SystemException {
290 
291         return mbCategoryPersistence.findByPrimaryKey(categoryId);
292     }
293 
294     public void getSubcategoryIds(
295             List<Long> categoryIds, long groupId, long categoryId)
296         throws SystemException {
297 
298         List<MBCategory> categories = mbCategoryPersistence.findByG_P(
299             groupId, categoryId);
300 
301         for (MBCategory category : categories) {
302             categoryIds.add(category.getCategoryId());
303 
304             getSubcategoryIds(
305                 categoryIds, category.getGroupId(), category.getCategoryId());
306         }
307     }
308 
309     public List<MBCategory> getSubscribedCategories(
310             long groupId, long userId, int start, int end)
311         throws SystemException {
312 
313         return mbCategoryFinder.findByS_G_U(groupId, userId, start, end);
314     }
315 
316     public int getSubscribedCategoriesCount(long groupId, long userId)
317         throws SystemException {
318 
319         return mbCategoryFinder.countByS_G_U(groupId, userId);
320     }
321 
322     public MBCategory getSystemCategory() throws SystemException {
323         long categoryId = CompanyConstants.SYSTEM;
324 
325         MBCategory category = mbCategoryPersistence.fetchByPrimaryKey(
326             categoryId);
327 
328         if (category == null) {
329             category = mbCategoryPersistence.create(categoryId);
330 
331             category.setCompanyId(CompanyConstants.SYSTEM);
332             category.setUserId(CompanyConstants.SYSTEM);
333 
334             mbCategoryPersistence.update(category, false);
335         }
336 
337         return category;
338     }
339 
340     public void reIndex(String[] ids) throws SystemException {
341         if (SearchEngineUtil.isIndexReadOnly()) {
342             return;
343         }
344 
345         long companyId = GetterUtil.getLong(ids[0]);
346 
347         try {
348             reIndexCategories(companyId);
349         }
350         catch (SystemException se) {
351             throw se;
352         }
353         catch (Exception e) {
354             throw new SystemException(e);
355         }
356     }
357 
358     public Hits search(
359             long companyId, long groupId, long[] categoryIds, long threadId,
360             String keywords, int start, int end)
361         throws SystemException {
362 
363         try {
364             BooleanQuery contextQuery = BooleanQueryFactoryUtil.create();
365 
366             contextQuery.addRequiredTerm(Field.PORTLET_ID, Indexer.PORTLET_ID);
367 
368             if (groupId > 0) {
369                 contextQuery.addRequiredTerm(Field.GROUP_ID, groupId);
370             }
371 
372             if ((categoryIds != null) && (categoryIds.length > 0)) {
373                 BooleanQuery categoryIdsQuery =
374                     BooleanQueryFactoryUtil.create();
375 
376                 for (long categoryId : categoryIds) {
377                     TermQuery termQuery = TermQueryFactoryUtil.create(
378                         "categoryId", categoryId);
379 
380                     categoryIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
381                 }
382 
383                 contextQuery.add(categoryIdsQuery, BooleanClauseOccur.MUST);
384             }
385 
386             if (threadId > 0) {
387                 contextQuery.addTerm("threadId", threadId);
388             }
389 
390             BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
391 
392             if (Validator.isNotNull(keywords)) {
393                 searchQuery.addTerm(Field.USER_NAME, keywords);
394                 searchQuery.addTerm(Field.TITLE, keywords);
395                 searchQuery.addTerm(Field.CONTENT, keywords);
396                 searchQuery.addTerm(Field.TAGS_ENTRIES, keywords);
397             }
398 
399             BooleanQuery fullQuery = BooleanQueryFactoryUtil.create();
400 
401             fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
402 
403             if (searchQuery.clauses().size() > 0) {
404                 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
405             }
406 
407             return SearchEngineUtil.search(companyId, fullQuery, start, end);
408         }
409         catch (Exception e) {
410             throw new SystemException(e);
411         }
412     }
413 
414     public MBCategory updateCategory(
415             long categoryId, long parentCategoryId, String name,
416             String description, String emailAddress, String inProtocol,
417             String inServerName, int inServerPort, boolean inUseSSL,
418             String inUserName, String inPassword, int inReadInterval,
419             String outEmailAddress, boolean outCustom, String outServerName,
420             int outServerPort, boolean outUseSSL, String outUserName,
421             String outPassword, boolean mailingListActive,
422             boolean mergeWithParentCategory)
423         throws PortalException, SystemException {
424 
425         // Category
426 
427         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
428             categoryId);
429 
430         parentCategoryId = getParentCategoryId(category, parentCategoryId);
431 
432         validate(name);
433 
434         category.setModifiedDate(new Date());
435         category.setParentCategoryId(parentCategoryId);
436         category.setName(name);
437         category.setDescription(description);
438 
439         mbCategoryPersistence.update(category, false);
440 
441         // Merge categories
442 
443         if (mergeWithParentCategory &&
444             (categoryId != parentCategoryId) &&
445             (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID)) {
446 
447             mergeCategories(category, parentCategoryId);
448         }
449 
450         // Mailing list
451 
452         MBMailingList mailingList = mbMailingListPersistence.fetchByCategoryId(
453             category.getCategoryId());
454 
455         if (mailingList != null) {
456             mbMailingListLocalService.updateMailingList(
457                 mailingList.getMailingListId(), emailAddress, inProtocol,
458                 inServerName, inServerPort, inUseSSL, inUserName, inPassword,
459                 inReadInterval, outEmailAddress, outCustom, outServerName,
460                 outServerPort, outUseSSL, outUserName, outPassword,
461                 mailingListActive);
462         }
463         else {
464             mbMailingListLocalService.addMailingList(
465                 null, category.getUserId(), category.getCategoryId(),
466                 emailAddress, inProtocol, inServerName, inServerPort, inUseSSL,
467                 inUserName, inPassword, inReadInterval, outEmailAddress,
468                 outCustom, outServerName, outServerPort, outUseSSL, outUserName,
469                 outPassword, mailingListActive);
470         }
471 
472         return category;
473     }
474 
475     protected long getParentCategoryId(long groupId, long parentCategoryId)
476         throws SystemException {
477 
478         if (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
479             MBCategory parentCategory = mbCategoryPersistence.fetchByPrimaryKey(
480                 parentCategoryId);
481 
482             if ((parentCategory == null) ||
483                 (groupId != parentCategory.getGroupId())) {
484 
485                 parentCategoryId = MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID;
486             }
487         }
488 
489         return parentCategoryId;
490     }
491 
492     protected long getParentCategoryId(
493             MBCategory category, long parentCategoryId)
494         throws SystemException {
495 
496         if (parentCategoryId == MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
497             return parentCategoryId;
498         }
499 
500         if (category.getCategoryId() == parentCategoryId) {
501             return category.getParentCategoryId();
502         }
503         else {
504             MBCategory parentCategory = mbCategoryPersistence.fetchByPrimaryKey(
505                 parentCategoryId);
506 
507             if ((parentCategory == null) ||
508                 (category.getGroupId() != parentCategory.getGroupId())) {
509 
510                 return category.getParentCategoryId();
511             }
512 
513             List<Long> subcategoryIds = new ArrayList<Long>();
514 
515             getSubcategoryIds(
516                 subcategoryIds, category.getGroupId(),
517                 category.getCategoryId());
518 
519             if (subcategoryIds.contains(parentCategoryId)) {
520                 return category.getParentCategoryId();
521             }
522 
523             return parentCategoryId;
524         }
525     }
526 
527     protected void mergeCategories(MBCategory fromCategory, long toCategoryId)
528         throws PortalException, SystemException {
529 
530         List<MBCategory> categories = mbCategoryPersistence.findByG_P(
531             fromCategory.getGroupId(), fromCategory.getCategoryId());
532 
533         for (MBCategory category : categories) {
534             mergeCategories(category, toCategoryId);
535         }
536 
537         List<MBThread> threads = mbThreadPersistence.findByCategoryId(
538             fromCategory.getCategoryId());
539 
540         for (MBThread thread : threads) {
541 
542             // Thread
543 
544             thread.setCategoryId(toCategoryId);
545 
546             mbThreadPersistence.update(thread, false);
547 
548             List<MBMessage> messages = mbMessagePersistence.findByThreadId(
549                 thread.getThreadId());
550 
551             for (MBMessage message : messages) {
552 
553                 // Message
554 
555                 message.setCategoryId(toCategoryId);
556 
557                 mbMessagePersistence.update(message, false);
558 
559                 // Indexer
560 
561                 mbMessageLocalService.reIndex(message);
562             }
563         }
564 
565         deleteCategory(fromCategory);
566     }
567 
568     public void subscribeCategory(long userId, long categoryId)
569         throws PortalException, SystemException {
570 
571         subscriptionLocalService.addSubscription(
572             userId, MBCategory.class.getName(), categoryId);
573     }
574 
575     public void unsubscribeCategory(long userId, long categoryId)
576         throws PortalException, SystemException {
577 
578         subscriptionLocalService.deleteSubscription(
579             userId, MBCategory.class.getName(), categoryId);
580     }
581 
582     protected void reIndexCategories(long companyId) throws SystemException {
583         int categoryCount = mbCategoryPersistence.countByCompanyId(companyId);
584 
585         int categoryPages = categoryCount / Indexer.DEFAULT_INTERVAL;
586 
587         for (int i = 0; i <= categoryPages; i++) {
588             int categoryStart = (i * Indexer.DEFAULT_INTERVAL);
589             int categoryEnd = categoryStart + Indexer.DEFAULT_INTERVAL;
590 
591             reIndexCategories(companyId, categoryStart, categoryEnd);
592         }
593     }
594 
595     protected void reIndexCategories(
596             long companyId, int categoryStart, int categoryEnd)
597         throws SystemException {
598 
599         List<MBCategory> categories = mbCategoryPersistence.findByCompanyId(
600             companyId, categoryStart, categoryEnd);
601 
602         for (MBCategory category : categories) {
603             long categoryId = category.getCategoryId();
604 
605             int messageCount = mbMessagePersistence.countByCategoryId(
606                 categoryId);
607 
608             int messagePages = messageCount / Indexer.DEFAULT_INTERVAL;
609 
610             for (int i = 0; i <= messagePages; i++) {
611                 int messageStart = (i * Indexer.DEFAULT_INTERVAL);
612                 int messageEnd = messageStart + Indexer.DEFAULT_INTERVAL;
613 
614                 reIndexMessages(categoryId, messageStart, messageEnd);
615             }
616         }
617     }
618 
619     protected void reIndexMessages(
620             long categoryId, int messageStart, int messageEnd)
621         throws SystemException {
622 
623         List<MBMessage> messages = mbMessagePersistence.findByCategoryId(
624             categoryId, messageStart, messageEnd);
625 
626         for (MBMessage message : messages) {
627             mbMessageLocalService.reIndex(message);
628         }
629     }
630 
631     protected void validate(String name) throws PortalException {
632         if (Validator.isNull(name)) {
633             throw new CategoryNameException();
634         }
635     }
636 
637     private static Log _log =
638         LogFactoryUtil.getLog(MBCategoryLocalServiceImpl.class);
639 
640 }