/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.lucene.util;


import java.io.IOException;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.AnalyzerWrapper;
import org.apache.lucene.analysis.CannedBinaryTokenStream;
import org.apache.lucene.analysis.MockAnalyzer;
import org.apache.lucene.analysis.MockSynonymFilter;
import org.apache.lucene.analysis.MockTokenizer;
import org.apache.lucene.analysis.TokenFilter;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BoostAttribute;
import org.apache.lucene.search.BoostQuery;
import org.apache.lucene.search.MultiPhraseQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.SynonymQuery;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.spans.SpanNearQuery;
import org.apache.lucene.search.spans.SpanOrQuery;
import org.apache.lucene.search.spans.SpanQuery;
import org.apache.lucene.search.spans.SpanTermQuery;
import org.apache.lucene.util.automaton.CharacterRunAutomaton;
import org.apache.lucene.util.automaton.RegExp;

public class TestQueryBuilder extends LuceneTestCase {
  
  public void testTerm() {
    TermQuery expected = new TermQuery(new Term("field", "test"));
    QueryBuilder builder = new QueryBuilder(new MockAnalyzer(random()));
    assertEquals(expected, builder.createBooleanQuery("field", "test"));
  }
  
  public void testBoolean() {
    BooleanQuery.Builder expected = new BooleanQuery.Builder();
    expected.add(new TermQuery(new Term("field", "foo")), BooleanClause.Occur.SHOULD);
    expected.add(new TermQuery(new Term("field", "bar")), BooleanClause.Occur.SHOULD);
    QueryBuilder builder = new QueryBuilder(new MockAnalyzer(random()));
    assertEquals(expected.build(), builder.createBooleanQuery("field", "foo bar"));
  }
  
  public void testBooleanMust() {
    BooleanQuery.Builder expected = new BooleanQuery.Builder();
    expected.add(new TermQuery(new Term("field", "foo")), BooleanClause.Occur.MUST);
    expected.add(new TermQuery(new Term("field", "bar")), BooleanClause.Occur.MUST);
    QueryBuilder builder = new QueryBuilder(new MockAnalyzer(random()));
    assertEquals(expected.build(), builder.createBooleanQuery("field", "foo bar", BooleanClause.Occur.MUST));
  }
  
  public void testMinShouldMatchNone() {
    QueryBuilder builder = new QueryBuilder(new MockAnalyzer(random()));
    assertEquals(builder.createBooleanQuery("field", "one two three four"),
                 builder.createMinShouldMatchQuery("field", "one two three four", 0f));
  }
  
  public void testMinShouldMatchAll() {
    QueryBuilder builder = new QueryBuilder(new MockAnalyzer(random()));
    assertEquals(builder.createBooleanQuery("field", "one two three four", BooleanClause.Occur.MUST),
                 builder.createMinShouldMatchQuery("field", "one two three four", 1f));
  }
  
  public void testMinShouldMatch() {
    BooleanQuery.Builder expectedB = new BooleanQuery.Builder();
    expectedB.add(new TermQuery(new Term("field", "one")), BooleanClause.Occur.SHOULD);
    expectedB.add(new TermQuery(new Term("field", "two")), BooleanClause.Occur.SHOULD);
    expectedB.add(new TermQuery(new Term("field", "three")), BooleanClause.Occur.SHOULD);
    expectedB.add(new TermQuery(new Term("field", "four")), BooleanClause.Occur.SHOULD);
    expectedB.setMinimumNumberShouldMatch(0);
    Query expected = expectedB.build();

    QueryBuilder builder = new QueryBuilder(new MockAnalyzer(random()));
    //assertEquals(expected, builder.createMinShouldMatchQuery("field", "one two three four", 0.1f));
    //assertEquals(expected, builder.createMinShouldMatchQuery("field", "one two three four", 0.24f));
    
    expectedB.setMinimumNumberShouldMatch(1);
    expected = expectedB.build();
    assertEquals(expected, builder.createMinShouldMatchQuery("field", "one two three four", 0.25f));
    assertEquals(expected, builder.createMinShouldMatchQuery("field", "one two three four", 0.49f));

    expectedB.setMinimumNumberShouldMatch(2);
    expected = expectedB.build();
    assertEquals(expected, builder.createMinShouldMatchQuery("field", "one two three four", 0.5f));
    assertEquals(expected, builder.createMinShouldMatchQuery("field", "one two three four", 0.74f));
    
    expectedB.setMinimumNumberShouldMatch(3);
    expected = expectedB.build();
    assertEquals(expected, builder.createMinShouldMatchQuery("field", "one two three four", 0.75f));
    assertEquals(expected, builder.createMinShouldMatchQuery("field", "one two three four", 0.99f));
  }
  
  public void testPhraseQueryPositionIncrements() throws Exception {
    PhraseQuery.Builder pqBuilder = new PhraseQuery.Builder();
    pqBuilder.add(new Term("field", "1"), 0);
    pqBuilder.add(new Term("field", "2"), 2);
    PhraseQuery expected = pqBuilder.build();
    CharacterRunAutomaton stopList = new CharacterRunAutomaton(new RegExp("[sS][tT][oO][pP]").toAutomaton());

    Analyzer analyzer = new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false, stopList);

    QueryBuilder builder = new QueryBuilder(analyzer);
    assertEquals(expected, builder.createPhraseQuery("field", "1 stop 2"));
  }
  
  public void testEmpty() {
    QueryBuilder builder = new QueryBuilder(new MockAnalyzer(random()));
    assertNull(builder.createBooleanQuery("field", ""));
  }
  
  /** adds synonym of "dog" for "dogs", and synonym of "cavy" for "guinea pig". */
  static class MockSynonymAnalyzer extends Analyzer {
    @Override
    protected TokenStreamComponents createComponents(String fieldName) {
      MockTokenizer tokenizer = new MockTokenizer();
      return new TokenStreamComponents(tokenizer, new MockSynonymFilter(tokenizer));
    }
  }
  
  /** simple synonyms test */
  public void testSynonyms() throws Exception {
    SynonymQuery expected = new SynonymQuery.Builder("field")
        .addTerm(new Term("field", "dogs"))
        .addTerm(new Term("field", "dog"))
        .build();
    QueryBuilder builder = new QueryBuilder(new MockSynonymAnalyzer());
    assertEquals(expected, builder.createBooleanQuery("field", "dogs"));
    assertEquals(expected, builder.createPhraseQuery("field", "dogs"));
    assertEquals(expected, builder.createBooleanQuery("field", "dogs", BooleanClause.Occur.MUST));
    assertEquals(expected, builder.createPhraseQuery("field", "dogs"));
  }
  
  /** forms multiphrase query */
  public void testSynonymsPhrase() throws Exception {
    MultiPhraseQuery.Builder expectedBuilder = new MultiPhraseQuery.Builder();
    expectedBuilder.add(new Term("field", "old"));
    expectedBuilder.add(new Term[] { new Term("field", "dogs"), new Term("field", "dog") });
    QueryBuilder builder = new QueryBuilder(new MockSynonymAnalyzer());
    assertEquals(expectedBuilder.build(), builder.createPhraseQuery("field", "old dogs"));
  }

  /** forms graph query */
  public void testMultiWordSynonymsPhrase() throws Exception {
    SpanNearQuery expectedNear = SpanNearQuery.newOrderedNearQuery("field")
        .addClause(new SpanTermQuery(new Term("field", "guinea")))
        .addClause(new SpanTermQuery(new Term("field", "pig")))
        .setSlop(0)
        .build();

    SpanTermQuery expectedTerm = new SpanTermQuery(new Term("field", "cavy"));

    QueryBuilder queryBuilder = new QueryBuilder(new MockSynonymAnalyzer());
    assertEquals(new SpanOrQuery(new SpanQuery[]{expectedNear, expectedTerm}),
        queryBuilder.createPhraseQuery("field", "guinea pig"));
  }

  public void testMultiWordSynonymsPhraseWithSlop() throws Exception {
    BooleanQuery expected = new BooleanQuery.Builder()
        .add(new PhraseQuery.Builder().setSlop(4)
                .add(new Term("field", "guinea")).add(new Term("field", "pig")).build(), BooleanClause.Occur.SHOULD)
        .add(new TermQuery(new Term("field", "cavy")), BooleanClause.Occur.SHOULD)
        .build();
    QueryBuilder queryBuilder = new QueryBuilder(new MockSynonymAnalyzer());
    assertEquals(expected,
        queryBuilder.createPhraseQuery("field", "guinea pig", 4));
  }

  /** forms graph query */
  public void testMultiWordSynonymsBoolean() throws Exception {
    for (BooleanClause.Occur occur : new BooleanClause.Occur[] {BooleanClause.Occur.SHOULD, BooleanClause.Occur.MUST}) {
      Query syn1 = new BooleanQuery.Builder()
          .add(new TermQuery(new Term("field", "guinea")), BooleanClause.Occur.MUST)
          .add(new TermQuery(new Term("field", "pig")), BooleanClause.Occur.MUST)
          .build();
      Query syn2 = new TermQuery(new Term("field", "cavy"));

      BooleanQuery synQuery = new BooleanQuery.Builder()
          .add(syn1, BooleanClause.Occur.SHOULD)
          .add(syn2, BooleanClause.Occur.SHOULD)
          .build();

      BooleanQuery expectedGraphQuery = new BooleanQuery.Builder()
          .add(synQuery, occur)
          .build();

      QueryBuilder queryBuilder = new QueryBuilder(new MockSynonymAnalyzer());
      assertEquals(expectedGraphQuery, queryBuilder.createBooleanQuery("field", "guinea pig", occur));

      BooleanQuery expectedBooleanQuery = new BooleanQuery.Builder()
          .add(synQuery, occur)
          .add(new TermQuery(new Term("field", "story")), occur)
          .build();
      assertEquals(expectedBooleanQuery, queryBuilder.createBooleanQuery("field", "guinea pig story", occur));

      expectedBooleanQuery = new BooleanQuery.Builder()
          .add(new TermQuery(new Term("field", "the")), occur)
          .add(synQuery, occur)
          .add(new TermQuery(new Term("field", "story")), occur)
          .build();
      assertEquals(expectedBooleanQuery, queryBuilder.createBooleanQuery("field", "the guinea pig story", occur));

      expectedBooleanQuery = new BooleanQuery.Builder()
          .add(new TermQuery(new Term("field", "the")), occur)
          .add(synQuery, occur)
          .add(new TermQuery(new Term("field", "story")), occur)
          .add(synQuery, occur)
          .build();
      assertEquals(expectedBooleanQuery, queryBuilder.createBooleanQuery("field", "the guinea pig story guinea pig", occur));
    }
  }

  /** forms graph query */
  public void testMultiWordPhraseSynonymsBoolean() throws Exception {
    for (BooleanClause.Occur occur : new BooleanClause.Occur[] {BooleanClause.Occur.SHOULD, BooleanClause.Occur.MUST}) {
      Query syn1 = new PhraseQuery.Builder()
          .add(new Term("field", "guinea"))
          .add(new Term("field", "pig"))
          .build();
      Query syn2 = new TermQuery(new Term("field", "cavy"));

      BooleanQuery synQuery = new BooleanQuery.Builder()
          .add(syn1, BooleanClause.Occur.SHOULD)
          .add(syn2, BooleanClause.Occur.SHOULD)
          .build();
      BooleanQuery expectedGraphQuery = new BooleanQuery.Builder()
          .add(synQuery, occur)
          .build();
      QueryBuilder queryBuilder = new QueryBuilder(new MockSynonymAnalyzer());
      queryBuilder.setAutoGenerateMultiTermSynonymsPhraseQuery(true);
      assertEquals(expectedGraphQuery, queryBuilder.createBooleanQuery("field", "guinea pig", occur));

      BooleanQuery expectedBooleanQuery = new BooleanQuery.Builder()
          .add(synQuery, occur)
          .add(new TermQuery(new Term("field", "story")), occur)
          .build();
      assertEquals(expectedBooleanQuery, queryBuilder.createBooleanQuery("field", "guinea pig story", occur));

      expectedBooleanQuery = new BooleanQuery.Builder()
          .add(new TermQuery(new Term("field", "the")), occur)
          .add(synQuery, occur)
          .add(new TermQuery(new Term("field", "story")), occur)
          .build();
      assertEquals(expectedBooleanQuery, queryBuilder.createBooleanQuery("field", "the guinea pig story", occur));

      expectedBooleanQuery = new BooleanQuery.Builder()
          .add(new TermQuery(new Term("field", "the")), occur)
          .add(synQuery, occur)
          .add(new TermQuery(new Term("field", "story")), occur)
          .add(synQuery, occur)
          .build();
      assertEquals(expectedBooleanQuery, queryBuilder.createBooleanQuery("field", "the guinea pig story guinea pig", occur));
    }
  }

  protected static class SimpleCJKTokenizer extends Tokenizer {
    private CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);

    public SimpleCJKTokenizer() {
      super();
    }

    @Override
    public final boolean incrementToken() throws IOException {
      int ch = input.read();
      if (ch < 0)
        return false;
      clearAttributes();
      termAtt.setEmpty().append((char) ch);
      return true;
    }
  }
  
  private static class SimpleCJKAnalyzer extends Analyzer {
    @Override
    public TokenStreamComponents createComponents(String fieldName) {
      return new TokenStreamComponents(new SimpleCJKTokenizer());
    }
  }
  
  public void testCJKTerm() throws Exception {
    // individual CJK chars as terms
    SimpleCJKAnalyzer analyzer = new SimpleCJKAnalyzer(); 
    
    BooleanQuery.Builder expected = new BooleanQuery.Builder();
    expected.add(new TermQuery(new Term("field", "中")), BooleanClause.Occur.SHOULD);
    expected.add(new TermQuery(new Term("field", "国")), BooleanClause.Occur.SHOULD);
    
    QueryBuilder builder = new QueryBuilder(analyzer);
    assertEquals(expected.build(), builder.createBooleanQuery("field", "中国"));
  }
  
  public void testCJKPhrase() throws Exception {
    // individual CJK chars as terms
    SimpleCJKAnalyzer analyzer = new SimpleCJKAnalyzer();
    
    PhraseQuery expected = new PhraseQuery("field", "中", "国");
    
    QueryBuilder builder = new QueryBuilder(analyzer);
    assertEquals(expected, builder.createPhraseQuery("field", "中国"));
  }
  
  public void testCJKSloppyPhrase() throws Exception {
    // individual CJK chars as terms
    SimpleCJKAnalyzer analyzer = new SimpleCJKAnalyzer();
    
    PhraseQuery expected = new PhraseQuery(3, "field", "中", "国");
    
    QueryBuilder builder = new QueryBuilder(analyzer);
    assertEquals(expected, builder.createPhraseQuery("field", "中国", 3));
  }
  
  /**
   * adds synonym of "國" for "国".
   */
  protected static class MockCJKSynonymFilter extends TokenFilter {
    CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
    PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
    boolean addSynonym = false;
    
    public MockCJKSynonymFilter(TokenStream input) {
      super(input);
    }

    @Override
    public final boolean incrementToken() throws IOException {
      if (addSynonym) { // inject our synonym
        clearAttributes();
        termAtt.setEmpty().append("國");
        posIncAtt.setPositionIncrement(0);
        addSynonym = false;
        return true;
      }
      
      if (input.incrementToken()) {
        addSynonym = termAtt.toString().equals("国");
        return true;
      } else {
        return false;
      }
    } 
  }
  
  static class MockCJKSynonymAnalyzer extends Analyzer {
    @Override
    protected TokenStreamComponents createComponents(String fieldName) {
      Tokenizer tokenizer = new SimpleCJKTokenizer();
      return new TokenStreamComponents(tokenizer, new MockCJKSynonymFilter(tokenizer));
    }
  }
  
  /** simple CJK synonym test */
  public void testCJKSynonym() throws Exception {
    SynonymQuery expected = new SynonymQuery.Builder("field")
        .addTerm(new Term("field", "国"))
        .addTerm(new Term("field", "國"))
        .build();
    QueryBuilder builder = new QueryBuilder(new MockCJKSynonymAnalyzer());
    assertEquals(expected, builder.createBooleanQuery("field", "国"));
    assertEquals(expected, builder.createPhraseQuery("field", "国"));
    assertEquals(expected, builder.createBooleanQuery("field", "国", BooleanClause.Occur.MUST));
  }
  
  /** synonyms with default OR operator */
  public void testCJKSynonymsOR() throws Exception {
    BooleanQuery.Builder expected = new BooleanQuery.Builder();
    expected.add(new TermQuery(new Term("field", "中")), BooleanClause.Occur.SHOULD);
    SynonymQuery inner = new SynonymQuery.Builder("field")
        .addTerm(new Term("field", "国"))
        .addTerm(new Term("field", "國"))
        .build();
    expected.add(inner, BooleanClause.Occur.SHOULD);
    QueryBuilder builder = new QueryBuilder(new MockCJKSynonymAnalyzer());
    assertEquals(expected.build(), builder.createBooleanQuery("field", "中国"));
  }
  
  /** more complex synonyms with default OR operator */
  public void testCJKSynonymsOR2() throws Exception {
    BooleanQuery.Builder expected = new BooleanQuery.Builder();
    expected.add(new TermQuery(new Term("field", "中")), BooleanClause.Occur.SHOULD);
    SynonymQuery inner = new SynonymQuery.Builder("field")
        .addTerm(new Term("field", "国"))
        .addTerm(new Term("field", "國"))
        .build();
    expected.add(inner, BooleanClause.Occur.SHOULD);
    SynonymQuery inner2 = new SynonymQuery.Builder("field")
        .addTerm(new Term("field", "国"))
        .addTerm(new Term("field", "國"))
        .build();
    expected.add(inner2, BooleanClause.Occur.SHOULD);
    QueryBuilder builder = new QueryBuilder(new MockCJKSynonymAnalyzer());
    assertEquals(expected.build(), builder.createBooleanQuery("field", "中国国"));
  }
  
  /** synonyms with default AND operator */
  public void testCJKSynonymsAND() throws Exception {
    BooleanQuery.Builder expected = new BooleanQuery.Builder();
    expected.add(new TermQuery(new Term("field", "中")), BooleanClause.Occur.MUST);
    SynonymQuery inner = new SynonymQuery.Builder("field")
        .addTerm(new Term("field", "国"))
        .addTerm(new Term("field", "國"))
        .build();
    expected.add(inner, BooleanClause.Occur.MUST);
    QueryBuilder builder = new QueryBuilder(new MockCJKSynonymAnalyzer());
    assertEquals(expected.build(), builder.createBooleanQuery("field", "中国", BooleanClause.Occur.MUST));
  }
  
  /** more complex synonyms with default AND operator */
  public void testCJKSynonymsAND2() throws Exception {
    BooleanQuery.Builder expected = new BooleanQuery.Builder();
    expected.add(new TermQuery(new Term("field", "中")), BooleanClause.Occur.MUST);
    SynonymQuery inner = new SynonymQuery.Builder("field")
        .addTerm(new Term("field", "国"))
        .addTerm(new Term("field", "國"))
        .build();
    expected.add(inner, BooleanClause.Occur.MUST);
    SynonymQuery inner2 = new SynonymQuery.Builder("field")
        .addTerm(new Term("field", "国"))
        .addTerm(new Term("field", "國"))
        .build();
    expected.add(inner2, BooleanClause.Occur.MUST);
    QueryBuilder builder = new QueryBuilder(new MockCJKSynonymAnalyzer());
    assertEquals(expected.build(), builder.createBooleanQuery("field", "中国国", BooleanClause.Occur.MUST));
  }
  
  /** forms multiphrase query */
  public void testCJKSynonymsPhrase() throws Exception {
    MultiPhraseQuery.Builder expectedBuilder = new MultiPhraseQuery.Builder();
    expectedBuilder.add(new Term("field", "中"));
    expectedBuilder.add(new Term[] { new Term("field", "国"), new Term("field", "國")});
    QueryBuilder builder = new QueryBuilder(new MockCJKSynonymAnalyzer());
    assertEquals(expectedBuilder.build(), builder.createPhraseQuery("field", "中国"));
    expectedBuilder.setSlop(3);
    assertEquals(expectedBuilder.build(), builder.createPhraseQuery("field", "中国", 3));
  }

  public void testNoTermAttribute() {
    //Can't use MockTokenizer because it adds TermAttribute and we don't want that
    Analyzer analyzer = new Analyzer() {
      @Override
      protected TokenStreamComponents createComponents(String fieldName) {
        return new TokenStreamComponents(
            new Tokenizer() {
              boolean wasReset = false;
              @Override
              public void reset() throws IOException {
                super.reset();
                assertFalse(wasReset);
                wasReset = true;
              }

              @Override
              public boolean incrementToken() throws IOException {
                assertTrue(wasReset);
                return false;
              }
            }
        );
      }
    };
    QueryBuilder builder = new QueryBuilder(analyzer);
    assertNull(builder.createBooleanQuery("field", "whatever"));
  }

  public void testMaxBooleanClause() throws Exception {
    int size = 34;
    CannedBinaryTokenStream.BinaryToken[] tokens = new CannedBinaryTokenStream.BinaryToken[size];
    BytesRef term1 = new BytesRef("ff");
    BytesRef term2 = new BytesRef("f");
    for (int i = 0; i < size;) {
      if (i % 2 == 0) {
        tokens[i] = new CannedBinaryTokenStream.BinaryToken(term2, 1, 1);
        tokens[i + 1] = new CannedBinaryTokenStream.BinaryToken(term1, 0, 2);
        i += 2;
      } else {
        tokens[i] = new CannedBinaryTokenStream.BinaryToken(term2, 1, 1);
        i ++;
      }
    }
    QueryBuilder qb = new QueryBuilder(null);
    try (TokenStream ts = new CannedBinaryTokenStream(tokens)) {
      expectThrows(BooleanQuery.TooManyClauses.class, () -> qb.analyzeGraphBoolean("", ts, BooleanClause.Occur.MUST));
    }
    try (TokenStream ts = new CannedBinaryTokenStream(tokens)) {
      expectThrows(BooleanQuery.TooManyClauses.class, () -> qb.analyzeGraphBoolean("", ts, BooleanClause.Occur.SHOULD));
    }
    try (TokenStream ts = new CannedBinaryTokenStream(tokens)) {
      expectThrows(BooleanQuery.TooManyClauses.class, () -> qb.analyzeGraphPhrase(ts, "", 0));
    }
  }

  private static final class MockBoostTokenFilter extends TokenFilter {

    final BoostAttribute boostAtt = addAttribute(BoostAttribute.class);
    final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);

    protected MockBoostTokenFilter(TokenStream input) {
      super(input);
    }

    @Override
    public boolean incrementToken() throws IOException {
      if (input.incrementToken() == false) {
        return false;
      }
      if (termAtt.length() == 3) {
        boostAtt.setBoost(0.5f);
      }
      return true;
    }
  }

  public void testTokenStreamBoosts() {
    Analyzer msa = new MockSynonymAnalyzer();
    Analyzer a = new AnalyzerWrapper(msa.getReuseStrategy()) {
      @Override
      protected Analyzer getWrappedAnalyzer(String fieldName) {
        return msa;
      }
      @Override
      protected TokenStreamComponents wrapComponents(String fieldName, TokenStreamComponents components) {
        return new TokenStreamComponents(components.getSource(), new MockBoostTokenFilter(components.getTokenStream()));
      }
    };

    QueryBuilder builder = new QueryBuilder(a);
    Query q = builder.createBooleanQuery("field", "hot dogs");
    Query expected = new BooleanQuery.Builder()
        .add(new BoostQuery(new TermQuery(new Term("field", "hot")), 0.5f), BooleanClause.Occur.SHOULD)
        .add(new SynonymQuery.Builder("field")
            .addTerm(new Term("field", "dogs"))
            .addTerm(new Term("field", "dog"), 0.5f)
            .build(), BooleanClause.Occur.SHOULD)
        .build();

    assertEquals(expected, q);
  }
}
