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