1
14
15 package com.liferay.portal.kernel.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.util.Validator;
21 import com.liferay.portal.model.Group;
22 import com.liferay.portal.service.GroupLocalServiceUtil;
23 import com.liferay.portlet.asset.service.AssetCategoryServiceUtil;
24
25
30 public abstract class BaseIndexer implements Indexer {
31
32 public void delete(Object obj) throws SearchException {
33 try {
34 doDelete(obj);
35 }
36 catch (SearchException se) {
37 throw se;
38 }
39 catch (Exception e) {
40 throw new SearchException(e);
41 }
42 }
43
44 public Document getDocument(Object obj) throws SearchException {
45 try {
46 return doGetDocument(obj);
47 }
48 catch (SearchException se) {
49 throw se;
50 }
51 catch (Exception e) {
52 throw new SearchException(e);
53 }
54 }
55
56 public void reindex(Object obj) throws SearchException {
57 try {
58 if (SearchEngineUtil.isIndexReadOnly()) {
59 return;
60 }
61
62 doReindex(obj);
63 }
64 catch (SearchException se) {
65 throw se;
66 }
67 catch (Exception e) {
68 throw new SearchException(e);
69 }
70 }
71
72 public void reindex(String className, long classPK) throws SearchException {
73 try {
74 if (SearchEngineUtil.isIndexReadOnly()) {
75 return;
76 }
77
78 doReindex(className, classPK);
79 }
80 catch (NoSuchModelException nsme) {
81 if (_log.isWarnEnabled()) {
82 _log.warn("Unable to index " + className + " " + classPK);
83 }
84 }
85 catch (SearchException se) {
86 throw se;
87 }
88 catch (Exception e) {
89 throw new SearchException(e);
90 }
91 }
92
93 public void reindex(String[] ids) throws SearchException {
94 try {
95 if (SearchEngineUtil.isIndexReadOnly()) {
96 return;
97 }
98
99 doReindex(ids);
100 }
101 catch (SearchException se) {
102 throw se;
103 }
104 catch (Exception e) {
105 throw new SearchException(e);
106 }
107 }
108
109 public Hits search(SearchContext searchContext) throws SearchException {
110 try {
111 String className = getClassName(searchContext);
112
113 BooleanQuery contextQuery = BooleanQueryFactoryUtil.create();
114
115 addSearchAssetCategoryIds(contextQuery, searchContext);
116 addSearchAssetTagNames(contextQuery, searchContext);
117 addSearchGroupId(contextQuery, searchContext);
118 addSearchOwnerUserId(contextQuery, searchContext);
119 addSearchCategoryIds(contextQuery, searchContext);
120 addSearchNodeIds(contextQuery, searchContext);
121 addSearchFolderIds(contextQuery, searchContext);
122 addSearchPortletIds(contextQuery, searchContext);
123
124 BooleanQuery fullQuery = createFullQuery(
125 contextQuery, searchContext);
126
127 return SearchEngineUtil.search(
128 searchContext.getCompanyId(), searchContext.getGroupIds(),
129 searchContext.getUserId(), className, fullQuery,
130 searchContext.getSorts(), searchContext.getStart(),
131 searchContext.getEnd());
132 }
133 catch (SearchException se) {
134 throw se;
135 }
136 catch (Exception e) {
137 throw new SearchException(e);
138 }
139 }
140
141 protected void addSearchAssetCategoryIds(
142 BooleanQuery contextQuery, SearchContext searchContext)
143 throws Exception {
144
145 long[] assetCategoryIds = searchContext.getAssetCategoryIds();
146
147 if ((assetCategoryIds == null) || (assetCategoryIds.length == 0)) {
148 return;
149 }
150
151 BooleanQuery assetCategoryIdsQuery = BooleanQueryFactoryUtil.create();
152
153 for (long assetCategoryId : assetCategoryIds) {
154 if (searchContext.getUserId() > 0) {
155 try {
156 AssetCategoryServiceUtil.getCategory(assetCategoryId);
157 }
158 catch (Exception e) {
159 continue;
160 }
161 }
162
163 TermQuery termQuery = TermQueryFactoryUtil.create(
164 Field.ASSET_CATEGORY_IDS, assetCategoryId);
165
166 assetCategoryIdsQuery.add(termQuery, BooleanClauseOccur.MUST);
167 }
168
169 if (!assetCategoryIdsQuery.clauses().isEmpty()) {
170 contextQuery.add(assetCategoryIdsQuery, BooleanClauseOccur.MUST);
171 }
172 }
173
174 protected void addSearchAssetTagNames(
175 BooleanQuery contextQuery, SearchContext searchContext)
176 throws Exception {
177
178 String[] assetTagNames = searchContext.getAssetTagNames();
179
180 if ((assetTagNames == null) || (assetTagNames.length == 0)) {
181 return;
182 }
183
184 BooleanQuery assetTagNamesQuery = BooleanQueryFactoryUtil.create();
185
186 for (String assetTagName : assetTagNames) {
187 TermQuery termQuery = TermQueryFactoryUtil.create(
188 Field.ASSET_TAG_NAMES, assetTagName);
189
190 assetTagNamesQuery.add(termQuery, BooleanClauseOccur.MUST);
191 }
192
193 if (!assetTagNamesQuery.clauses().isEmpty()) {
194 contextQuery.add(assetTagNamesQuery, BooleanClauseOccur.MUST);
195 }
196 }
197
198 protected void addSearchCategoryIds(
199 BooleanQuery contextQuery, SearchContext searchContext)
200 throws Exception {
201
202 long[] categoryIds = searchContext.getCategoryIds();
203
204 if ((categoryIds == null) || (categoryIds.length == 0)) {
205 return;
206 }
207
208 BooleanQuery categoryIdsQuery = BooleanQueryFactoryUtil.create();
209
210 for (long categoryId : categoryIds) {
211 if (searchContext.getUserId() > 0) {
212 try {
213 checkSearchCategoryId(categoryId, searchContext);
214 }
215 catch (Exception e) {
216 continue;
217 }
218 }
219
220 TermQuery termQuery = TermQueryFactoryUtil.create(
221 Field.CATEGORY_ID, categoryId);
222
223 categoryIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
224 }
225
226 if (!categoryIdsQuery.clauses().isEmpty()) {
227 contextQuery.add(categoryIdsQuery, BooleanClauseOccur.MUST);
228 }
229 }
230
231 protected void addSearchFolderIds(
232 BooleanQuery contextQuery, SearchContext searchContext)
233 throws Exception {
234
235 long[] folderIds = searchContext.getFolderIds();
236
237 if ((folderIds == null) || (folderIds.length == 0)) {
238 return;
239 }
240
241 BooleanQuery folderIdsQuery = BooleanQueryFactoryUtil.create();
242
243 for (long folderId : folderIds) {
244 if (searchContext.getUserId() > 0) {
245 try {
246 checkSearchFolderId(folderId, searchContext);
247 }
248 catch (Exception e) {
249 continue;
250 }
251 }
252
253 TermQuery termQuery = TermQueryFactoryUtil.create(
254 Field.FOLDER_ID, folderId);
255
256 folderIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
257 }
258
259 if (!folderIdsQuery.clauses().isEmpty()) {
260 contextQuery.add(folderIdsQuery, BooleanClauseOccur.MUST);
261 }
262 }
263
264 protected void addSearchGroupId(
265 BooleanQuery contextQuery, SearchContext searchContext)
266 throws Exception {
267
268 long[] groupIds = searchContext.getGroupIds();
269
270 if ((groupIds == null) || (groupIds.length == 0) ||
271 ((groupIds.length == 1) && (groupIds[0] == 0))){
272
273 return;
274 }
275
276 BooleanQuery groupIdsQuery = BooleanQueryFactoryUtil.create();
277
278 for (int i = 0; i < groupIds.length; i ++) {
279 long groupId = groupIds[i];
280
281 if (groupId <= 0) {
282 continue;
283 }
284
285 try {
286 Group group = GroupLocalServiceUtil.getGroup(groupId);
287
288 long parentGroupId = groupId;
289
290 if (group.isLayout() || searchContext.isScopeStrict()) {
291 contextQuery.addRequiredTerm(
292 Field.SCOPE_GROUP_ID, groupId);
293 }
294
295 if (group.isLayout()) {
296 parentGroupId = group.getParentGroupId();
297 }
298
299 contextQuery.addRequiredTerm(Field.GROUP_ID, parentGroupId);
300
301 groupIds[i] = parentGroupId;
302 }
303 catch (Exception e) {
304 continue;
305 }
306
307 TermQuery termQuery = TermQueryFactoryUtil.create(
308 Field.GROUP_ID, groupId);
309
310 groupIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
311 }
312
313 searchContext.setGroupIds(groupIds);
314
315 if (!groupIdsQuery.clauses().isEmpty()) {
316 contextQuery.add(groupIdsQuery, BooleanClauseOccur.MUST);
317 }
318 }
319
320 protected void addSearchKeywords(
321 BooleanQuery searchQuery, SearchContext searchContext)
322 throws Exception {
323
324 String keywords = searchContext.getKeywords();
325
326 if (Validator.isNull(keywords)) {
327 return;
328 }
329
330 searchQuery.addTerms(_KEYWORDS_FIELDS, keywords);
331 }
332
333 protected void addSearchNodeIds(
334 BooleanQuery contextQuery, SearchContext searchContext)
335 throws Exception {
336
337 long[] nodeIds = searchContext.getNodeIds();
338
339 if ((nodeIds == null) || (nodeIds.length == 0)) {
340 return;
341 }
342
343 BooleanQuery nodeIdsQuery = BooleanQueryFactoryUtil.create();
344
345 for (long nodeId : nodeIds) {
346 if (searchContext.getUserId() > 0) {
347 try {
348 checkSearchNodeId(nodeId, searchContext);
349 }
350 catch (Exception e) {
351 continue;
352 }
353 }
354
355 TermQuery termQuery = TermQueryFactoryUtil.create(
356 Field.NODE_ID, nodeId);
357
358 nodeIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
359 }
360
361 if (!nodeIdsQuery.clauses().isEmpty()) {
362 contextQuery.add(nodeIdsQuery, BooleanClauseOccur.MUST);
363 }
364 }
365
366 protected void addSearchOwnerUserId(
367 BooleanQuery contextQuery, SearchContext searchContext) {
368
369 long ownerUserId = searchContext.getOwnerUserId();
370
371 if (ownerUserId > 0) {
372 contextQuery.addRequiredTerm(Field.USER_ID, ownerUserId);
373 }
374 }
375
376 protected void addSearchPortletIds(
377 BooleanQuery contextQuery, SearchContext searchContext)
378 throws Exception {
379
380 String[] portletIds = searchContext.getPortletIds();
381
382 if ((portletIds == null) || (portletIds.length == 0)) {
383 contextQuery.addRequiredTerm(
384 Field.PORTLET_ID, getPortletId(searchContext));
385 }
386 else {
387 BooleanQuery portletIdsQuery = BooleanQueryFactoryUtil.create();
388
389 for (String portletId : portletIds) {
390 if (Validator.isNull(portletId)) {
391 continue;
392 }
393
394 TermQuery termQuery = TermQueryFactoryUtil.create(
395 Field.PORTLET_ID, portletId);
396
397 portletIdsQuery.add(termQuery, BooleanClauseOccur.SHOULD);
398 }
399
400 if (!portletIdsQuery.clauses().isEmpty()) {
401 contextQuery.add(portletIdsQuery, BooleanClauseOccur.MUST);
402 }
403 }
404 }
405
406 protected void checkSearchCategoryId(
407 long categoryId, SearchContext searchContext)
408 throws Exception {
409 }
410
411 protected void checkSearchFolderId(
412 long folderId, SearchContext searchContext)
413 throws Exception {
414 }
415
416 protected void checkSearchNodeId(
417 long nodeId, SearchContext searchContext)
418 throws Exception {
419 }
420
421 protected BooleanQuery createFullQuery(
422 BooleanQuery contextQuery, SearchContext searchContext)
423 throws Exception {
424
425 postProcessContextQuery(contextQuery, searchContext);
426
427 BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
428
429 addSearchKeywords(searchQuery, searchContext);
430 postProcessSearchQuery(searchQuery, searchContext);
431
432 BooleanQuery fullQuery = BooleanQueryFactoryUtil.create();
433
434 fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
435
436 if (!searchQuery.clauses().isEmpty()) {
437 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
438 }
439
440 BooleanClause[] booleanClauses = searchContext.getBooleanClauses();
441
442 if (booleanClauses != null) {
443 for (BooleanClause booleanClause : booleanClauses) {
444 fullQuery.add(
445 booleanClause.getQuery(),
446 booleanClause.getBooleanClauseOccur());
447 }
448 }
449
450 postProcessFullQuery(fullQuery, searchContext);
451
452 return fullQuery;
453 }
454
455 protected abstract void doDelete(Object obj) throws Exception;
456
457 protected abstract Document doGetDocument(Object obj) throws Exception;
458
459 protected abstract void doReindex(Object obj) throws Exception;
460
461 protected abstract void doReindex(String className, long classPK)
462 throws Exception;
463
464 protected abstract void doReindex(String[] ids) throws Exception;
465
466 protected String getClassName(SearchContext searchContext) {
467 String[] classNames = getClassNames();
468
469 if (classNames.length != 1) {
470 throw new UnsupportedOperationException(
471 "Search method needs to be manually implemented for " +
472 "indexers with more than one class name");
473 }
474
475 return classNames[0];
476 }
477
478 protected long getParentGroupId(long groupId) {
479 long parentGroupId = groupId;
480
481 try {
482 Group group = GroupLocalServiceUtil.getGroup(groupId);
483
484 if (group.isLayout()) {
485 parentGroupId = group.getParentGroupId();
486 }
487 }
488 catch (Exception e) {
489 }
490
491 return parentGroupId;
492 }
493
494 protected abstract String getPortletId(SearchContext searchContext);
495
496 protected void postProcessContextQuery(
497 BooleanQuery contextQuery, SearchContext searchContext)
498 throws Exception {
499 }
500
501 protected void postProcessFullQuery(
502 BooleanQuery fullQuery, SearchContext searchContext)
503 throws Exception {
504 }
505
506 protected void postProcessSearchQuery(
507 BooleanQuery searchQuery, SearchContext searchContext)
508 throws Exception {
509 }
510
511 private static final String[] _KEYWORDS_FIELDS = {
512 Field.ASSET_TAG_NAMES, Field.COMMENTS, Field.CONTENT, Field.DESCRIPTION,
513 Field.PROPERTIES, Field.TITLE, Field.URL, Field.USER_NAME
514 };
515
516 private static Log _log = LogFactoryUtil.getLog(BaseIndexer.class);
517
518 }