View Javadoc
1   /*
2    * Copyright (C) 2003-2011 eXo Platform SAS.
3    *
4    * This program is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Affero General Public License
6    * as published by the Free Software Foundation; either version 3
7    * of the License, or (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program; if not, see<http://www.gnu.org/licenses/>.
16   */
17  package org.exoplatform.services.wcm.search.base;
18  
19  import org.exoplatform.commons.api.search.data.SearchResult;
20  import org.exoplatform.commons.utils.CommonsUtils;
21  import org.exoplatform.services.jcr.ext.common.SessionProvider;
22  import org.exoplatform.services.jcr.impl.core.query.QueryImpl;
23  import org.exoplatform.services.log.ExoLogger;
24  import org.exoplatform.services.log.Log;
25  import org.exoplatform.services.security.ConversationState;
26  import org.exoplatform.services.wcm.search.QueryCriteria;
27  import org.exoplatform.services.wcm.search.SiteSearchService;
28  import org.exoplatform.services.wcm.search.connector.FileApplicationSearchServiceConnector;
29  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
30  
31  import javax.jcr.*;
32  import javax.jcr.query.*;
33  import java.util.*;
34  import java.util.regex.Matcher;
35  import java.util.regex.Pattern;
36  
37  /**
38   * Created by The eXo Platform SAS
39   * Author : Nguyen Anh Vu
40   *          anhvurz90@gmail.com
41   * Jun 17, 2011  
42   */
43  public class PageListFactory {
44  
45    private static final Log LOG = ExoLogger.getLogger(PageListFactory.class.getName());
46    
47    public static <E> AbstractPageList<E> createPageList(String queryStatement,
48                                                         Locale locale,
49                                                         String workspace,
50                                                         String language,
51                                                         boolean isSystemSession,
52                                                         NodeSearchFilter filter,
53                                                         SearchDataCreator<E> dataCreator,
54                                                         int pageSize,
55                                                         int bufferSize,
56                                                         QueryCriteria criteria) throws RepositoryException {
57      SiteSearchService siteSearchService = WCMCoreUtils.getService(SiteSearchService.class);
58  
59      if (pageSize == 0) {
60        pageSize = AbstractPageList.DEFAULT_PAGE_SIZE;
61      }
62  
63      if (criteria != null) {
64        if (criteria.getOffset() <= 0) {
65          // WCMAdvancedSearch takes the default value (-1) of QueryCriteria's offset
66          // reset it to 0 to align with the default value of Unified Search
67          criteria.setOffset(0);
68          siteSearchService.clearCache(ConversationState.getCurrent().getIdentity().getUserId(), queryStatement);
69        }
70      } else {
71        siteSearchService.clearCache(ConversationState.getCurrent().getIdentity().getUserId(), queryStatement);
72      }
73  
74      // search in JCR
75      List<E> results = searchInJCR(queryStatement, workspace, language, isSystemSession, filter, dataCreator, criteria);
76  
77      if(criteria != null && !criteria.isSearchWebpage()) {
78        // search in ES
79        results.addAll(searchInES(workspace, locale, isSystemSession, filter, dataCreator, criteria));
80      }
81  
82      // remove duplications
83      results = new ArrayList<>(new LinkedHashSet<>(results));
84  
85      if(criteria != null && criteria.getOffset() > 0) {
86        results = results.subList((int) criteria.getOffset(), results.size());
87      }
88  
89      return new ArrayNodePageList<>(results, pageSize);
90    }
91    
92    public static <E> AbstractPageList<E> createPageList(String queryStatement,
93                                                         Locale locale,
94                                                         String workspace,
95                                                         String language,
96                                                         boolean isSystemSession,
97                                                         NodeSearchFilter filter,
98                                                         SearchDataCreator<E> dataCreator,
99                                                         int pageSize,
100                                                        int bufferSize) throws LoginException,
101                                                                       NoSuchWorkspaceException,
102                                                                       RepositoryException {
103     return createPageList(queryStatement, locale, workspace, language,
104                            isSystemSession, filter, dataCreator,
105                            pageSize, bufferSize, null);
106   }
107   
108   public static <E> AbstractPageList<E> createPageList(String queryStatement,
109                                                        Locale locale,
110                                                        String workspace,
111                                                        String language,
112                                                        boolean isSystemSession,
113                                                        NodeSearchFilter filter,
114                                                        SearchDataCreator<E> dataCreator) throws LoginException,
115                                                                                         NoSuchWorkspaceException,
116                                                                                         RepositoryException {
117     return createPageList(queryStatement, locale, workspace, language,
118                           isSystemSession, filter, dataCreator,
119                           AbstractPageList.DEFAULT_PAGE_SIZE, AbstractPageList.DEAFAULT_BUFFER_SIZE);
120   }
121   
122   public static <E> AbstractPageList<E> createPageList(List<Node> nodes, int pageSize, 
123                            NodeSearchFilter filter, SearchDataCreator<E> dataCreator) {
124 
125     return new ArrayNodePageList<E>(nodes, pageSize, filter, dataCreator);
126   }
127   
128   /**
129    * 
130    * @param <E>
131    * @param queryStatement
132    * @param workspace
133    * @param language
134    * @param isSystemSession
135    * @param dataCreator
136    * @return
137    * @throws LoginException
138    * @throws NoSuchWorkspaceException
139    * @throws RepositoryException
140    */
141   public static <E> List<E> createPageList(String queryStatement,
142                                            String workspace,
143                                            String language,
144                                            boolean isSystemSession,
145                                            SearchDataCreator<E> dataCreator) throws LoginException,
146                                                                             NoSuchWorkspaceException,
147                                                                             RepositoryException {
148     SessionProvider sessionProvider = isSystemSession ? WCMCoreUtils.getSystemSessionProvider()
149                                                      : WCMCoreUtils.getUserSessionProvider();
150     Session session = sessionProvider.getSession(workspace, WCMCoreUtils.getRepository());
151     QueryManager queryManager = session.getWorkspace().getQueryManager();
152     Query query = queryManager.createQuery(queryStatement, language);
153     QueryResult queryResult = query.execute();
154     List<E> dataList = new ArrayList<E>();
155     try {
156       NodeIterator nodeIterator = queryResult.getNodes();
157       RowIterator rowIterator = queryResult.getRows();
158       while (nodeIterator.hasNext()) {
159         Node node = nodeIterator.nextNode();
160         Row row = rowIterator.nextRow();
161         if (dataCreator != null && node != null) { 
162           E data = dataCreator.createData(node, row, null);
163           if (data != null) {
164             dataList.add(data);
165           }
166         }
167       }
168     } catch (RepositoryException e) {
169       if (LOG.isWarnEnabled()) {
170         LOG.warn(e.getMessage());
171       }
172     }
173     return dataList;
174   }
175   
176   public static <E> LazyPageList<E> createLazyPageList(QueryData queryData, int nodePerPage, 
177                                                        SearchDataCreator<E> dataCreator) {
178     return new LazyPageList<E>(queryData, nodePerPage, dataCreator);
179   }
180 
181   /**
182    * Search in JCR
183    * @param queryStatement
184    * @param workspace
185    * @param language
186    * @param isSystemSession
187    * @param filter
188    * @param dataCreator
189    * @param criteria
190    * @param <E>
191    * @return
192    * @throws RepositoryException
193    */
194   protected static <E> List<E> searchInJCR(String queryStatement,
195                                     String workspace,
196                                     String language,
197                                     boolean isSystemSession,
198                                     NodeSearchFilter filter,
199                                     SearchDataCreator<E> dataCreator,
200                                     QueryCriteria criteria) throws RepositoryException {
201     SessionProvider sessionProvider = isSystemSession ? WCMCoreUtils.getSystemSessionProvider() :
202             WCMCoreUtils.getUserSessionProvider();
203     Session session = sessionProvider.getSession(workspace, WCMCoreUtils.getRepository());
204     QueryManager queryManager = session.getWorkspace().getQueryManager();
205     Query query = queryManager.createQuery(queryStatement, language);
206 
207     long offset = criteria != null ? criteria.getOffset() : 0;
208     ((QueryImpl) query).setOffset(0);
209     ((QueryImpl) query).setLimit(offset + AbstractPageList.RESULT_SIZE_SEPARATOR + 1);
210     QueryResult result = query.execute();
211 
212     List<E> dataList = new ArrayList<>();
213 
214     try {
215       NodeIterator nodeIterator = result.getNodes();
216       RowIterator rowIterator = result.getRows();
217       while (nodeIterator.hasNext()) {
218         Node node = nodeIterator.nextNode();
219         Row row = rowIterator.nextRow();
220         if (filter != null) {
221           node = filter.filterNodeToDisplay(node);
222         }
223         if (dataCreator != null && node != null) {
224           E data = dataCreator.createData(node, row, null);
225           if (data != null) {
226             dataList.add(data);
227           }
228         }
229       }
230     } catch (RepositoryException e) {
231       if (LOG.isWarnEnabled()) {
232         LOG.warn(e.getMessage());
233       }
234     }
235 
236     return dataList;
237   }
238 
239   /**
240    *
241    * @param workspace
242    * @param isSystemSession
243    * @param filter
244    * @param dataCreator
245    * @param criteria
246    * @param <E>
247    * @return
248    * @throws RepositoryException
249    */
250   protected static <E> List<E> searchInES(String workspace,
251                                    Locale locale,
252                                    boolean isSystemSession,
253                                    NodeSearchFilter filter,
254                                    SearchDataCreator<E> dataCreator,
255                                    QueryCriteria criteria) throws RepositoryException {
256     SessionProvider sessionProvider = isSystemSession ? WCMCoreUtils.getSystemSessionProvider() :
257             WCMCoreUtils.getUserSessionProvider();
258     Session session = sessionProvider.getSession(workspace, WCMCoreUtils.getRepository());
259 
260     FileApplicationSearchServiceConnector fileSearchInternalServiceConnector = CommonsUtils.getService(FileApplicationSearchServiceConnector.class);
261     int offset = criteria != null ? (int) criteria.getOffset() : 0;
262     Collection<SearchResult> results = fileSearchInternalServiceConnector.appSearch(workspace,
263             criteria != null ? criteria.getSearchPath() : "",
264             locale,
265             criteria != null ? criteria.getKeyword() : "",
266             0,
267             offset + AbstractPageList.RESULT_SIZE_SEPARATOR + 1,
268             null,
269             null);
270 
271     List<E> filteredResults = new ArrayList<>();
272 
273     results.forEach(result -> {
274       EcmsSearchResult searchResult = (EcmsSearchResult) result;
275       // JCR score is calculated as (lucene score)*1000 , so we do the same thing for ES results to have a more accurate comparison
276       searchResult.setRelevancy(searchResult.getRelevancy() * 1000);
277       String nodePath = searchResult.getNodePath();
278       try {
279         Node node = (Node) session.getItem(nodePath);
280         if(node != null) {
281           if (filter != null) {
282             node = filter.filterNodeToDisplay(node);
283           }
284           filteredResults.add(dataCreator.createData(node, null, searchResult));
285         }
286       } catch (RepositoryException e) {
287         LOG.error("Cannot get node " + nodePath, e);
288       }
289     });
290 
291     return filteredResults;
292   }
293 }