View Javadoc
1   package org.wikimedia.search.extra.regex;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import org.apache.lucene.index.Term;
7   import org.apache.lucene.search.BooleanClause.Occur;
8   import org.apache.lucene.search.BooleanQuery;
9   import org.apache.lucene.search.Query;
10  import org.apache.lucene.search.TermInSetQuery;
11  import org.apache.lucene.search.TermQuery;
12  import org.apache.lucene.util.BytesRef;
13  import org.wikimedia.search.extra.regex.expression.Expression;
14  
15  import com.google.common.collect.ImmutableSet;
16  
17  /**
18   * Transforms expressions to queries.
19   */
20  public class ExpressionToQueryTransformer implements Expression.Transformer<String, Query> {
21      private final String ngramField;
22  
23      public ExpressionToQueryTransformer(String ngramField) {
24          this.ngramField = ngramField;
25      }
26  
27      @Override
28      public Query alwaysTrue() {
29          throw new InvalidRegexException("Can't transform always true into a query.");
30      }
31  
32      @Override
33      public Query alwaysFalse() {
34          throw new InvalidRegexException("Can't transform always false into a query.");
35      }
36  
37      @Override
38      public Query leaf(String t) {
39          return new TermQuery(new Term(ngramField, t));
40      }
41  
42      @Override
43      public Query and(ImmutableSet<Query> js) {
44          BooleanQuery.Builder builder = new BooleanQuery.Builder();
45  
46          for (Query j : js) {
47              builder.add(j, Occur.FILTER);
48          }
49          return builder.build();
50      }
51  
52      @Override
53      public Query or(ImmutableSet<Query> js) {
54          // Array containing all terms if this is contains only term queries
55          boolean allTermQueries = true;
56          List<BytesRef> allTerms = null;
57          BooleanQuery.Builder builder = new BooleanQuery.Builder();
58          for (Query j : js) {
59              builder.add(j, Occur.SHOULD);
60              if (allTermQueries) {
61                  allTermQueries = j instanceof TermQuery;
62                  if (allTermQueries) {
63                      if (allTerms == null) {
64                          allTerms = new ArrayList<>(js.size());
65                      }
66                      allTerms.add(((TermQuery) j).getTerm().bytes());
67                  }
68              }
69          }
70          if (!allTermQueries) {
71              return builder.build();
72          }
73          assert allTerms != null;
74          return new TermInSetQuery(ngramField, allTerms);
75      }
76  }