1
14
15 package com.liferay.portal.search;
16
17 import com.liferay.portal.NoSuchModelException;
18 import com.liferay.portal.kernel.log.Log;
19 import com.liferay.portal.kernel.log.LogFactoryUtil;
20 import com.liferay.portal.kernel.search.BooleanClause;
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.Document;
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.SearchException;
31 import com.liferay.portal.kernel.search.TermQuery;
32 import com.liferay.portal.kernel.search.TermQueryFactoryUtil;
33 import com.liferay.portal.kernel.util.Validator;
34 import com.liferay.portal.model.Group;
35 import com.liferay.portal.service.GroupLocalServiceUtil;
36
37
42 public abstract class BaseIndexer implements Indexer {
43
44 public void delete(Object obj) throws SearchException {
45 try {
46 doDelete(obj);
47 }
48 catch (SearchException se) {
49 throw se;
50 }
51 catch (Exception e) {
52 throw new SearchException(e);
53 }
54 }
55
56 public Document getDocument(Object obj) throws SearchException {
57 try {
58 return doGetDocument(obj);
59 }
60 catch (SearchException se) {
61 throw se;
62 }
63 catch (Exception e) {
64 throw new SearchException(e);
65 }
66 }
67
68 public void reindex(Object obj) throws SearchException {
69 try {
70 if (SearchEngineUtil.isIndexReadOnly()) {
71 return;
72 }
73
74 doReindex(obj);
75 }
76 catch (SearchException se) {
77 throw se;
78 }
79 catch (Exception e) {
80 throw new SearchException(e);
81 }
82 }
83
84 public void reindex(String className, long classPK) throws SearchException {
85 try {
86 if (SearchEngineUtil.isIndexReadOnly()) {
87 return;
88 }
89
90 doReindex(className, classPK);
91 }
92 catch (NoSuchModelException nsme) {
93 if (_log.isWarnEnabled()) {
94 _log.warn("Unable to index " + className + " " + classPK);
95 }
96 }
97 catch (SearchException se) {
98 throw se;
99 }
100 catch (Exception e) {
101 throw new SearchException(e);
102 }
103 }
104
105 public void reindex(String[] ids) throws SearchException {
106 try {
107 if (SearchEngineUtil.isIndexReadOnly()) {
108 return;
109 }
110
111 doReindex(ids);
112 }
113 catch (SearchException se) {
114 throw se;
115 }
116 catch (Exception e) {
117 throw new SearchException(e);
118 }
119 }
120
121 public Hits search(SearchContext searchContext) throws SearchException {
122 try {
123 String className = getClassName(searchContext);
124
125 BooleanQuery contextQuery = BooleanQueryFactoryUtil.create();
126
127 contextQuery.addRequiredTerm(
128 Field.PORTLET_ID, getPortletId(searchContext));
129
130 addSearchGroupId(contextQuery, searchContext);
131 addSearchOwnerUserId(contextQuery, searchContext);
132 addSearchCategoryIds(contextQuery, searchContext);
133 addSearchNodeIds(contextQuery, searchContext);
134 addSearchFolderIds(contextQuery, searchContext);
135
136 BooleanQuery fullQuery = createFullQuery(
137 contextQuery, searchContext);
138
139 return SearchEngineUtil.search(
140 searchContext.getCompanyId(), searchContext.getGroupId(),
141 searchContext.getUserId(), className, fullQuery,
142 searchContext.getSorts(), searchContext.getStart(),
143 searchContext.getEnd());
144 }
145 catch (SearchException se) {
146 throw se;
147 }
148 catch (Exception e) {
149 throw new SearchException(e);
150 }
151 }
152
153 protected void addSearchCategoryIds(
154 BooleanQuery contextQuery, SearchContext searchContext)
155 throws Exception {
156
157 long[] categoryIds = searchContext.getCategoryIds();
158
159 if ((categoryIds == null) || (categoryIds.length == 0)) {
160 return;
161 }
162
163 BooleanQuery categoryIdsQuery = BooleanQueryFactoryUtil.create();
164
165 for (long categoryId : categoryIds) {
166 if (searchContext.getUserId() > 0) {
167 try {
168 checkSearchCategoryId(categoryId, searchContext);
169 }
170 catch (Exception e) {
171 continue;
172 }
173 }
174
175 TermQuery termQuery = TermQueryFactoryUtil.create(
176 Field.CATEGORY_ID, categoryId);
177
178 categoryIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
179 }
180
181 if (!categoryIdsQuery.clauses().isEmpty()) {
182 contextQuery.add(categoryIdsQuery, BooleanClauseOccur.MUST);
183 }
184 }
185
186 protected void addSearchFolderIds(
187 BooleanQuery contextQuery, SearchContext searchContext)
188 throws Exception {
189
190 long[] folderIds = searchContext.getFolderIds();
191
192 if ((folderIds == null) || (folderIds.length == 0)) {
193 return;
194 }
195
196 BooleanQuery folderIdsQuery = BooleanQueryFactoryUtil.create();
197
198 for (long folderId : folderIds) {
199 if (searchContext.getUserId() > 0) {
200 try {
201 checkSearchFolderId(folderId, searchContext);
202 }
203 catch (Exception e) {
204 continue;
205 }
206 }
207
208 TermQuery termQuery = TermQueryFactoryUtil.create(
209 Field.FOLDER_ID, folderId);
210
211 folderIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
212 }
213
214 if (!folderIdsQuery.clauses().isEmpty()) {
215 contextQuery.add(folderIdsQuery, BooleanClauseOccur.MUST);
216 }
217 }
218
219 protected void addSearchGroupId(
220 BooleanQuery contextQuery, SearchContext searchContext)
221 throws Exception {
222
223 long groupId = searchContext.getGroupId();
224
225 if (groupId <= 0) {
226 return;
227 }
228
229 Group group = GroupLocalServiceUtil.getGroup(groupId);
230
231 long parentGroupId = groupId;
232
233 if (group.isLayout() || searchContext.isScopeStrict()) {
234 contextQuery.addRequiredTerm(Field.SCOPE_GROUP_ID, groupId);
235 }
236
237 if (group.isLayout()) {
238 parentGroupId = group.getParentGroupId();
239 }
240
241 contextQuery.addRequiredTerm(Field.GROUP_ID, parentGroupId);
242
243 searchContext.setGroupId(parentGroupId);
244 }
245
246 protected void addSearchKeywords(
247 BooleanQuery searchQuery, SearchContext searchContext)
248 throws Exception {
249
250 String keywords = searchContext.getKeywords();
251
252 if (Validator.isNull(keywords)) {
253 return;
254 }
255
256 searchQuery.addTerm(Field.USER_NAME, keywords);
257 searchQuery.addTerm(Field.TITLE, keywords);
258 searchQuery.addTerm(Field.CONTENT, keywords);
259 searchQuery.addTerm(Field.DESCRIPTION, keywords);
260 searchQuery.addTerm(Field.PROPERTIES, keywords);
261 searchQuery.addTerm(Field.ASSET_TAG_NAMES, keywords, true);
262 searchQuery.addTerm(Field.URL, keywords);
263 searchQuery.addTerm(Field.COMMENTS, keywords);
264 }
265
266 protected void addSearchNodeIds(
267 BooleanQuery contextQuery, SearchContext searchContext)
268 throws Exception {
269
270 long[] nodeIds = searchContext.getNodeIds();
271
272 if ((nodeIds == null) || (nodeIds.length == 0)) {
273 return;
274 }
275
276 BooleanQuery nodeIdsQuery = BooleanQueryFactoryUtil.create();
277
278 for (long nodeId : nodeIds) {
279 if (searchContext.getUserId() > 0) {
280 try {
281 checkSearchNodeId(nodeId, searchContext);
282 }
283 catch (Exception e) {
284 continue;
285 }
286 }
287
288 TermQuery termQuery = TermQueryFactoryUtil.create(
289 Field.NODE_ID, nodeId);
290
291 nodeIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
292 }
293
294 if (!nodeIdsQuery.clauses().isEmpty()) {
295 contextQuery.add(nodeIdsQuery, BooleanClauseOccur.MUST);
296 }
297 }
298
299 protected void addSearchOwnerUserId(
300 BooleanQuery contextQuery, SearchContext searchContext) {
301
302 long ownerUserId = searchContext.getOwnerUserId();
303
304 if (ownerUserId > 0) {
305 contextQuery.addRequiredTerm(Field.USER_ID, ownerUserId);
306 }
307 }
308
309 protected void checkSearchCategoryId(
310 long categoryId, SearchContext searchContext)
311 throws Exception {
312 }
313
314 protected void checkSearchFolderId(
315 long folderId, SearchContext searchContext)
316 throws Exception {
317 }
318
319 protected void checkSearchNodeId(
320 long nodeId, SearchContext searchContext)
321 throws Exception {
322 }
323
324 protected BooleanQuery createFullQuery(
325 BooleanQuery contextQuery, SearchContext searchContext)
326 throws Exception {
327
328 postProcessContextQuery(contextQuery, searchContext);
329
330 BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
331
332 addSearchKeywords(searchQuery, searchContext);
333 postProcessSearchQuery(searchQuery, searchContext);
334
335 BooleanQuery fullQuery = BooleanQueryFactoryUtil.create();
336
337 fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
338
339 if (!searchQuery.clauses().isEmpty()) {
340 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
341 }
342
343 BooleanClause[] booleanClauses = searchContext.getBooleanClauses();
344
345 if (booleanClauses != null) {
346 for (BooleanClause booleanClause : booleanClauses) {
347 fullQuery.add(
348 booleanClause.getQuery(),
349 booleanClause.getBooleanClauseOccur());
350 }
351 }
352
353 postProcessFullQuery(fullQuery, searchContext);
354
355 return fullQuery;
356 }
357
358 protected abstract void doDelete(Object obj) throws Exception;
359
360 protected abstract Document doGetDocument(Object obj) throws Exception;
361
362 protected abstract void doReindex(Object obj) throws Exception;
363
364 protected abstract void doReindex(String className, long classPK)
365 throws Exception;
366
367 protected abstract void doReindex(String[] ids) throws Exception;
368
369 protected String getClassName(SearchContext searchContext) {
370 String[] classNames = getClassNames();
371
372 if (classNames.length != 1) {
373 throw new UnsupportedOperationException(
374 "Search method needs to be manually implemented for " +
375 "indexers with more than one class name");
376 }
377
378 return classNames[0];
379 }
380
381 protected long getParentGroupId(long groupId) {
382 long parentGroupId = groupId;
383
384 try {
385 Group group = GroupLocalServiceUtil.getGroup(groupId);
386
387 if (group.isLayout()) {
388 parentGroupId = group.getParentGroupId();
389 }
390 }
391 catch (Exception e) {
392 }
393
394 return parentGroupId;
395 }
396
397 protected abstract String getPortletId(SearchContext searchContext);
398
399 protected void postProcessContextQuery(
400 BooleanQuery contextQuery, SearchContext searchContext)
401 throws Exception {
402 }
403
404 protected void postProcessFullQuery(
405 BooleanQuery fullQuery, SearchContext searchContext)
406 throws Exception {
407 }
408
409 protected void postProcessSearchQuery(
410 BooleanQuery searchQuery, SearchContext searchContext)
411 throws Exception {
412 }
413
414 private static Log _log = LogFactoryUtil.getLog(BaseIndexer.class);
415
416 }