View Javadoc

1   package org.appfuse.dao.hibernate;
2   
3   import java.util.Collection;
4   import java.util.HashSet;
5   
6   import org.apache.commons.logging.Log;
7   import org.apache.commons.logging.LogFactory;
8   import org.apache.lucene.analysis.Analyzer;
9   import org.apache.lucene.index.FieldInfo;
10  import org.apache.lucene.index.IndexReader;
11  import org.apache.lucene.queryParser.MultiFieldQueryParser;
12  import org.apache.lucene.queryParser.ParseException;
13  import org.apache.lucene.search.MatchAllDocsQuery;
14  import org.apache.lucene.search.Query;
15  import org.apache.lucene.util.ReaderUtil;
16  import org.apache.lucene.util.Version;
17  import org.hibernate.Session;
18  import org.hibernate.search.FullTextSession;
19  import org.hibernate.search.MassIndexer;
20  import org.hibernate.search.Search;
21  import org.hibernate.search.SearchFactory;
22  import org.hibernate.search.indexes.IndexReaderAccessor;
23  
24  /**
25   * Utility class to generate lucene queries for hibernate search and perform full reindexing.
26   *
27   * @author jgarcia
28   */
29  class HibernateSearchTools {
30      protected static final Log log = LogFactory.getLog(HibernateSearchTools.class);
31  
32      /**
33       * Generates a lucene query to search for a given term in all the indexed fields of a class
34       *
35       * @param searchTerm the term to search for
36       * @param searchedEntity the class searched
37       * @param sess the hibernate session
38       * @param defaultAnalyzer the default analyzer for parsing the search terms
39       * @return
40       * @throws ParseException
41       */
42      public static Query generateQuery(String searchTerm, Class searchedEntity, Session sess, Analyzer defaultAnalyzer) throws ParseException {
43          Query qry = null;
44  
45          if (searchTerm.equals("*")) {
46              qry = new MatchAllDocsQuery();
47          } else {
48              // Search in all indexed fields
49  
50              IndexReaderAccessor readerAccessor = null;
51              IndexReader reader = null;
52              try {
53                  FullTextSession txtSession = Search.getFullTextSession(sess);
54  
55                  // obtain analyzer to parse the query:
56                  Analyzer analyzer;
57                  if (searchedEntity == null) {
58                      analyzer = defaultAnalyzer;
59                  } else {
60                      analyzer = txtSession.getSearchFactory().getAnalyzer(searchedEntity);
61                  }
62  
63                  // search on all indexed fields: generate field list, removing internal hibernate search field name: _hibernate_class
64                  // TODO: possible improvement: cache the fields of each entity
65                  SearchFactory searchFactory = txtSession.getSearchFactory();
66                  readerAccessor = searchFactory.getIndexReaderAccessor();
67                  reader = readerAccessor.open(searchedEntity);
68                  Collection<String> fieldNames = new HashSet<>();
69                  for (FieldInfo fieldInfo : ReaderUtil.getMergedFieldInfos(reader)) {
70                      if (fieldInfo.isIndexed) {
71                          fieldNames.add(fieldInfo.name);
72                      }
73                  }
74                  fieldNames.remove("_hibernate_class");
75                  String[] fnames = new String[0];
76                  fnames = fieldNames.toArray(fnames);
77  
78                  // To search on all fields, search the term in all fields
79                  String[] queries = new String[fnames.length];
80                  for (int i = 0; i < queries.length; ++i) {
81                      queries[i] = searchTerm;
82                  }
83  
84                  qry = MultiFieldQueryParser.parse(Version.LUCENE_36, queries, fnames, analyzer);
85              } finally {
86                  if (readerAccessor != null && reader != null) {
87                      readerAccessor.close(reader);
88                  }
89              }
90          }
91          return qry;
92      }
93  
94      /**
95       * Regenerates the index for a given class
96       *
97       * @param clazz the class
98       * @param sess the hibernate session
99       */
100     public static void reindex(Class clazz, Session sess) {
101         FullTextSession txtSession = Search.getFullTextSession(sess);
102         MassIndexer massIndexer = txtSession.createIndexer(clazz);
103         try {
104             massIndexer.startAndWait();
105         } catch (InterruptedException e) {
106             log.error("mass reindexing interrupted: " + e.getMessage());
107         } finally {
108             txtSession.flushToIndexes();
109         }
110     }
111 
112     /**
113      * Regenerates all the indexed class indexes
114      *
115      * @param async true if the reindexing will be done as a background thread
116      * @param sess the hibernate session
117      */
118     public static void reindexAll(boolean async, Session sess) {
119         FullTextSession txtSession = Search.getFullTextSession(sess);
120         MassIndexer massIndexer = txtSession.createIndexer();
121         massIndexer.purgeAllOnStart(true);
122         try {
123             if (!async) {
124                 massIndexer.startAndWait();
125             } else {
126                 massIndexer.start();
127             }
128         } catch (InterruptedException e) {
129             log.error("mass reindexing interrupted: " + e.getMessage());
130         } finally {
131             txtSession.flushToIndexes();
132         }
133     }
134 }