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 void postProcessContextQuery(
128 BooleanQuery contextQuery, SearchContext searchContext)
129 throws Exception {
130
131 addStatus(contextQuery, searchContext);
132
133 boolean discussion = GetterUtil.getBoolean(
134 searchContext.getAttribute("discussion"), false);
135
136 contextQuery.addRequiredTerm("discussion", discussion);
137
138 if (searchContext.isIncludeDiscussions()) {
139 addRelatedClassNames(contextQuery, searchContext);
140 }
141
142 long threadId = GetterUtil.getLong(
143 (String)searchContext.getAttribute("threadId"));
144
145 if (threadId > 0) {
146 contextQuery.addRequiredTerm("threadId", threadId);
147 }
148
149 long[] categoryIds = searchContext.getCategoryIds();
150
151 if ((categoryIds != null) && (categoryIds.length > 0) &&
152 (categoryIds[0] !=
153 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID)) {
154
155 BooleanQuery categoriesQuery = BooleanQueryFactoryUtil.create(
156 searchContext);
157
158 for (long categoryId : categoryIds) {
159 try {
160 MBCategoryServiceUtil.getCategory(categoryId);
161 }
162 catch (Exception e) {
163 continue;
164 }
165
166 categoriesQuery.addTerm(Field.CATEGORY_ID, categoryId);
167 }
168
169 contextQuery.add(categoriesQuery, BooleanClauseOccur.MUST);
170 }
171 }
172
173 @Override
174 protected void doDelete(Object obj) throws Exception {
175 MBMessage message = (MBMessage)obj;
176
177 deleteDocument(message.getCompanyId(), message.getMessageId());
178 }
179
180 @Override
181 protected Document doGetDocument(Object obj) throws Exception {
182 MBMessage message = (MBMessage)obj;
183
184 Document document = getBaseModelDocument(PORTLET_ID, message);
185
186 document.addKeyword(Field.CATEGORY_ID, message.getCategoryId());
187 document.addText(Field.CONTENT, processContent(message));
188 document.addKeyword(
189 Field.ROOT_ENTRY_CLASS_PK, message.getRootMessageId());
190 document.addText(Field.TITLE, message.getSubject());
191
192 if (message.isAnonymous()) {
193 document.remove(Field.USER_NAME);
194 }
195
196 try {
197 MBDiscussionLocalServiceUtil.getThreadDiscussion(
198 message.getThreadId());
199
200 document.addKeyword("discussion", true);
201 }
202 catch (NoSuchDiscussionException nsde) {
203 document.addKeyword("discussion", false);
204 }
205
206 document.addKeyword("threadId", message.getThreadId());
207
208 if (message.isDiscussion()) {
209 Indexer indexer = IndexerRegistryUtil.getIndexer(
210 message.getClassName());
211
212 if (indexer != null) {
213 indexer.addRelatedEntryFields(document, obj);
214 }
215 }
216
217 return document;
218 }
219
220 @Override
221 protected Summary doGetSummary(
222 Document document, Locale locale, String snippet,
223 PortletURL portletURL) {
224
225 String messageId = document.get(Field.ENTRY_CLASS_PK);
226
227 portletURL.setParameter(
228 "struts_action", "/message_boards/view_message");
229 portletURL.setParameter("messageId", messageId);
230
231 Summary summary = createSummary(document, Field.TITLE, Field.CONTENT);
232
233 summary.setMaxContentLength(200);
234 summary.setPortletURL(portletURL);
235
236 return summary;
237 }
238
239 @Override
240 protected void doReindex(Object obj) throws Exception {
241 MBMessage message = (MBMessage)obj;
242
243 if (!message.isApproved() && !message.isInTrash()) {
244 return;
245 }
246
247 if (message.isDiscussion() && message.isRoot()) {
248 return;
249 }
250
251 Document document = getDocument(message);
252
253 SearchEngineUtil.updateDocument(
254 getSearchEngineId(), message.getCompanyId(), document);
255 }
256
257 @Override
258 protected void doReindex(String className, long classPK) throws Exception {
259 MBMessage message = MBMessageLocalServiceUtil.getMessage(classPK);
260
261 doReindex(message);
262
263 if (message.isRoot()) {
264 List<MBMessage> messages =
265 MBMessageLocalServiceUtil.getThreadMessages(
266 message.getThreadId(), WorkflowConstants.STATUS_APPROVED);
267
268 for (MBMessage curMessage : messages) {
269 reindex(curMessage);
270 }
271 }
272 else {
273 reindex(message);
274 }
275 }
276
277 @Override
278 protected void doReindex(String[] ids) throws Exception {
279 long companyId = GetterUtil.getLong(ids[0]);
280
281 reindexCategories(companyId);
282 reindexDiscussions(companyId);
283 reindexRoot(companyId);
284 }
285
286 @Override
287 protected String getPortletId(SearchContext searchContext) {
288 return PORTLET_ID;
289 }
290
291 protected String processContent(MBMessage message) {
292 String content = message.getBody();
293
294 try {
295 if (message.isFormatBBCode()) {
296 content = BBCodeTranslatorUtil.getHTML(content);
297 }
298 }
299 catch (Exception e) {
300 _log.error(
301 "Could not parse message " + message.getMessageId() + ": " +
302 e.getMessage());
303 }
304
305 content = HtmlUtil.extractText(content);
306
307 return content;
308 }
309
310 protected void reindexCategories(final long companyId)
311 throws PortalException, SystemException {
312
313 ActionableDynamicQuery actionableDynamicQuery =
314 new MBCategoryActionableDynamicQuery() {
315
316 @Override
317 protected void performAction(Object object)
318 throws PortalException, SystemException {
319
320 MBCategory category = (MBCategory)object;
321
322 reindexMessages(
323 companyId, category.getGroupId(), category.getCategoryId());
324 }
325
326 };
327
328 actionableDynamicQuery.setCompanyId(companyId);
329
330 actionableDynamicQuery.performActions();
331 }
332
333 protected void reindexDiscussions(final long companyId)
334 throws PortalException, SystemException {
335
336 ActionableDynamicQuery actionableDynamicQuery =
337 new GroupActionableDynamicQuery() {
338
339 @Override
340 protected void performAction(Object object)
341 throws PortalException, SystemException {
342
343 Group group = (Group)object;
344
345 reindexMessages(
346 companyId, group.getGroupId(),
347 MBCategoryConstants.DISCUSSION_CATEGORY_ID);
348 }
349
350 };
351
352 actionableDynamicQuery.setCompanyId(companyId);
353
354 actionableDynamicQuery.performActions();
355 }
356
357 protected void reindexMessages(
358 long companyId, long groupId, final long categoryId)
359 throws PortalException, SystemException {
360
361 ActionableDynamicQuery actionableDynamicQuery =
362 new MBMessageActionableDynamicQuery() {
363
364 @Override
365 protected void addCriteria(DynamicQuery dynamicQuery) {
366 Property categoryIdProperty = PropertyFactoryUtil.forName(
367 "categoryId");
368
369 dynamicQuery.add(categoryIdProperty.eq(categoryId));
370
371 Property statusProperty = PropertyFactoryUtil.forName("status");
372
373 Integer[] statuses = {
374 WorkflowConstants.STATUS_APPROVED,
375 WorkflowConstants.STATUS_IN_TRASH
376 };
377
378 dynamicQuery.add(statusProperty.in(statuses));
379 }
380
381 @Override
382 protected void performAction(Object object) throws PortalException {
383 MBMessage message = (MBMessage)object;
384
385 if (message.isDiscussion() && message.isRoot()) {
386 return;
387 }
388
389 Document document = getDocument(message);
390
391 addDocument(document);
392 }
393
394 };
395
396 actionableDynamicQuery.setCompanyId(companyId);
397 actionableDynamicQuery.setGroupId(groupId);
398 actionableDynamicQuery.setSearchEngineId(getSearchEngineId());
399
400 actionableDynamicQuery.performActions();
401 }
402
403 protected void reindexRoot(final long companyId)
404 throws PortalException, SystemException {
405
406 ActionableDynamicQuery actionableDynamicQuery =
407 new GroupActionableDynamicQuery() {
408
409 @Override
410 protected void performAction(Object object)
411 throws PortalException, SystemException {
412
413 Group group = (Group)object;
414
415 reindexMessages(
416 companyId, group.getGroupId(),
417 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID);
418 }
419
420 };
421
422 actionableDynamicQuery.setCompanyId(companyId);
423
424 actionableDynamicQuery.performActions();
425 }
426
427 private static Log _log = LogFactoryUtil.getLog(MBMessageIndexer.class);
428
429 }