All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.browseengine.bobo.search.section.SectionSearchQueryPlanBuilder Maven / Gradle / Ivy

There is a newer version: 3.1.2
Show newest version
/**
 * This software is licensed to you under the Apache License, Version 2.0 (the
 * "Apache License").
 *
 * LinkedIn's contributions are made under the Apache License. If you contribute
 * to the Software, the contributions will be deemed to have been made under the
 * Apache License, unless you expressly indicate otherwise. Please do not make any
 * contributions that would be inconsistent with the Apache License.
 *
 * You may obtain a copy of the Apache License at http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, this software
 * distributed under the Apache License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Apache
 * License for the specific language governing permissions and limitations for the
 * software governed under the Apache License.
 *
 * © 2012 LinkedIn Corp. All Rights Reserved.  
 */

package com.browseengine.bobo.search.section;

import java.io.IOException;
import java.util.ArrayList;

import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;

/**
 *
 */
public class SectionSearchQueryPlanBuilder
{
  public static class TranslationException extends RuntimeException
  {
    private static final long serialVersionUID = 1L;

    public TranslationException(String message)
    {
      super(message);
    }
  }
  
  protected final IndexReader _reader;
  protected final MetaDataCacheProvider _cacheProvider;
  
  public SectionSearchQueryPlanBuilder(IndexReader reader)
  {
    _reader = reader;
    _cacheProvider = (reader instanceof MetaDataCacheProvider ? (MetaDataCacheProvider)reader : null);
  }
  
  /**
   * Gets a query plan for the given query.
   * It is assumed that query is already rewritten before this call.
   * @param query
   * @return SectionSearchQueryPlan
   * @throws IOException
   */
  public SectionSearchQueryPlan getPlan(Query query)
    throws IOException
  {
    if(query != null)
    {
      SectionSearchQueryPlan textSearchPlan = translate(query);
      
      if(!(textSearchPlan instanceof UnaryNotNode))
      {
        return textSearchPlan;
      }
    }
    return null;
  }
  
  /**
   * Translates a Lucence Query object to an SectionSearchQueryPlan 
   * @param query
   * @param reader
   * @return
   * @throws IOException
   */
  private SectionSearchQueryPlan translate(Query query)
    throws IOException
  {
    if(query != null)
    {
      if(query instanceof TermQuery)
      {
        return translateTermQuery((TermQuery) query);
      }
      else if(query instanceof PhraseQuery)
      {
        return translatePhraseQuery((PhraseQuery) query);
      }
      else if(query instanceof BooleanQuery)
      {
        return translateBooleanQuery((BooleanQuery) query);
      }
      else if(query instanceof MetaDataQuery)
      {
        MetaDataQuery mquery = (MetaDataQuery)query;
        MetaDataCache cache = (_cacheProvider != null ? _cacheProvider.get(mquery.getTerm()) : null);
        
        if(cache != null)
        {
          return ((MetaDataQuery)query).getPlan(cache);
        }
        else
        {
          return ((MetaDataQuery)query).getPlan(_reader);
        }
      }
      else
      {
        throw new TranslationException("unable to translate Query class: " + query.getClass().getName());
      }
    }
    return null;
  }
  
  private SectionSearchQueryPlan translateTermQuery(TermQuery query)
    throws IOException
  {
    return new TermNode(query.getTerm(), _reader);
  }

  private SectionSearchQueryPlan translatePhraseQuery(PhraseQuery query)
    throws IOException
  {
    Term[] terms = query.getTerms();
    TermNode[] nodes = new TermNode[terms.length];
    int[] positions = query.getPositions();
    for(int i = 0; i < terms.length; i++)
    {
      nodes[i] = new TermNode(terms[i], positions[i], _reader);
    }
    return new PhraseNode(nodes, _reader);
  }
  
  private SectionSearchQueryPlan translateBooleanQuery(BooleanQuery query)
    throws IOException
  {
    ArrayList requiredClauses = new ArrayList();
    ArrayList prohibitedClauses = new ArrayList();
    ArrayList optionalClauses = new ArrayList();
    BooleanClause[] clauses = query.getClauses();
    for(BooleanClause clause : clauses)
    {
      if(clause.isRequired())
      {
        requiredClauses.add(clause.getQuery());
      }
      else if(clause.isProhibited())
      {
        prohibitedClauses.add(clause.getQuery());
      }
      else
      {
        optionalClauses.add(clause.getQuery());
      }
    }
    
    SectionSearchQueryPlan positiveNode = null;
    SectionSearchQueryPlan negativeNode = null;
    
    if(requiredClauses.size() > 0)
    {
      if(requiredClauses.size() == 1)
      {
        positiveNode = translate(requiredClauses.get(0));
      }
      else
      {
        SectionSearchQueryPlan[] subqueries = translate(requiredClauses);
        if(subqueries != null && subqueries.length > 0) positiveNode = new AndNode(subqueries);
      }
    }
    else if(optionalClauses.size() > 0)
    {
      if(optionalClauses.size() == 1)
      {
        positiveNode = translate(optionalClauses.get(0));
      }
      else
      {
        SectionSearchQueryPlan[] subqueries = translate(optionalClauses);
        if(subqueries != null && subqueries.length > 0) positiveNode = new OrNode(subqueries);
      }
    }
    
    if(prohibitedClauses.size() > 0)
    {
      if(prohibitedClauses.size() == 1)
      {
        negativeNode = translate(prohibitedClauses.get(0));        
      }
      else
      {
        negativeNode = new OrNode(translate(prohibitedClauses));
      }
    }
    
    if(negativeNode == null)
    {
      return positiveNode;
    }
    else
    {
      if(positiveNode == null)
      {
        return new UnaryNotNode(negativeNode);
      }
      else
      {
        return new AndNotNode(positiveNode, negativeNode);
      }
    }
  }

  private SectionSearchQueryPlan[] translate(ArrayList queries)
    throws IOException
  {
    int size = queries.size();
    ArrayList result = new ArrayList(size);
    for(int i = 0; i < size; i++)
    {
      SectionSearchQueryPlan plan = translate(queries.get(i));
      if(plan != null) result.add(plan);
    }
    return result.toArray(new SectionSearchQueryPlan[result.size()]);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy