Example #1
0
 static DocumentBuilderIndexedEntity<?> getDocumentBuilder(QueryBuildingContext queryContext) {
   final SearchFactoryImplementor factory = queryContext.getFactory();
   final Class<?> type = queryContext.getEntityType();
   EntityIndexBinder indexBinding = factory.getIndexBindingForEntity(type);
   if (indexBinding == null) {
     throw new AssertionFailure("Class in not indexed: " + type);
   }
   return indexBinding.getDocumentBuilder();
 }
  public Query createQuery(FieldContext fieldContext) {
    final Query perFieldQuery;
    final String fieldName = fieldContext.getField();

    /*
     * Store terms per position and detect if for a given position more than one term is present
     */
    TokenStream stream = null;
    boolean isMultiPhrase = false;
    Map<Integer, List<Term>> termsPerPosition = new HashMap<Integer, List<Term>>();
    final String sentence = phraseContext.getSentence();
    try {
      Reader reader = new StringReader(sentence);
      stream = queryContext.getQueryAnalyzer().tokenStream(fieldName, reader);

      CharTermAttribute termAttribute = stream.addAttribute(CharTermAttribute.class);
      PositionIncrementAttribute positionAttribute =
          stream.addAttribute(PositionIncrementAttribute.class);

      stream.reset();
      int position = -1; // start at -1 since we apply at least one increment
      List<Term> termsAtSamePosition = null;
      while (stream.incrementToken()) {
        int positionIncrement = 1;
        if (positionAttribute != null) {
          positionIncrement = positionAttribute.getPositionIncrement();
        }

        if (positionIncrement > 0) {
          position += positionIncrement;
          termsAtSamePosition = termsPerPosition.get(position);
        }

        if (termsAtSamePosition == null) {
          termsAtSamePosition = new ArrayList<Term>();
          termsPerPosition.put(position, termsAtSamePosition);
        }

        String termString = new String(termAttribute.buffer(), 0, termAttribute.length());
        termsAtSamePosition.add(new Term(fieldName, termString));
        if (termsAtSamePosition.size() > 1) {
          isMultiPhrase = true;
        }
      }
    } catch (IOException e) {
      throw new AssertionFailure("IOException while reading a string. Doh!", e);
    } finally {
      if (stream != null) {
        try {
          stream.end();
          stream.close();
        } catch (IOException e) {
          throw new AssertionFailure("IOException while reading a string. Doh!", e);
        }
      }
    }

    /*
     * Create the appropriate query depending on the conditions
     * note that a MultiPhraseQuery is needed if several terms share the same position
     * as it will do a OR and not a AND like PhraseQuery
     */
    final int size = termsPerPosition.size();
    if (size == 0) {
      perFieldQuery = new BooleanQuery.Builder().build();
    } else if (size <= 1) {
      final List<Term> terms = termsPerPosition.values().iterator().next();
      if (terms.size() == 1) {
        perFieldQuery = new TermQuery(terms.get(0));
      } else {
        BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();
        for (Term term : terms) {
          booleanQueryBuilder.add(new TermQuery(term), BooleanClause.Occur.SHOULD);
        }
        perFieldQuery = booleanQueryBuilder.build();
      }
    } else {
      if (isMultiPhrase) {
        MultiPhraseQuery query = new MultiPhraseQuery();
        query.setSlop(phraseContext.getSlop());
        for (Map.Entry<Integer, List<Term>> entry : termsPerPosition.entrySet()) {
          final List<Term> value = entry.getValue();
          query.add(value.toArray(new Term[value.size()]), entry.getKey());
        }
        perFieldQuery = query;
      } else {
        PhraseQuery query = new PhraseQuery();
        query.setSlop(phraseContext.getSlop());
        for (Map.Entry<Integer, List<Term>> entry : termsPerPosition.entrySet()) {
          final List<Term> value = entry.getValue();
          query.add(value.get(0), entry.getKey());
        }
        perFieldQuery = query;
      }
    }
    return fieldContext.getFieldCustomizer().setWrappedQuery(perFieldQuery).createQuery();
  }