001
014
015 package com.liferay.portlet.messageboards.util;
016
017 import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
018 import com.liferay.portal.kernel.dao.orm.DynamicQuery;
019 import com.liferay.portal.kernel.dao.orm.Property;
020 import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
021 import com.liferay.portal.kernel.exception.PortalException;
022 import com.liferay.portal.kernel.exception.SystemException;
023 import com.liferay.portal.kernel.log.Log;
024 import com.liferay.portal.kernel.log.LogFactoryUtil;
025 import com.liferay.portal.kernel.parsers.bbcode.BBCodeTranslatorUtil;
026 import com.liferay.portal.kernel.search.BaseIndexer;
027 import com.liferay.portal.kernel.search.BooleanClauseOccur;
028 import com.liferay.portal.kernel.search.BooleanQuery;
029 import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
030 import com.liferay.portal.kernel.search.Document;
031 import com.liferay.portal.kernel.search.Field;
032 import com.liferay.portal.kernel.search.Indexer;
033 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
034 import com.liferay.portal.kernel.search.SearchContext;
035 import com.liferay.portal.kernel.search.SearchEngineUtil;
036 import com.liferay.portal.kernel.search.Summary;
037 import com.liferay.portal.kernel.util.GetterUtil;
038 import com.liferay.portal.kernel.util.HtmlUtil;
039 import com.liferay.portal.kernel.workflow.WorkflowConstants;
040 import com.liferay.portal.model.Group;
041 import com.liferay.portal.security.permission.ActionKeys;
042 import com.liferay.portal.security.permission.PermissionChecker;
043 import com.liferay.portal.service.persistence.GroupActionableDynamicQuery;
044 import com.liferay.portal.util.PortalUtil;
045 import com.liferay.portal.util.PortletKeys;
046 import com.liferay.portlet.documentlibrary.model.DLFileEntry;
047 import com.liferay.portlet.messageboards.NoSuchDiscussionException;
048 import com.liferay.portlet.messageboards.model.MBCategory;
049 import com.liferay.portlet.messageboards.model.MBCategoryConstants;
050 import com.liferay.portlet.messageboards.model.MBMessage;
051 import com.liferay.portlet.messageboards.service.MBCategoryServiceUtil;
052 import com.liferay.portlet.messageboards.service.MBDiscussionLocalServiceUtil;
053 import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
054 import com.liferay.portlet.messageboards.service.permission.MBMessagePermission;
055 import com.liferay.portlet.messageboards.service.persistence.MBCategoryActionableDynamicQuery;
056 import com.liferay.portlet.messageboards.service.persistence.MBMessageActionableDynamicQuery;
057
058 import javax.portlet.PortletURL;
059 import java.util.List;
060 import java.util.Locale;
061
062
068 public class MBMessageIndexer extends BaseIndexer {
069
070 public static final String[] CLASS_NAMES = {MBMessage.class.getName()};
071
072 public static final String PORTLET_ID = PortletKeys.MESSAGE_BOARDS;
073
074 public MBMessageIndexer() {
075 setFilterSearch(true);
076 setPermissionAware(true);
077 }
078
079 @Override
080 public void addRelatedEntryFields(Document document, Object obj)
081 throws Exception {
082
083 DLFileEntry dlFileEntry = (DLFileEntry)obj;
084
085 MBMessage message = null;
086
087 try {
088 message = MBMessageAttachmentsUtil.getMessage(
089 dlFileEntry.getFileEntryId());
090 }
091 catch (Exception e) {
092 return;
093 }
094
095 document.addKeyword(Field.CATEGORY_ID, message.getCategoryId());
096 document.addKeyword(
097 Field.CLASS_NAME_ID,
098 PortalUtil.getClassNameId(MBMessage.class.getName()));
099 document.addKeyword(Field.CLASS_PK, message.getMessageId());
100 document.addKeyword(Field.RELATED_ENTRY, true);
101
102 document.addKeyword("discussion", false);
103 document.addKeyword("threadId", message.getThreadId());
104 }
105
106 @Override
107 public String[] getClassNames() {
108 return CLASS_NAMES;
109 }
110
111 @Override
112 public String getPortletId() {
113 return PORTLET_ID;
114 }
115
116 @Override
117 public boolean hasPermission(
118 PermissionChecker permissionChecker, String entryClassName,
119 long entryClassPK, String actionId)
120 throws Exception {
121
122 return MBMessagePermission.contains(
123 permissionChecker, entryClassPK, ActionKeys.VIEW);
124 }
125
126 @Override
127 public boolean isVisible(long classPK, int status) throws Exception {
128 MBMessage message = MBMessageLocalServiceUtil.getMessage(classPK);
129
130 return isVisible(message.getStatus(), status);
131 }
132
133 @Override
134 public boolean isVisibleRelatedEntry(long classPK, int status)
135 throws Exception {
136
137 MBMessage message = MBMessageLocalServiceUtil.getMessage(classPK);
138
139 if (message.isDiscussion()) {
140 Indexer indexer = IndexerRegistryUtil.getIndexer(
141 message.getClassName());
142
143 return indexer.isVisible(message.getClassPK(), status);
144 }
145
146 return true;
147 }
148
149 @Override
150 public void postProcessContextQuery(
151 BooleanQuery contextQuery, SearchContext searchContext)
152 throws Exception {
153
154 addStatus(contextQuery, searchContext);
155
156 boolean discussion = GetterUtil.getBoolean(
157 searchContext.getAttribute("discussion"), false);
158
159 contextQuery.addRequiredTerm("discussion", discussion);
160
161 if (searchContext.isIncludeDiscussions()) {
162 addRelatedClassNames(contextQuery, searchContext);
163 }
164
165 long threadId = GetterUtil.getLong(
166 (String)searchContext.getAttribute("threadId"));
167
168 if (threadId > 0) {
169 contextQuery.addRequiredTerm("threadId", threadId);
170 }
171
172 long[] categoryIds = searchContext.getCategoryIds();
173
174 if ((categoryIds != null) && (categoryIds.length > 0) &&
175 (categoryIds[0] !=
176 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID)) {
177
178 BooleanQuery categoriesQuery = BooleanQueryFactoryUtil.create(
179 searchContext);
180
181 for (long categoryId : categoryIds) {
182 try {
183 MBCategoryServiceUtil.getCategory(categoryId);
184 }
185 catch (Exception e) {
186 continue;
187 }
188
189 categoriesQuery.addTerm(Field.CATEGORY_ID, categoryId);
190 }
191
192 contextQuery.add(categoriesQuery, BooleanClauseOccur.MUST);
193 }
194 }
195
196 @Override
197 protected void doDelete(Object obj) throws Exception {
198 MBMessage message = (MBMessage)obj;
199
200 deleteDocument(message.getCompanyId(), message.getMessageId());
201 }
202
203 @Override
204 protected Document doGetDocument(Object obj) throws Exception {
205 MBMessage message = (MBMessage)obj;
206
207 Document document = getBaseModelDocument(PORTLET_ID, message);
208
209 document.addKeyword(Field.CATEGORY_ID, message.getCategoryId());
210 document.addText(Field.CONTENT, processContent(message));
211 document.addKeyword(
212 Field.ROOT_ENTRY_CLASS_PK, message.getRootMessageId());
213 document.addText(Field.TITLE, message.getSubject());
214
215 if (message.isAnonymous()) {
216 document.remove(Field.USER_NAME);
217 }
218
219 try {
220 MBDiscussionLocalServiceUtil.getThreadDiscussion(
221 message.getThreadId());
222
223 document.addKeyword("discussion", true);
224 }
225 catch (NoSuchDiscussionException nsde) {
226 document.addKeyword("discussion", false);
227 }
228
229 document.addKeyword("threadId", message.getThreadId());
230
231 if (message.isDiscussion()) {
232 Indexer indexer = IndexerRegistryUtil.getIndexer(
233 message.getClassName());
234
235 if (indexer != null) {
236 indexer.addRelatedEntryFields(document, obj);
237 }
238 }
239
240 return document;
241 }
242
243 @Override
244 protected Summary doGetSummary(
245 Document document, Locale locale, String snippet,
246 PortletURL portletURL) {
247
248 String messageId = document.get(Field.ENTRY_CLASS_PK);
249
250 portletURL.setParameter(
251 "struts_action", "/message_boards/view_message");
252 portletURL.setParameter("messageId", messageId);
253
254 Summary summary = createSummary(document, Field.TITLE, Field.CONTENT);
255
256 summary.setMaxContentLength(200);
257 summary.setPortletURL(portletURL);
258
259 return summary;
260 }
261
262 @Override
263 protected void doReindex(Object obj) throws Exception {
264 MBMessage message = (MBMessage)obj;
265
266 if (!message.isApproved() && !message.isInTrash()) {
267 return;
268 }
269
270 if (message.isDiscussion() && message.isRoot()) {
271 return;
272 }
273
274 Document document = getDocument(message);
275
276 SearchEngineUtil.updateDocument(
277 getSearchEngineId(), message.getCompanyId(), document);
278 }
279
280 @Override
281 protected void doReindex(String className, long classPK) throws Exception {
282 MBMessage message = MBMessageLocalServiceUtil.getMessage(classPK);
283
284 doReindex(message);
285
286 if (message.isRoot()) {
287 List<MBMessage> messages =
288 MBMessageLocalServiceUtil.getThreadMessages(
289 message.getThreadId(), WorkflowConstants.STATUS_APPROVED);
290
291 for (MBMessage curMessage : messages) {
292 reindex(curMessage);
293 }
294 }
295 else {
296 reindex(message);
297 }
298 }
299
300 @Override
301 protected void doReindex(String[] ids) throws Exception {
302 long companyId = GetterUtil.getLong(ids[0]);
303
304 reindexCategories(companyId);
305 reindexDiscussions(companyId);
306 reindexRoot(companyId);
307 }
308
309 @Override
310 protected String getPortletId(SearchContext searchContext) {
311 return PORTLET_ID;
312 }
313
314 protected String processContent(MBMessage message) {
315 String content = message.getBody();
316
317 try {
318 if (message.isFormatBBCode()) {
319 content = BBCodeTranslatorUtil.getHTML(content);
320 }
321 }
322 catch (Exception e) {
323 _log.error(
324 "Could not parse message " + message.getMessageId() + ": " +
325 e.getMessage());
326 }
327
328 content = HtmlUtil.extractText(content);
329
330 return content;
331 }
332
333 protected void reindexCategories(final long companyId)
334 throws PortalException, SystemException {
335
336 ActionableDynamicQuery actionableDynamicQuery =
337 new MBCategoryActionableDynamicQuery() {
338
339 @Override
340 protected void performAction(Object object)
341 throws PortalException, SystemException {
342
343 MBCategory category = (MBCategory)object;
344
345 reindexMessages(
346 companyId, category.getGroupId(), category.getCategoryId());
347 }
348
349 };
350
351 actionableDynamicQuery.setCompanyId(companyId);
352
353 actionableDynamicQuery.performActions();
354 }
355
356 protected void reindexDiscussions(final long companyId)
357 throws PortalException, SystemException {
358
359 ActionableDynamicQuery actionableDynamicQuery =
360 new GroupActionableDynamicQuery() {
361
362 @Override
363 protected void performAction(Object object)
364 throws PortalException, SystemException {
365
366 Group group = (Group)object;
367
368 reindexMessages(
369 companyId, group.getGroupId(),
370 MBCategoryConstants.DISCUSSION_CATEGORY_ID);
371 }
372
373 };
374
375 actionableDynamicQuery.setCompanyId(companyId);
376
377 actionableDynamicQuery.performActions();
378 }
379
380 protected void reindexMessages(
381 long companyId, long groupId, final long categoryId)
382 throws PortalException, SystemException {
383
384 ActionableDynamicQuery actionableDynamicQuery =
385 new MBMessageActionableDynamicQuery() {
386
387 @Override
388 protected void addCriteria(DynamicQuery dynamicQuery) {
389 Property categoryIdProperty = PropertyFactoryUtil.forName(
390 "categoryId");
391
392 dynamicQuery.add(categoryIdProperty.eq(categoryId));
393
394 Property statusProperty = PropertyFactoryUtil.forName("status");
395
396 Integer[] statuses = {
397 WorkflowConstants.STATUS_APPROVED,
398 WorkflowConstants.STATUS_IN_TRASH
399 };
400
401 dynamicQuery.add(statusProperty.in(statuses));
402 }
403
404 @Override
405 protected void performAction(Object object) throws PortalException {
406 MBMessage message = (MBMessage)object;
407
408 if (message.isDiscussion() && message.isRoot()) {
409 return;
410 }
411
412 Document document = getDocument(message);
413
414 addDocument(document);
415 }
416
417 };
418
419 actionableDynamicQuery.setCompanyId(companyId);
420 actionableDynamicQuery.setGroupId(groupId);
421 actionableDynamicQuery.setSearchEngineId(getSearchEngineId());
422
423 actionableDynamicQuery.performActions();
424 }
425
426 protected void reindexRoot(final long companyId)
427 throws PortalException, SystemException {
428
429 ActionableDynamicQuery actionableDynamicQuery =
430 new GroupActionableDynamicQuery() {
431
432 @Override
433 protected void performAction(Object object)
434 throws PortalException, SystemException {
435
436 Group group = (Group)object;
437
438 reindexMessages(
439 companyId, group.getGroupId(),
440 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID);
441 }
442
443 };
444
445 actionableDynamicQuery.setCompanyId(companyId);
446
447 actionableDynamicQuery.performActions();
448 }
449
450 private static Log _log = LogFactoryUtil.getLog(MBMessageIndexer.class);
451
452 }