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