1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.services.wcm.search;
18
19 import java.util.*;
20 import java.util.concurrent.CopyOnWriteArraySet;
21
22 import javax.jcr.*;
23 import javax.jcr.nodetype.NodeType;
24 import javax.jcr.nodetype.NodeTypeManager;
25 import javax.jcr.query.*;
26
27 import org.apache.commons.lang.StringUtils;
28 import org.exoplatform.commons.api.search.data.SearchResult;
29 import org.exoplatform.container.xml.InitParams;
30 import org.exoplatform.container.xml.ValueParam;
31 import org.exoplatform.portal.config.UserACL;
32 import org.exoplatform.services.cache.CacheService;
33 import org.exoplatform.services.cache.ExoCache;
34 import org.exoplatform.services.cms.documents.TrashService;
35 import org.exoplatform.services.cms.impl.Utils;
36 import org.exoplatform.services.cms.templates.TemplateService;
37 import org.exoplatform.services.jcr.RepositoryService;
38 import org.exoplatform.services.jcr.core.ManageableRepository;
39 import org.exoplatform.services.jcr.ext.common.SessionProvider;
40 import org.exoplatform.services.log.ExoLogger;
41 import org.exoplatform.services.log.Log;
42 import org.exoplatform.services.security.IdentityConstants;
43 import org.exoplatform.services.wcm.core.NodeLocation;
44 import org.exoplatform.services.wcm.core.NodetypeConstant;
45 import org.exoplatform.services.wcm.core.WCMConfigurationService;
46 import org.exoplatform.services.wcm.portal.LivePortalManagerService;
47 import org.exoplatform.services.wcm.publication.WCMComposer;
48 import org.exoplatform.services.wcm.search.QueryCriteria.DATE_RANGE_SELECTED;
49 import org.exoplatform.services.wcm.search.QueryCriteria.DatetimeRange;
50 import org.exoplatform.services.wcm.search.QueryCriteria.QueryProperty;
51 import org.exoplatform.services.wcm.search.base.*;
52 import org.exoplatform.services.wcm.search.connector.BaseSearchServiceConnector;
53 import org.exoplatform.services.wcm.utils.SQLQueryBuilder;
54 import org.exoplatform.services.wcm.utils.WCMCoreUtils;
55 import org.exoplatform.services.wcm.utils.AbstractQueryBuilder.COMPARISON_TYPE;
56 import org.exoplatform.services.wcm.utils.AbstractQueryBuilder.LOGICAL;
57 import org.exoplatform.services.wcm.utils.AbstractQueryBuilder.ORDERBY;
58 import org.exoplatform.services.wcm.utils.AbstractQueryBuilder.PATH_TYPE;
59 import org.exoplatform.services.wcm.utils.AbstractQueryBuilder.QueryTermHelper;
60
61
62
63
64 public class SiteSearchServiceImpl implements SiteSearchService {
65
66 private static final String SITE_SEARCH_FOUND_CACHE = "ecms.SiteSearchService.found";
67
68 private static final String SITE_SEARCH_DROP_CACHE = "ecms.SiteSearchService.drop";
69
70
71 private static final String IS_ENABLED_FUZZY_SEARCH = "isEnabledFuzzySearch";
72
73
74
75 private static final String FUZZY_SEARCH_INDEX = "fuzzySearchIndex";
76
77
78 private LivePortalManagerService livePortalManagerService;
79
80
81 private TemplateService templateService;
82
83
84 private WCMConfigurationService configurationService;
85
86
87 private RepositoryService repositoryService;
88
89
90 private CopyOnWriteArraySet<String> excludeNodeTypes = new CopyOnWriteArraySet<>();
91
92
93 private CopyOnWriteArraySet<String> includeNodeTypes = new CopyOnWriteArraySet<>();
94
95
96 private CopyOnWriteArraySet<String> excludeMimeTypes = new CopyOnWriteArraySet<>();
97
98
99 private CopyOnWriteArraySet<String> includeMimeTypes = new CopyOnWriteArraySet<>();
100
101 private boolean isEnabledFuzzySearch = true;
102
103 private double fuzzySearchIndex = 0.8;
104
105
106 private static final Log LOG = ExoLogger.getLogger(SiteSearchServiceImpl.class.getName());
107
108 private ExoCache<String, Map<?, Integer>> foundNodeCache;
109 private ExoCache<String, Map<Integer, Integer>> dropNodeCache;
110
111
112
113
114
115
116
117
118
119
120
121
122 public SiteSearchServiceImpl(LivePortalManagerService portalManagerService,
123 TemplateService templateService,
124 WCMConfigurationService configurationService,
125 RepositoryService repositoryService,
126 CacheService caService,
127 InitParams initParams) throws Exception {
128 this.livePortalManagerService = portalManagerService;
129 this.templateService = templateService;
130 this.repositoryService = repositoryService;
131 this.configurationService = configurationService;
132 this.foundNodeCache = caService.getCacheInstance(SITE_SEARCH_FOUND_CACHE);
133 this.dropNodeCache = caService.getCacheInstance(SITE_SEARCH_DROP_CACHE);
134 if (initParams != null) {
135 ValueParam isEnabledFuzzySearchValue = initParams.getValueParam(IS_ENABLED_FUZZY_SEARCH);
136 if (isEnabledFuzzySearchValue != null)
137 isEnabledFuzzySearch = Boolean.parseBoolean(isEnabledFuzzySearchValue.getValue());
138 ValueParam enabledFuzzySearchValue = initParams.getValueParam(FUZZY_SEARCH_INDEX);
139 if (enabledFuzzySearchValue != null) {
140 try {
141 fuzzySearchIndex = Double.parseDouble(enabledFuzzySearchValue.getValue());
142 } catch (NumberFormatException e) {
143
144 fuzzySearchIndex = 0.8;
145 }
146 }
147 if (fuzzySearchIndex < 0 || fuzzySearchIndex >= 1) {
148
149 fuzzySearchIndex = 0.8;
150 }
151 }
152
153 }
154
155
156
157
158
159
160
161 @Override
162 public void addExcludeIncludeDataTypePlugin(ExcludeIncludeDataTypePlugin plugin) {
163 excludeNodeTypes.addAll(plugin.getExcludeNodeTypes());
164 excludeMimeTypes.addAll(plugin.getExcludeMimeTypes());
165 includeMimeTypes.addAll(plugin.getIncludeMimeTypes());
166 includeNodeTypes.addAll(plugin.getIncludeNodeTypes());
167 }
168
169
170
171
172
173
174
175
176 @Override
177 public AbstractPageList<ResultNode> searchSiteContents(SessionProvider sessionProvider,
178 QueryCriteria queryCriteria,
179 Locale locale,
180 int pageSize,
181 boolean isSearchContent) throws Exception {
182 ManageableRepository currentRepository = repositoryService.getCurrentRepository();
183 NodeLocation location = configurationService.getLivePortalsLocation();
184 Session session = sessionProvider.getSession(location.getWorkspace(),currentRepository);
185 if (queryCriteria.isSearchWebpage()) {
186 session = sessionProvider.getSession("portal-system", WCMCoreUtils.getRepository());
187 }
188 QueryManager queryManager = session.getWorkspace().getQueryManager();
189 long startTime = System.currentTimeMillis();
190 Query query = createQuery(queryCriteria, queryManager);
191 String suggestion = getSpellSuggestion(queryCriteria.getKeyword(),currentRepository);
192 AbstractPageList<ResultNode> pageList = null;
193 if (LOG.isDebugEnabled()) {
194 LOG.debug("execute query: " + query.getStatement().toLowerCase());
195 }
196 pageList = PageListFactory.createPageList(query.getStatement(),
197 locale,
198 session.getWorkspace().getName(),
199 query.getLanguage(),
200 IdentityConstants.SYSTEM.equals(session.getUserID()),
201 new NodeFilter(isSearchContent, queryCriteria),
202 new DataCreator(),
203 pageSize,
204 (int)queryCriteria.getLimit(), queryCriteria);
205
206 long queryTime = System.currentTimeMillis() - startTime;
207 pageList.setQueryTime(queryTime);
208 pageList.setSpellSuggestion(suggestion);
209 return pageList;
210 }
211
212
213
214
215 @Override
216 public AbstractPageList<ResultNode> searchPageContents(SessionProvider sessionProvider,
217 QueryCriteria queryCriteria,
218 Locale locale,
219 int pageSize,
220 boolean isSearchContent) throws Exception {
221 ManageableRepository currentRepository = repositoryService.getCurrentRepository();
222 Session session = sessionProvider.getSession("portal-system", currentRepository);
223 QueryManager queryManager = session.getWorkspace().getQueryManager();
224 long startTime = System.currentTimeMillis();
225 Query query = createSearchPageQuery(queryCriteria, queryManager);
226 if (query == null) {
227 return new ArrayNodePageList<>(pageSize);
228 }
229 String suggestion = getSpellSuggestion(queryCriteria.getKeyword(), currentRepository);
230 if (LOG.isDebugEnabled()) {
231 LOG.debug("execute query: " + query.getStatement().toLowerCase());
232 }
233 AbstractPageList<ResultNode> pageList = PageListFactory.createPageList(query.getStatement(),
234 locale,
235 session.getWorkspace()
236 .getName(),
237 query.getLanguage(),
238 true,
239 new PageNodeFilter(),
240 new PageDataCreator(),
241 pageSize,
242 0);
243
244 long queryTime = System.currentTimeMillis() - startTime;
245 pageList.setQueryTime(queryTime);
246 pageList.setSpellSuggestion(suggestion);
247 return pageList;
248 }
249
250 @Override
251 public Map<?, Integer> getFoundNodes(String userId, String queryStatement) {
252 String key = new StringBuilder('(').append(userId).append(';').append(queryStatement).append(')').toString();
253 Map<?, Integer> ret = foundNodeCache.get(key);
254 if (ret == null) {
255 ret = new HashMap<Integer, Integer>();
256 foundNodeCache.put(key, ret);
257 }
258 return ret;
259 }
260
261 @Override
262 public Map<Integer, Integer> getDropNodes(String userId, String queryStatement) {
263 String key = new StringBuilder('(').append(userId).append(';').append(queryStatement).append(')').toString();
264 Map<Integer, Integer> ret = dropNodeCache.get(key);
265 if (ret == null) {
266 ret = new HashMap<>();
267 dropNodeCache.put(key, ret);
268 }
269 return ret;
270 }
271
272 @Override
273 public void clearCache(String userId, String queryStatement) {
274 String key = new StringBuilder('(').append(userId).append(';').append(queryStatement).append(')').toString();
275 foundNodeCache.remove(key);
276 dropNodeCache.remove(key);
277 }
278
279 private Query createSearchPageQuery(QueryCriteria queryCriteria, QueryManager queryManager) throws Exception {
280 SQLQueryBuilder queryBuilder = new SQLQueryBuilder();
281 List<String> mopPages = this.searchPageByTitle(queryCriteria.getSiteName(),
282 queryCriteria.getKeyword());
283 if (mopPages.size() == 0) {
284 return null;
285 }
286 List<QueryProperty> queryProps = new ArrayList<>();
287 for (String page : mopPages) {
288 QueryProperty prop = queryCriteria.new QueryProperty();
289 prop.setName("mop:page");
290 prop.setValue(page);
291 prop.setComparisonType(COMPARISON_TYPE.EQUAL);
292 queryProps.add(prop);
293 }
294 QueryProperty prop = queryCriteria.new QueryProperty();
295 prop.setName("exo:name");
296 prop.setValue("mop:" + queryCriteria.getKeyword().toLowerCase());
297 queryProps.add(prop);
298 queryCriteria.setQueryMetadatas(queryProps.toArray(new QueryProperty[queryProps.size()]));
299 mapQueryTypes(queryCriteria, queryBuilder);
300 if (queryCriteria.isFulltextSearch()) {
301 mapQueryPath(queryCriteria, queryBuilder);
302 mapFulltextQueryTearm(queryCriteria, queryBuilder, LOGICAL.OR);
303 } else {
304 searchByNodeName(queryCriteria, queryBuilder);
305 }
306 mapCategoriesCondition(queryCriteria,queryBuilder);
307 mapDatetimeRangeSelected(queryCriteria,queryBuilder);
308 mapMetadataProperties(queryCriteria,queryBuilder, LOGICAL.OR);
309 orderBy(queryCriteria, queryBuilder);
310 String queryStatement = queryBuilder.createQueryStatement();
311 Query query = queryManager.createQuery(queryStatement, Query.SQL);
312 return query;
313 }
314
315
316
317
318
319
320 private List<String> searchPageByTitle(String siteName, String keyword) throws Exception {
321 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
322 ManageableRepository currentRepository = repositoryService.getCurrentRepository();
323 Session session = sessionProvider.getSession("portal-system", currentRepository);
324 QueryManager queryManager = session.getWorkspace().getQueryManager();
325 QueryCriteria queryCriteria = new QueryCriteria();
326 queryCriteria.setSiteName(siteName);
327 queryCriteria.setKeyword(keyword);
328 queryCriteria.setSearchWebpage(true);
329 Query query = createSearchPageByTitleQuery(queryCriteria, queryManager);
330 if (LOG.isDebugEnabled()) {
331 LOG.debug("execute query: " + query.getStatement().toLowerCase());
332 }
333 List<String> pageList = PageListFactory.createPageList(query.getStatement(),
334 session.getWorkspace().getName(),
335 query.getLanguage(),
336 true,
337 new PageTitleDataCreator());
338 return pageList;
339 }
340
341
342
343
344
345
346
347
348 private Query createSearchPageByTitleQuery(QueryCriteria queryCriteria, QueryManager queryManager) throws Exception {
349 SQLQueryBuilder queryBuilder = new SQLQueryBuilder();
350
351
352 queryBuilder.selectTypes(null);
353
354
355 queryBuilder.fromNodeTypes(new String[] { "mop:page" });
356
357 mapQueryPath(queryCriteria, queryBuilder);
358
359 queryCriteria.setFulltextSearchProperty(new String[] {"gtn:name"});
360
361 mapFulltextQueryTearm(queryCriteria, queryBuilder, LOGICAL.OR);
362
363 String queryStatement = queryBuilder.createQueryStatement();
364 Query query = queryManager.createQuery(queryStatement, Query.SQL);
365
366 return query;
367 }
368
369
370
371
372
373
374
375
376
377
378
379 private String getSpellSuggestion(String checkingWord, ManageableRepository manageableRepository) throws Exception {
380
381 String suggestion = null;
382 Session session = null;
383 try{
384 session = manageableRepository.getSystemSession(manageableRepository.getConfiguration().getDefaultWorkspaceName());
385 QueryManager queryManager = session.getWorkspace().getQueryManager();
386 Query query = queryManager.createQuery("SELECT rep:spellcheck() FROM nt:base WHERE jcr:path like '/' AND SPELLCHECK('"
387 + checkingWord + "')",
388 Query.SQL);
389 RowIterator rows = query.execute().getRows();
390 Value value = rows.nextRow().getValue("rep:spellcheck()");
391 if (value != null) {
392 suggestion = value.getString();
393 }
394 } catch (Exception e) {
395 if (LOG.isWarnEnabled()) {
396 LOG.warn(e.getMessage());
397 }
398 } finally {
399 if (session != null)
400 session.logout();
401 }
402 return suggestion;
403 }
404
405
406
407
408
409
410
411
412
413
414
415 private Query createQuery(QueryCriteria queryCriteria, QueryManager queryManager) throws Exception {
416 SQLQueryBuilder queryBuilder = new SQLQueryBuilder();
417 mapQueryTypes(queryCriteria, queryBuilder);
418 if (queryCriteria.isFulltextSearch()) {
419 mapQueryPath(queryCriteria, queryBuilder);
420 mapFulltextQueryTearm(queryCriteria, queryBuilder, LOGICAL.OR);
421 } else {
422 searchByNodeName(queryCriteria, queryBuilder);
423 }
424 mapCategoriesCondition(queryCriteria,queryBuilder);
425 mapDatetimeRangeSelected(queryCriteria, queryBuilder);
426 mapMetadataProperties(queryCriteria, queryBuilder, LOGICAL.AND);
427 orderBy(queryCriteria, queryBuilder);
428 String queryStatement = queryBuilder.createQueryStatement();
429 Query query = queryManager.createQuery(queryStatement, Query.SQL);
430
431 return query;
432 }
433
434
435
436
437
438
439
440
441
442 private void mapQueryPath(final QueryCriteria queryCriteria, final SQLQueryBuilder queryBuilder) throws Exception {
443 queryBuilder.setQueryPath(getPath(queryCriteria), PATH_TYPE.DECENDANTS);
444 }
445
446
447
448
449
450
451
452
453
454
455 private String getPath(final QueryCriteria queryCriteria) throws Exception {
456 String siteName = queryCriteria.getSiteName();
457
458 if (queryCriteria.isSearchWebpage()) {
459 if ("all".equals(siteName) || siteName == null || siteName.trim().length() == 0) {
460 return PATH_PORTAL_SITES;
461 }
462 return PATH_PORTAL_SITES.concat("/mop:").concat(siteName);
463 }
464
465 if (queryCriteria.getSearchPath() != null) {
466 return queryCriteria.getSearchPath();
467 }
468 String sitePath = null;
469 if (siteName != null) {
470 sitePath = livePortalManagerService.getPortalPathByName(siteName);
471 } else {
472 sitePath = configurationService.getLivePortalsLocation().getPath();
473 }
474 return sitePath;
475 }
476
477
478
479
480
481
482
483 private void mapFulltextQueryTearm(final QueryCriteria queryCriteria,
484 final SQLQueryBuilder queryBuilder, LOGICAL condition) {
485 String keyword = queryCriteria.getKeyword();
486 if (keyword == null || keyword.length() == 0)
487 return;
488
489 keyword = Utils.escapeIllegalCharacterInQuery(keyword);
490
491 QueryTermHelper queryTermHelper = new QueryTermHelper();
492 String queryTerm = null;
493 if (isEnabledFuzzySearch) {
494 if (keyword.contains("*") || keyword.contains("?") || keyword.contains("~") || keyword.contains("\"")) {
495 queryTerm = queryTermHelper.contains(keyword).buildTerm();
496 } else if(queryCriteria.isFuzzySearch()) {
497 queryTerm = queryTermHelper.contains(keyword).allowFuzzySearch(fuzzySearchIndex).buildTerm();
498 } else {
499 queryTerm = queryTermHelper.contains(keyword).buildTerm();
500 }
501 } else {
502 if(!queryCriteria.isFuzzySearch()) {
503 keyword = keyword.replace("~", "\\~");
504 keyword = keyword.replace("*", "\\*");
505 keyword = keyword.replace("?", "\\?");
506 }
507 queryTerm = queryTermHelper.contains(keyword).buildTerm();
508 }
509 String[] props = queryCriteria.getFulltextSearchProperty();
510 if (props == null || props.length == 0 || QueryCriteria.ALL_PROPERTY_SCOPE.equals(props[0])) {
511 queryBuilder.contains(null, queryTerm, LOGICAL.NULL);
512 } else {
513 queryBuilder.contains(props[0], queryTerm, LOGICAL.NULL);
514 for (int i = 1; i < props.length; i++) {
515 queryBuilder.contains(props[i], queryTerm, condition);
516 }
517 }
518 }
519
520
521
522
523
524
525
526
527
528 private void searchByNodeName(final QueryCriteria queryCriteria,
529 final SQLQueryBuilder queryBuilder) throws Exception {
530 queryBuilder.queryByNodeName(getPath(queryCriteria), queryCriteria.getKeyword());
531 }
532
533
534
535
536
537
538
539 private void mapDatetimeRangeSelected(final QueryCriteria queryCriteria,
540 final SQLQueryBuilder queryBuilder) {
541 DATE_RANGE_SELECTED selectedDateRange = queryCriteria.getDateRangeSelected();
542 if (selectedDateRange == null)
543 return;
544 if (DATE_RANGE_SELECTED.CREATED == selectedDateRange) {
545 DatetimeRange createdDateRange = queryCriteria.getCreatedDateRange();
546 queryBuilder.betweenDates("exo:dateCreated",
547 createdDateRange.getFromDate(),
548 createdDateRange.getToDate(),
549 LOGICAL.AND);
550 } else if (DATE_RANGE_SELECTED.MODIFIDED == selectedDateRange) {
551 DatetimeRange modifiedDateRange = queryCriteria.getLastModifiedDateRange();
552 queryBuilder.betweenDates("exo:dateModified",
553 modifiedDateRange.getFromDate(),
554 modifiedDateRange.getToDate(),
555 LOGICAL.AND);
556 } else if (DATE_RANGE_SELECTED.START_PUBLICATION == selectedDateRange) {
557 throw new UnsupportedOperationException();
558 } else if (DATE_RANGE_SELECTED.END_PUBLICATION == selectedDateRange) {
559 throw new UnsupportedOperationException();
560 }
561 }
562
563
564
565
566
567
568
569 private void mapCategoriesCondition(QueryCriteria queryCriteria, SQLQueryBuilder queryBuilder) {
570 String[] categoryUUIDs = queryCriteria.getCategoryUUIDs();
571 if (categoryUUIDs == null)
572 return;
573 queryBuilder.openGroup(LOGICAL.AND);
574 queryBuilder.like("exo:category", categoryUUIDs[0], LOGICAL.NULL);
575 if (categoryUUIDs.length > 1) {
576 for (int i = 1; i < categoryUUIDs.length; i++) {
577 queryBuilder.like("exo:category", categoryUUIDs[i], LOGICAL.OR);
578 }
579 }
580 queryBuilder.closeGroup();
581 }
582
583
584
585
586
587
588
589 private void mapMetadataProperties(final QueryCriteria queryCriteria, SQLQueryBuilder queryBuilder, LOGICAL condition) {
590 QueryProperty[] queryProperty = queryCriteria.getQueryMetadatas();
591 if (queryProperty == null || queryProperty.length == 0)
592 return;
593 queryBuilder.openGroup(condition);
594 if (queryProperty[0].getComparisonType() == COMPARISON_TYPE.EQUAL) {
595 queryBuilder.equal(queryProperty[0].getName(), queryProperty[0].getValue(), LOGICAL.NULL);
596 } else {
597 queryBuilder.like(queryProperty[0].getName(), queryProperty[0].getValue(), LOGICAL.NULL);
598 }
599 if (queryProperty.length > 1) {
600 for (int i = 1; i < queryProperty.length; i++) {
601 if (queryProperty[i].getComparisonType() == COMPARISON_TYPE.EQUAL) {
602 queryBuilder.equal(queryProperty[i].getName(), queryProperty[i].getValue(), LOGICAL.OR);
603 } else {
604 queryBuilder.like(queryProperty[i].getName(), queryProperty[i].getValue(), LOGICAL.OR);
605 }
606 }
607 }
608 queryBuilder.closeGroup();
609 }
610
611
612
613
614
615
616
617
618
619
620 private void mapQuerySpecificNodeTypes(final QueryCriteria queryCriteria,
621 final SQLQueryBuilder queryBuilder,
622 final NodeTypeManager nodeTypeManager) throws Exception {
623 String[] contentTypes = queryCriteria.getContentTypes();
624 NodeType fistType = nodeTypeManager.getNodeType(contentTypes[0]);
625 queryBuilder.openGroup(LOGICAL.AND);
626 if (fistType.isMixin()) {
627 queryBuilder.like("jcr:mixinTypes", contentTypes[0], LOGICAL.NULL);
628 } else {
629 queryBuilder.equal("jcr:primaryType", contentTypes[0], LOGICAL.NULL);
630 }
631 if(contentTypes.length>1) {
632 for (int i=1; i<contentTypes.length; i++) {
633 String type = contentTypes[i];
634 NodeType nodetype = nodeTypeManager.getNodeType(type);
635 if (nodetype.isMixin()) {
636 queryBuilder.like("jcr:mixinTypes", type, LOGICAL.OR);
637 } else {
638 queryBuilder.equal("jcr:primaryType", type, LOGICAL.OR);
639 }
640 }
641 }
642 queryBuilder.closeGroup();
643
644 queryBuilder.openGroup(LOGICAL.AND_NOT);
645 queryBuilder.like("jcr:mixinTypes", "exo:cssFile", LOGICAL.NULL);
646 queryBuilder.like("jcr:mixinTypes","exo:jsFile",LOGICAL.OR);
647 queryBuilder.closeGroup();
648 }
649
650
651
652
653
654
655
656
657
658 private void mapQueryTypes(final QueryCriteria queryCriteria, final SQLQueryBuilder queryBuilder) throws Exception {
659 queryBuilder.selectTypes(null);
660
661 queryBuilder.fromNodeTypes(queryCriteria.getNodeTypes());
662 ManageableRepository currentRepository = repositoryService.getCurrentRepository();
663 NodeTypeManager manager = currentRepository.getNodeTypeManager();
664
665 String[] contentTypes = queryCriteria.getContentTypes();
666 if ((contentTypes != null && contentTypes.length > 0 && queryCriteria.getKeyword() == null)
667 || queryCriteria.isSearchWebpage()) {
668 mapQuerySpecificNodeTypes(queryCriteria, queryBuilder, manager);
669 return;
670 }
671 List<String> selectedNodeTypes =
672 (contentTypes != null && contentTypes.length > 0) ? Arrays.asList(contentTypes) :
673 templateService.getDocumentTemplates();
674 queryBuilder.openGroup(LOGICAL.AND);
675 if (selectedNodeTypes.contains("nt:file")) {
676 queryBuilder.equal("jcr:primaryType", NodetypeConstant.NT_FILE, LOGICAL.NULL);
677 } else {
678
679 queryBuilder.openGroup(null);
680 queryBuilder.equal(NodetypeConstant.JCR_PRIMARY_TYPE, NodetypeConstant.NT_RESOURCE, LOGICAL.NULL);
681 queryBuilder.equal(NodetypeConstant.JCR_MIXIN_TYPES, NodetypeConstant.EXO_WEBCONTENT_CHILD, LOGICAL.AND);
682 queryBuilder.closeGroup();
683 }
684
685
686 for (String type : selectedNodeTypes) {
687 NodeType nodetype = manager.getNodeType(type);
688 if (nodetype.isMixin()) {
689 if (selectedNodeTypes.contains("nt:file") ||
690 !NodetypeConstant.EXO_CSS_FILE.equals(type) &&
691 !NodetypeConstant.EXO_JS_FILE.equals(type) &&
692 !NodetypeConstant.EXO_HTML_FILE.equals(type)) {
693 queryBuilder.like("jcr:mixinTypes", type, LOGICAL.OR);
694 } else {
695
696 queryBuilder.openGroup(LOGICAL.OR);
697 queryBuilder.equal(NodetypeConstant.JCR_MIXIN_TYPES, type, LOGICAL.NULL);
698 queryBuilder.equal(NodetypeConstant.JCR_MIXIN_TYPES, NodetypeConstant.EXO_WEBCONTENT_CHILD, LOGICAL.AND);
699 queryBuilder.closeGroup();
700 }
701 } else {
702 if(!type.equals(NodetypeConstant.NT_FILE)) {
703 queryBuilder.equal("jcr:primaryType", type, LOGICAL.OR);
704 }
705 }
706 }
707 queryBuilder.closeGroup();
708
709 if(excludeMimeTypes.size()<1) return;
710 queryBuilder.openGroup(LOGICAL.AND_NOT);
711 String[] mimetypes = excludeMimeTypes.toArray(new String[]{});
712 queryBuilder.equal("jcr:mimeType",mimetypes[0],LOGICAL.NULL);
713 for(int i=1; i<mimetypes.length; i++) {
714 queryBuilder.equal("jcr:mimeType",mimetypes[i],LOGICAL.OR);
715 }
716 queryBuilder.closeGroup();
717
718 queryBuilder.openGroup(LOGICAL.AND_NOT);
719 queryBuilder.like("jcr:mixinTypes", "exo:cssFile", LOGICAL.NULL);
720 queryBuilder.like("jcr:mixinTypes","exo:jsFile",LOGICAL.OR);
721 queryBuilder.closeGroup();
722
723 queryBuilder.openGroup(LOGICAL.AND_NOT);
724 String[] _excludeNodeTypes = excludeNodeTypes.toArray(new String[]{});
725 for(int i=0; i < _excludeNodeTypes.length; i++) {
726 if(i==0) {
727 queryBuilder.equal("jcr:mixinTypes", _excludeNodeTypes[i], LOGICAL.NULL);
728 } else {
729 queryBuilder.equal("jcr:mixinTypes", _excludeNodeTypes[i], LOGICAL.OR);
730 }
731 }
732 queryBuilder.closeGroup();
733
734 }
735
736
737
738
739
740
741
742 private void orderBy(final QueryCriteria criteria, final SQLQueryBuilder queryBuilder) {
743 String sortBy = "jcr:score";
744 String orderBy = "desc";
745
746 if (BaseSearchServiceConnector.sortByTitle.equals(criteria.getSortBy())) {
747 sortBy = NodetypeConstant.EXO_TITLE;
748 } else if (BaseSearchServiceConnector.sortByDate.equals(criteria.getSortBy())) {
749 sortBy = NodetypeConstant.EXO_LAST_MODIFIED_DATE;
750 }
751 if (StringUtils.isNotBlank(criteria.getOrderBy())) {
752 orderBy = criteria.getOrderBy();
753 }
754 queryBuilder.orderBy(sortBy, "desc".equals(orderBy) ? ORDERBY.DESC : ORDERBY.ASC);
755 }
756
757 public static class NodeFilter implements NodeSearchFilter {
758
759 private boolean isSearchContent;
760 private QueryCriteria queryCriteria;
761 private TrashService trashService = WCMCoreUtils.getService(TrashService.class);
762
763 public NodeFilter(boolean isSearchContent, QueryCriteria queryCriteria) {
764 this.isSearchContent = isSearchContent;
765 this.queryCriteria = queryCriteria;
766 }
767
768 @Override
769 public Node filterNodeToDisplay(Node node) {
770 try {
771 if (node == null || node.getPath().contains("/jcr:system/")) return null;
772 if(trashService.isInTrash(node)) return null;
773 Node displayNode = getNodeToCheckState(node);
774 if(displayNode == null) return null;
775 if (isSearchContent) return displayNode;
776 NodeLocation nodeLocation = NodeLocation.getNodeLocationByNode(displayNode);
777 WCMComposer wcmComposer = WCMCoreUtils.getService(WCMComposer.class);
778 HashMap<String, String> filters = new HashMap<>();
779 filters.put(WCMComposer.FILTER_MODE, queryCriteria.isLiveMode() ? WCMComposer.MODE_LIVE
780 : WCMComposer.MODE_EDIT);
781 return wcmComposer.getContent(nodeLocation.getWorkspace(),
782 nodeLocation.getPath(),
783 filters,
784 WCMCoreUtils.getSystemSessionProvider());
785 } catch (Exception e) {
786 return null;
787 }
788 }
789
790 protected Node getNodeToCheckState(Node node)throws Exception{
791 Node displayNode = node;
792 if (displayNode.isNodeType("nt:resource")) {
793 displayNode = node.getParent();
794 }
795
796 if (displayNode.isNodeType("exo:htmlFile")) {
797 Node parent = displayNode.getParent();
798 if (parent.isNodeType("exo:webContent")) {
799 displayNode = parent;
800 }
801 }
802 String[] contentTypes = queryCriteria.getContentTypes();
803 if(contentTypes != null && contentTypes.length > 0) {
804 for (String contentType : contentTypes) {
805 if (displayNode.isNodeType(contentType)) {
806 return displayNode;
807 }
808 }
809 } else {
810 return displayNode;
811 }
812 return null;
813 }
814
815 }
816
817
818
819
820
821
822 public static class PageNodeFilter implements NodeSearchFilter {
823
824 @Override
825 public Node filterNodeToDisplay(Node node) {
826 try {
827 if (!node.isNodeType("mop:navigation") && !node.isNodeType("mop:pagelink")
828 && !node.isNodeType("gtn:language")) {
829 return null;
830 } else {
831 return node;
832 }
833 } catch (RepositoryException e) {
834 return null;
835 }
836 }
837
838 }
839
840 public static class DataCreator implements SearchDataCreator<ResultNode> {
841
842 @Override
843 public ResultNode createData(Node node, Row row, SearchResult searchResult) {
844 try {
845 if(row == null && searchResult != null) {
846 return new ResultNode(node, searchResult.getRelevancy(), searchResult.getExcerpt());
847 } else {
848 return new ResultNode(node, row);
849 }
850 } catch (Exception e) {
851 return null;
852 }
853 }
854
855 }
856
857 public static class PageDataCreator implements SearchDataCreator<ResultNode> {
858
859 private static HashSet<String> userNavigationUriList = new HashSet<>();
860
861 @Override
862 public ResultNode createData(Node node, Row row, SearchResult searchResult) {
863 try {
864 if (node.isNodeType("mop:pagelink")) {
865 node = node.getParent();
866 }
867
868 if (node.isNodeType("gtn:language")) {
869 node = node.getParent().getParent();
870 }
871 String userNaviUri = "/" + WCMCoreUtils.getPortalName() + "/" + PageDataCreator.getUserNavigationURI(node).toString();
872 if (userNavigationUriList.contains(userNaviUri)) {
873 return null;
874 }
875 userNavigationUriList.add(userNaviUri);
876 return new ResultNode(node, row, userNaviUri);
877 } catch (Exception e) {
878 return null;
879 }
880 }
881
882
883
884
885
886
887
888 public static StringBuilder getUserNavigationURI(Node node) throws RepositoryException {
889 if (!node.isNodeType("mop:portalsites")) {
890 StringBuilder builder = getUserNavigationURI(node.getParent());
891 String name = node.getName();
892 if ("mop:children".equals(name) || "mop:default".equals(name)
893 || "mop:rootnavigation".equals(name)) {
894 return builder.append("");
895 } else {
896 if (builder.length() > 0) {
897 builder.append("/");
898 }
899 return builder.append(node.getName().replaceFirst("mop:", ""));
900 }
901 } else {
902 return new StringBuilder();
903 }
904
905 }
906
907 }
908
909
910
911
912
913
914 public static class PageTitleDataCreator implements SearchDataCreator<String> {
915
916 @Override
917 public String createData(Node node, Row row, SearchResult searchResult) {
918 try {
919 UserACL userACL = WCMCoreUtils.getService(UserACL.class);
920 if (node.hasProperty("gtn:access-permissions")) {
921 for (Value v : node.getProperty("gtn:access-permissions").getValues()) {
922 if (userACL.hasPermission(v.getString())) {
923 return node.getPath();
924 }
925 }
926 return null;
927 } else {
928 return node.getPath();
929 }
930 } catch (RepositoryException e) {
931 return null;
932 }
933 }
934
935 }
936
937 }