1
14
15 package com.liferay.portlet.messageboards.util;
16
17 import com.liferay.portal.kernel.dao.orm.QueryUtil;
18 import com.liferay.portal.kernel.log.Log;
19 import com.liferay.portal.kernel.log.LogFactoryUtil;
20 import com.liferay.portal.kernel.search.BaseIndexer;
21 import com.liferay.portal.kernel.search.BooleanQuery;
22 import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
23 import com.liferay.portal.kernel.search.Document;
24 import com.liferay.portal.kernel.search.DocumentImpl;
25 import com.liferay.portal.kernel.search.Field;
26 import com.liferay.portal.kernel.search.Hits;
27 import com.liferay.portal.kernel.search.Indexer;
28 import com.liferay.portal.kernel.search.SearchContext;
29 import com.liferay.portal.kernel.search.SearchEngineUtil;
30 import com.liferay.portal.kernel.search.Summary;
31 import com.liferay.portal.kernel.util.GetterUtil;
32 import com.liferay.portal.kernel.util.HtmlUtil;
33 import com.liferay.portal.kernel.util.StringUtil;
34 import com.liferay.portal.kernel.util.Validator;
35 import com.liferay.portal.kernel.workflow.WorkflowConstants;
36 import com.liferay.portal.model.Group;
37 import com.liferay.portal.service.GroupLocalServiceUtil;
38 import com.liferay.portal.util.PortalUtil;
39 import com.liferay.portal.util.PortletKeys;
40 import com.liferay.portlet.asset.service.AssetTagLocalServiceUtil;
41 import com.liferay.portlet.expando.model.ExpandoBridge;
42 import com.liferay.portlet.expando.util.ExpandoBridgeIndexerUtil;
43 import com.liferay.portlet.messageboards.model.MBCategory;
44 import com.liferay.portlet.messageboards.model.MBCategoryConstants;
45 import com.liferay.portlet.messageboards.model.MBMessage;
46 import com.liferay.portlet.messageboards.model.MBThread;
47 import com.liferay.portlet.messageboards.service.MBCategoryLocalServiceUtil;
48 import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
49 import com.liferay.portlet.messageboards.service.MBThreadLocalServiceUtil;
50
51 import java.util.ArrayList;
52 import java.util.Collection;
53 import java.util.Date;
54 import java.util.List;
55
56 import javax.portlet.PortletURL;
57
58
66 public class MBIndexer extends BaseIndexer {
67
68 public static final String[] CLASS_NAMES = {MBMessage.class.getName()};
69
70 public static final String PORTLET_ID = PortletKeys.MESSAGE_BOARDS;
71
72 public String[] getClassNames() {
73 return CLASS_NAMES;
74 }
75
76 public Summary getSummary(
77 Document document, String snippet, PortletURL portletURL) {
78
79 String title = document.get(Field.TITLE);
80
81 String content = snippet;
82
83 if (Validator.isNull(snippet)) {
84 content = StringUtil.shorten(document.get(Field.CONTENT), 200);
85 }
86
87 String messageId = document.get(Field.ENTRY_CLASS_PK);
88
89 portletURL.setParameter(
90 "struts_action", "/message_boards/view_message");
91 portletURL.setParameter("messageId", messageId);
92
93 return new Summary(title, content, portletURL);
94 }
95
96 protected void doDelete(Object obj) throws Exception {
97 if (obj instanceof MBCategory) {
98 MBCategory category = (MBCategory)obj;
99
100 BooleanQuery booleanQuery = BooleanQueryFactoryUtil.create();
101
102 booleanQuery.addRequiredTerm(Field.PORTLET_ID, PORTLET_ID);
103
104 booleanQuery.addRequiredTerm(
105 "categoryId", category.getCategoryId());
106
107 Hits hits = SearchEngineUtil.search(
108 category.getCompanyId(), booleanQuery, QueryUtil.ALL_POS,
109 QueryUtil.ALL_POS);
110
111 for (int i = 0; i < hits.getLength(); i++) {
112 Document document = hits.doc(i);
113
114 SearchEngineUtil.deleteDocument(
115 category.getCompanyId(), document.get(Field.UID));
116 }
117 }
118 else if (obj instanceof MBMessage) {
119 MBMessage message = (MBMessage)obj;
120
121 Document document = new DocumentImpl();
122
123 document.addUID(PORTLET_ID, message.getMessageId());
124
125 SearchEngineUtil.deleteDocument(
126 message.getCompanyId(), document.get(Field.UID));
127 }
128 else if (obj instanceof MBThread) {
129 MBThread thread = (MBThread)obj;
130
131 MBMessage message = MBMessageLocalServiceUtil.getMessage(
132 thread.getRootMessageId());
133
134 BooleanQuery booleanQuery = BooleanQueryFactoryUtil.create();
135
136 booleanQuery.addRequiredTerm(Field.PORTLET_ID, PORTLET_ID);
137
138 booleanQuery.addRequiredTerm("threadId", thread.getThreadId());
139
140 Hits hits = SearchEngineUtil.search(
141 message.getCompanyId(), booleanQuery, QueryUtil.ALL_POS,
142 QueryUtil.ALL_POS);
143
144 for (int i = 0; i < hits.getLength(); i++) {
145 Document document = hits.doc(i);
146
147 SearchEngineUtil.deleteDocument(
148 message.getCompanyId(), document.get(Field.UID));
149 }
150 }
151 }
152
153 protected Document doGetDocument(Object obj) throws Exception {
154 MBMessage message = (MBMessage)obj;
155
156 long companyId = message.getCompanyId();
157 long groupId = getParentGroupId(message.getGroupId());
158 long scopeGroupId = message.getGroupId();
159 long userId = message.getUserId();
160 String userName = PortalUtil.getUserName(userId, message.getUserName());
161 long categoryId = message.getCategoryId();
162 long threadId = message.getThreadId();
163 long messageId = message.getMessageId();
164 String title = message.getSubject();
165 String content = processContent(messageId, message.getBody());
166 boolean anonymous = message.isAnonymous();
167 Date modifiedDate = message.getModifiedDate();
168
169 String[] assetTagNames = AssetTagLocalServiceUtil.getTagNames(
170 MBMessage.class.getName(), messageId);
171
172 ExpandoBridge expandoBridge = message.getExpandoBridge();
173
174 Document document = new DocumentImpl();
175
176 document.addUID(PORTLET_ID, messageId);
177
178 document.addModifiedDate(modifiedDate);
179
180 document.addKeyword(Field.COMPANY_ID, companyId);
181 document.addKeyword(Field.PORTLET_ID, PORTLET_ID);
182 document.addKeyword(Field.GROUP_ID, groupId);
183 document.addKeyword(Field.SCOPE_GROUP_ID, scopeGroupId);
184 document.addKeyword(Field.USER_ID, userId);
185
186 if (!anonymous) {
187 document.addText(Field.USER_NAME, userName);
188 }
189
190 document.addText(Field.TITLE, title);
191 document.addText(Field.CONTENT, content);
192 document.addKeyword(Field.ASSET_TAG_NAMES, assetTagNames);
193
194 document.addKeyword(Field.CATEGORY_ID, categoryId);
195 document.addKeyword("threadId", threadId);
196 document.addKeyword(Field.ENTRY_CLASS_NAME, MBMessage.class.getName());
197 document.addKeyword(Field.ENTRY_CLASS_PK, messageId);
198
199 try {
200 MBThread thread = MBThreadLocalServiceUtil.getMBThread(threadId);
201
202 document.addKeyword(
203 Field.ROOT_ENTRY_CLASS_PK, thread.getRootMessageId());
204 }
205 catch (Exception e) {
206 }
207
208 ExpandoBridgeIndexerUtil.addAttributes(document, expandoBridge);
209
210 return document;
211 }
212
213 protected void doReindex(Object obj) throws Exception {
214 MBMessage message = (MBMessage)obj;
215
216 if (message.isDiscussion() ||
217 (message.getStatus() != WorkflowConstants.STATUS_APPROVED)) {
218
219 return;
220 }
221
222 Document document = getDocument(message);
223
224 SearchEngineUtil.updateDocument(message.getCompanyId(), document);
225 }
226
227 protected void doReindex(String className, long classPK) throws Exception {
228 MBMessage message = MBMessageLocalServiceUtil.getMessage(classPK);
229
230 doReindex(message);
231
232 if (message.isRoot()) {
233 List<MBMessage> messages =
234 MBMessageLocalServiceUtil.getThreadMessages(
235 message.getThreadId(), WorkflowConstants.STATUS_APPROVED);
236
237 for (MBMessage curMessage : messages) {
238 reindex(curMessage);
239 }
240 }
241 else {
242 reindex(message);
243 }
244 }
245
246 protected void doReindex(String[] ids) throws Exception {
247 long companyId = GetterUtil.getLong(ids[0]);
248
249 reindexCategories(companyId);
250 reindexRoot(companyId);
251 }
252
253 protected String getPortletId(SearchContext searchContext) {
254 return PORTLET_ID;
255 }
256
257 protected void postProcessContextQuery(
258 BooleanQuery contextQuery, SearchContext searchContext)
259 throws Exception {
260
261 long threadId = GetterUtil.getLong(
262 (String)searchContext.getAttribute("threadId"));
263
264 if (threadId > 0) {
265 contextQuery.addTerm("threadId", threadId);
266 }
267 }
268
269 protected String processContent(long messageId, String content) {
270 try {
271 content = BBCodeUtil.getHTML(content);
272 }
273 catch (Exception e) {
274 _log.error(
275 "Could not parse message " + messageId + ": " + e.getMessage());
276 }
277
278 content = HtmlUtil.extractText(content);
279
280 return content;
281 }
282
283 protected void reindexCategories(long companyId) throws Exception {
284 int categoryCount =
285 MBCategoryLocalServiceUtil.getCompanyCategoriesCount(companyId);
286
287 int categoryPages = categoryCount / Indexer.DEFAULT_INTERVAL;
288
289 for (int i = 0; i <= categoryPages; i++) {
290 int categoryStart = (i * Indexer.DEFAULT_INTERVAL);
291 int categoryEnd = categoryStart + Indexer.DEFAULT_INTERVAL;
292
293 reindexCategories(companyId, categoryStart, categoryEnd);
294 }
295 }
296
297 protected void reindexCategories(
298 long companyId, int categoryStart, int categoryEnd)
299 throws Exception {
300
301 List<MBCategory> categories =
302 MBCategoryLocalServiceUtil.getCompanyCategories(
303 companyId, categoryStart, categoryEnd);
304
305 for (MBCategory category : categories) {
306 long groupId = category.getGroupId();
307 long categoryId = category.getCategoryId();
308
309 int messageCount =
310 MBMessageLocalServiceUtil.getCategoryMessagesCount(
311 groupId, categoryId, WorkflowConstants.STATUS_APPROVED);
312
313 int messagePages = messageCount / Indexer.DEFAULT_INTERVAL;
314
315 for (int i = 0; i <= messagePages; i++) {
316 int messageStart = (i * Indexer.DEFAULT_INTERVAL);
317 int messageEnd = messageStart + Indexer.DEFAULT_INTERVAL;
318
319 reindexMessages(
320 companyId, groupId, categoryId, messageStart, messageEnd);
321 }
322 }
323 }
324
325 protected void reindexMessages(
326 long companyId, long groupId, long categoryId, int messageStart,
327 int messageEnd)
328 throws Exception {
329
330 List<MBMessage> messages =
331 MBMessageLocalServiceUtil.getCategoryMessages(
332 groupId, categoryId, WorkflowConstants.STATUS_APPROVED,
333 messageStart, messageEnd);
334
335 if (messages.isEmpty()) {
336 return;
337 }
338
339 Collection<Document> documents = new ArrayList<Document>();
340
341 for (MBMessage message : messages) {
342 Document document = getDocument(message);
343
344 documents.add(document);
345 }
346
347 SearchEngineUtil.updateDocuments(companyId, documents);
348 }
349
350 protected void reindexRoot(long companyId) throws Exception {
351 int groupCount = GroupLocalServiceUtil.getCompanyGroupsCount(companyId);
352
353 int groupPages = groupCount / Indexer.DEFAULT_INTERVAL;
354
355 for (int i = 0; i <= groupPages; i++) {
356 int groupStart = (i * Indexer.DEFAULT_INTERVAL);
357 int groupEnd = groupStart + Indexer.DEFAULT_INTERVAL;
358
359 reindexRoot(companyId, groupStart, groupEnd);
360 }
361 }
362
363 protected void reindexRoot(long companyId, int groupStart, int groupEnd)
364 throws Exception {
365
366 List<Group> groups = GroupLocalServiceUtil.getCompanyGroups(
367 companyId, groupStart, groupEnd);
368
369 for (Group group : groups) {
370 long groupId = group.getGroupId();
371 long categoryId = MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID;
372
373 int entryCount = MBMessageLocalServiceUtil.getCategoryMessagesCount(
374 groupId, categoryId, WorkflowConstants.STATUS_APPROVED);
375
376 int entryPages = entryCount / Indexer.DEFAULT_INTERVAL;
377
378 for (int i = 0; i <= entryPages; i++) {
379 int entryStart = (i * Indexer.DEFAULT_INTERVAL);
380 int entryEnd = entryStart + Indexer.DEFAULT_INTERVAL;
381
382 reindexMessages(
383 companyId, groupId, categoryId, entryStart, entryEnd);
384 }
385 }
386 }
387
388 private static Log _log = LogFactoryUtil.getLog(MBIndexer.class);
389
390 }