1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights 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.util.PortalUtil;
44  import com.liferay.portlet.messageboards.CategoryNameException;
45  import com.liferay.portlet.messageboards.model.MBCategory;
46  import com.liferay.portlet.messageboards.model.MBMessage;
47  import com.liferay.portlet.messageboards.model.MBThread;
48  import com.liferay.portlet.messageboards.model.impl.MBCategoryImpl;
49  import com.liferay.portlet.messageboards.service.base.MBCategoryLocalServiceBaseImpl;
50  import com.liferay.portlet.messageboards.util.Indexer;
51  
52  import java.util.ArrayList;
53  import java.util.Date;
54  import java.util.List;
55  
56  /**
57   * <a href="MBCategoryLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
58   *
59   * @author Brian Wing Shun Chan
60   */
61  public class MBCategoryLocalServiceImpl extends MBCategoryLocalServiceBaseImpl {
62  
63      public MBCategory addCategory(
64              long userId, long plid, long parentCategoryId, String name,
65              String description, boolean addCommunityPermissions,
66              boolean addGuestPermissions)
67          throws PortalException, SystemException {
68  
69          return addCategory(
70              null, userId, plid, parentCategoryId, name, description,
71              Boolean.valueOf(addCommunityPermissions),
72              Boolean.valueOf(addGuestPermissions), null, null);
73      }
74  
75      public MBCategory addCategory(
76              String uuid, long userId, long plid, long parentCategoryId,
77              String name, String description, boolean addCommunityPermissions,
78              boolean addGuestPermissions)
79          throws PortalException, SystemException {
80  
81          return addCategory(
82              uuid, userId, plid, parentCategoryId, name, description,
83              Boolean.valueOf(addCommunityPermissions),
84              Boolean.valueOf(addGuestPermissions), null, null);
85      }
86  
87      public MBCategory addCategory(
88              long userId, long plid, long parentCategoryId, String name,
89              String description, String[] communityPermissions,
90              String[] guestPermissions)
91          throws PortalException, SystemException {
92  
93          return addCategory(
94              null, userId, plid, parentCategoryId, name, description, null, null,
95              communityPermissions, guestPermissions);
96      }
97  
98      public MBCategory addCategory(
99              String uuid, long userId, long plid, long parentCategoryId,
100             String name, String description, Boolean addCommunityPermissions,
101             Boolean addGuestPermissions, String[] communityPermissions,
102             String[] guestPermissions)
103         throws PortalException, SystemException {
104 
105         // Category
106 
107         User user = userPersistence.findByPrimaryKey(userId);
108         long groupId = PortalUtil.getScopeGroupId(plid);
109         parentCategoryId = getParentCategoryId(groupId, parentCategoryId);
110         Date now = new Date();
111 
112         validate(name);
113 
114         long categoryId = counterLocalService.increment();
115 
116         MBCategory category = mbCategoryPersistence.create(categoryId);
117 
118         category.setUuid(uuid);
119         category.setGroupId(groupId);
120         category.setCompanyId(user.getCompanyId());
121         category.setUserId(user.getUserId());
122         category.setUserName(user.getFullName());
123         category.setCreateDate(now);
124         category.setModifiedDate(now);
125         category.setParentCategoryId(parentCategoryId);
126         category.setName(name);
127         category.setDescription(description);
128 
129         mbCategoryPersistence.update(category, false);
130 
131         // Resources
132 
133         if ((addCommunityPermissions != null) &&
134             (addGuestPermissions != null)) {
135 
136             addCategoryResources(
137                 category, addCommunityPermissions.booleanValue(),
138                 addGuestPermissions.booleanValue());
139         }
140         else {
141             addCategoryResources(
142                 category, communityPermissions, guestPermissions);
143         }
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         // Resources
241 
242         resourceLocalService.deleteResource(
243             category.getCompanyId(), MBCategory.class.getName(),
244             ResourceConstants.SCOPE_INDIVIDUAL, category.getCategoryId());
245 
246         // Category
247 
248         mbCategoryPersistence.remove(category);
249     }
250 
251     public List<MBCategory> getCategories(long groupId) throws SystemException {
252         return mbCategoryPersistence.findByGroupId(groupId);
253     }
254 
255     public List<MBCategory> getCategories(long groupId, long parentCategoryId)
256         throws SystemException {
257 
258         return mbCategoryPersistence.findByG_P(groupId, parentCategoryId);
259     }
260 
261     public List<MBCategory> getCategories(
262             long groupId, long parentCategoryId, int start, int end)
263         throws SystemException {
264 
265         return mbCategoryPersistence.findByG_P(
266             groupId, parentCategoryId, start, end);
267     }
268 
269     public int getCategoriesCount(long groupId) throws SystemException {
270         return mbCategoryPersistence.countByGroupId(groupId);
271     }
272 
273     public int getCategoriesCount(long groupId, long parentCategoryId)
274         throws SystemException {
275 
276         return mbCategoryPersistence.countByG_P(groupId, parentCategoryId);
277     }
278 
279     public MBCategory getCategory(long categoryId)
280         throws PortalException, SystemException {
281 
282         return mbCategoryPersistence.findByPrimaryKey(categoryId);
283     }
284 
285     public void getSubcategoryIds(
286             List<Long> categoryIds, long groupId, long categoryId)
287         throws SystemException {
288 
289         List<MBCategory> categories = mbCategoryPersistence.findByG_P(
290             groupId, categoryId);
291 
292         for (MBCategory category : categories) {
293             categoryIds.add(category.getCategoryId());
294 
295             getSubcategoryIds(
296                 categoryIds, category.getGroupId(), category.getCategoryId());
297         }
298     }
299 
300     public List<MBCategory> getSubscribedCategories(
301             long groupId, long userId, int start, int end)
302         throws SystemException {
303 
304         return mbCategoryFinder.findByS_G_U(groupId, userId, start, end);
305     }
306 
307     public int getSubscribedCategoriesCount(long groupId, long userId)
308         throws SystemException {
309 
310         return mbCategoryFinder.countByS_G_U(groupId, userId);
311     }
312 
313     public MBCategory getSystemCategory() throws SystemException {
314         long categoryId = CompanyConstants.SYSTEM;
315 
316         MBCategory category = mbCategoryPersistence.fetchByPrimaryKey(
317             categoryId);
318 
319         if (category == null) {
320             category = mbCategoryPersistence.create(categoryId);
321 
322             category.setCompanyId(CompanyConstants.SYSTEM);
323             category.setUserId(CompanyConstants.SYSTEM);
324 
325             mbCategoryPersistence.update(category, false);
326         }
327 
328         return category;
329     }
330 
331     public void reIndex(String[] ids) throws SystemException {
332         if (SearchEngineUtil.isIndexReadOnly()) {
333             return;
334         }
335 
336         long companyId = GetterUtil.getLong(ids[0]);
337 
338         try {
339             reIndexCategories(companyId);
340         }
341         catch (SystemException se) {
342             throw se;
343         }
344         catch (Exception e) {
345             throw new SystemException(e);
346         }
347     }
348 
349     public Hits search(
350             long companyId, long groupId, long[] categoryIds, long threadId,
351             String keywords, int start, int end)
352         throws SystemException {
353 
354         try {
355             BooleanQuery contextQuery = BooleanQueryFactoryUtil.create();
356 
357             contextQuery.addRequiredTerm(Field.PORTLET_ID, Indexer.PORTLET_ID);
358 
359             if (groupId > 0) {
360                 contextQuery.addRequiredTerm(Field.GROUP_ID, groupId);
361             }
362 
363             if ((categoryIds != null) && (categoryIds.length > 0)) {
364                 BooleanQuery categoryIdsQuery =
365                     BooleanQueryFactoryUtil.create();
366 
367                 for (long categoryId : categoryIds) {
368                     TermQuery termQuery = TermQueryFactoryUtil.create(
369                         "categoryId", categoryId);
370 
371                     categoryIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
372                 }
373 
374                 contextQuery.add(categoryIdsQuery, BooleanClauseOccur.MUST);
375             }
376 
377             if (threadId > 0) {
378                 contextQuery.addTerm("threadId", threadId);
379             }
380 
381             BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
382 
383             if (Validator.isNotNull(keywords)) {
384                 searchQuery.addTerm(Field.USER_NAME, keywords);
385                 searchQuery.addTerm(Field.TITLE, keywords);
386                 searchQuery.addTerm(Field.CONTENT, keywords);
387                 searchQuery.addTerm(Field.TAGS_ENTRIES, keywords, true);
388             }
389 
390             BooleanQuery fullQuery = BooleanQueryFactoryUtil.create();
391 
392             fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
393 
394             if (searchQuery.clauses().size() > 0) {
395                 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
396             }
397 
398             return SearchEngineUtil.search(companyId, fullQuery, start, end);
399         }
400         catch (Exception e) {
401             throw new SystemException(e);
402         }
403     }
404 
405     public MBCategory updateCategory(
406             long categoryId, long parentCategoryId, String name,
407             String description, boolean mergeWithParentCategory)
408         throws PortalException, SystemException {
409 
410         // Category
411 
412         MBCategory category = mbCategoryPersistence.findByPrimaryKey(
413             categoryId);
414 
415         parentCategoryId = getParentCategoryId(category, parentCategoryId);
416 
417         validate(name);
418 
419         category.setModifiedDate(new Date());
420         category.setParentCategoryId(parentCategoryId);
421         category.setName(name);
422         category.setDescription(description);
423 
424         mbCategoryPersistence.update(category, false);
425 
426         // Merge categories
427 
428         if (mergeWithParentCategory &&
429             (categoryId != parentCategoryId) &&
430             (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID)) {
431 
432             mergeCategories(category, parentCategoryId);
433         }
434 
435         return category;
436     }
437 
438     protected long getParentCategoryId(long groupId, long parentCategoryId)
439         throws SystemException {
440 
441         if (parentCategoryId != MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
442             MBCategory parentCategory = mbCategoryPersistence.fetchByPrimaryKey(
443                 parentCategoryId);
444 
445             if ((parentCategory == null) ||
446                 (groupId != parentCategory.getGroupId())) {
447 
448                 parentCategoryId = MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID;
449             }
450         }
451 
452         return parentCategoryId;
453     }
454 
455     protected long getParentCategoryId(
456             MBCategory category, long parentCategoryId)
457         throws SystemException {
458 
459         if (parentCategoryId == MBCategoryImpl.DEFAULT_PARENT_CATEGORY_ID) {
460             return parentCategoryId;
461         }
462 
463         if (category.getCategoryId() == parentCategoryId) {
464             return category.getParentCategoryId();
465         }
466         else {
467             MBCategory parentCategory = mbCategoryPersistence.fetchByPrimaryKey(
468                 parentCategoryId);
469 
470             if ((parentCategory == null) ||
471                 (category.getGroupId() != parentCategory.getGroupId())) {
472 
473                 return category.getParentCategoryId();
474             }
475 
476             List<Long> subcategoryIds = new ArrayList<Long>();
477 
478             getSubcategoryIds(
479                 subcategoryIds, category.getGroupId(),
480                 category.getCategoryId());
481 
482             if (subcategoryIds.contains(parentCategoryId)) {
483                 return category.getParentCategoryId();
484             }
485 
486             return parentCategoryId;
487         }
488     }
489 
490     protected void mergeCategories(MBCategory fromCategory, long toCategoryId)
491         throws PortalException, SystemException {
492 
493         List<MBCategory> categories = mbCategoryPersistence.findByG_P(
494             fromCategory.getGroupId(), fromCategory.getCategoryId());
495 
496         for (MBCategory category : categories) {
497             mergeCategories(category, toCategoryId);
498         }
499 
500         List<MBThread> threads = mbThreadPersistence.findByCategoryId(
501             fromCategory.getCategoryId());
502 
503         for (MBThread thread : threads) {
504 
505             // Thread
506 
507             thread.setCategoryId(toCategoryId);
508 
509             mbThreadPersistence.update(thread, false);
510 
511             List<MBMessage> messages = mbMessagePersistence.findByThreadId(
512                 thread.getThreadId());
513 
514             for (MBMessage message : messages) {
515 
516                 // Message
517 
518                 message.setCategoryId(toCategoryId);
519 
520                 mbMessagePersistence.update(message, false);
521 
522                 // Indexer
523 
524                 mbMessageLocalService.reIndex(message);
525             }
526         }
527 
528         deleteCategory(fromCategory);
529     }
530 
531     public void subscribeCategory(long userId, long categoryId)
532         throws PortalException, SystemException {
533 
534         subscriptionLocalService.addSubscription(
535             userId, MBCategory.class.getName(), categoryId);
536     }
537 
538     public void unsubscribeCategory(long userId, long categoryId)
539         throws PortalException, SystemException {
540 
541         subscriptionLocalService.deleteSubscription(
542             userId, MBCategory.class.getName(), categoryId);
543     }
544 
545     protected void reIndexCategories(long companyId) throws SystemException {
546         int categoryCount = mbCategoryPersistence.countByCompanyId(companyId);
547 
548         int categoryPages = categoryCount / Indexer.DEFAULT_INTERVAL;
549 
550         for (int i = 0; i <= categoryPages; i++) {
551             int categoryStart = (i * Indexer.DEFAULT_INTERVAL);
552             int categoryEnd = categoryStart + Indexer.DEFAULT_INTERVAL;
553 
554             reIndexCategories(companyId, categoryStart, categoryEnd);
555         }
556     }
557 
558     protected void reIndexCategories(
559             long companyId, int categoryStart, int categoryEnd)
560         throws SystemException {
561 
562         List<MBCategory> categories = mbCategoryPersistence.findByCompanyId(
563             companyId, categoryStart, categoryEnd);
564 
565         for (MBCategory category : categories) {
566             long categoryId = category.getCategoryId();
567 
568             int messageCount = mbMessagePersistence.countByCategoryId(
569                 categoryId);
570 
571             int messagePages = messageCount / Indexer.DEFAULT_INTERVAL;
572 
573             for (int i = 0; i <= messagePages; i++) {
574                 int messageStart = (i * Indexer.DEFAULT_INTERVAL);
575                 int messageEnd = messageStart + Indexer.DEFAULT_INTERVAL;
576 
577                 reIndexMessages(categoryId, messageStart, messageEnd);
578             }
579         }
580     }
581 
582     protected void reIndexMessages(
583             long categoryId, int messageStart, int messageEnd)
584         throws SystemException {
585 
586         List<MBMessage> messages = mbMessagePersistence.findByCategoryId(
587             categoryId, messageStart, messageEnd);
588 
589         for (MBMessage message : messages) {
590             mbMessageLocalService.reIndex(message);
591         }
592     }
593 
594     protected void validate(String name) throws PortalException {
595         if (Validator.isNull(name)) {
596             throw new CategoryNameException();
597         }
598     }
599 
600     private static Log _log =
601         LogFactoryUtil.getLog(MBCategoryLocalServiceImpl.class);
602 
603 }