Package org.apache.solr.search

Source Code of org.apache.solr.search.QParser

/**
* 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.solr.search;

import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.MapSolrParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.request.SolrQueryRequest;

import java.util.*;

/**
* <b>Note: This API is experimental and may change in non backward-compatible ways in the future</b>
*
* @version $Id: QParser.java 1149032 2011-07-21 03:59:06Z koji $
*/
public abstract class QParser {
  protected String qstr;
  protected SolrParams params;
  protected SolrParams localParams;
  protected SolrQueryRequest req;
  protected int recurseCount;

  protected Query query;

  protected String stringIncludingLocalParams;   // the original query string including any local params
  protected boolean valFollowedParams;           // true if the value "qstr" followed the localParams
  protected int localParamsEnd;                  // the position one past where the localParams ended

  /**
   * Constructor for the QParser
   * @param qstr The part of the query string specific to this parser
   * @param localParams The set of parameters that are specific to this QParser.  See http://wiki.apache.org/solr/LocalParams
   * @param params The rest of the {@link org.apache.solr.common.params.SolrParams}
   * @param req The original {@link org.apache.solr.request.SolrQueryRequest}.
   */
  public QParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
    this.qstr = qstr;
    this.localParams = localParams;

    // insert tags into tagmap.
    // WARNING: the internal representation of tagged objects in the request context is
    // experimental and subject to change!
    if (localParams != null) {
      String tagStr = localParams.get(CommonParams.TAG);
      if (tagStr != null) {
        Map context = req.getContext();
        Map<String,Collection<Object>> tagMap = (Map<String, Collection<Object>>)req.getContext().get("tags");
        if (tagMap == null) {
          tagMap = new HashMap<String,Collection<Object>>();
          context.put("tags", tagMap);         
        }
        if (tagStr.indexOf(',') >= 0) {
          List<String> tags = StrUtils.splitSmart(tagStr, ',');
          for (String tag : tags) {
            addTag(tagMap, tag, this);
          }
        } else {
          addTag(tagMap, tagStr, this);
        }
      }
    }

    this.params = params;
    this.req = req;
  }


  private static void addTag(Map tagMap, Object key, Object val) {
    Collection lst = (Collection)tagMap.get(key);
    if (lst == null) {
      lst = new ArrayList(2);
      tagMap.put(key, lst);
    }
    lst.add(val);
  }

  /** Create and return the <code>Query</code> object represented by <code>qstr</code>
   * @see #getQuery()
   **/
  public abstract Query parse() throws ParseException;

  public SolrParams getLocalParams() {
    return localParams;
  }

  public void setLocalParams(SolrParams localParams) {
    this.localParams = localParams;
  }

  public SolrParams getParams() {
    return params;
  }

  public void setParams(SolrParams params) {
    this.params = params;
  }

  public SolrQueryRequest getReq() {
    return req;
  }

  public void setReq(SolrQueryRequest req) {
    this.req = req;
  }

  public String getString() {
    return qstr;
  }

  public void setString(String s) {
    this.qstr = s;
  }

  /**
   * Returns the resulting query from this QParser, calling parse() only the
   * first time and caching the Query result.
   *
   * @throws ParseException
   */
  public Query getQuery() throws ParseException {
    if (query==null) {
      query=parse();

      if (localParams != null) {
        String cacheStr = localParams.get(CommonParams.CACHE);
        if (cacheStr != null) {
          if (CommonParams.FALSE.equals(cacheStr)) {
            extendedQuery().setCache(false);
          } else if (CommonParams.TRUE.equals(cacheStr)) {
            extendedQuery().setCache(true);
          } else if ("sep".equals(cacheStr)) {
            extendedQuery().setCacheSep(true);
          }
        }

        int cost = localParams.getInt(CommonParams.COST, Integer.MIN_VALUE);
        if (cost != Integer.MIN_VALUE) {
          extendedQuery().setCost(cost);
        }
      }
    }
    return query;
  }

  // returns an extended query (and sets "query" to a new wrapped query if necessary)
  private ExtendedQuery extendedQuery() {
    if (query instanceof ExtendedQuery) {
      return (ExtendedQuery)query;
    } else {
      WrappedQuery wq = new WrappedQuery(query);
      query = wq;
      return wq;
    }
  }

  private void checkRecurse() throws ParseException {
    if (recurseCount++ >= 100) {
      throw new ParseException("Infinite Recursion detected parsing query '" + qstr + "'");
    }
  }

  // TODO: replace with a SolrParams that defaults to checking localParams first?
  // ideas..
  //   create params that satisfy field-specific overrides
  //   overrideable syntax $x=foo  (set global for limited scope) (invariants & security?)
  //                       $x+=foo (append to global for limited scope)

  /** check both local and global params */
  public String getParam(String name) {
    String val;
    if (localParams != null) {
      val = localParams.get(name);
      if (val != null) return val;
    }
    return params.get(name);
  }

  /** Create a new QParser for parsing an embedded sub-query */
  public QParser subQuery(String q, String defaultType) throws ParseException {
    checkRecurse();
    if (defaultType == null && localParams != null) {
      // if not passed, try and get the defaultType from local params
      defaultType = localParams.get(QueryParsing.DEFTYPE);
    }
    QParser nestedParser = getParser(q, defaultType, getReq());
    nestedParser.recurseCount = recurseCount;
    recurseCount--;
    return nestedParser;
  }


  /**
   * @param useGlobalParams look up sort, start, rows in global params if not in local params
   * @return the sort specification
   */
  public SortSpec getSort(boolean useGlobalParams) throws ParseException {
    getQuery(); // ensure query is parsed first

    String sortStr = null;
    String startS = null;
    String rowsS = null;

    if (localParams != null) {
      sortStr = localParams.get(CommonParams.SORT);
      startS = localParams.get(CommonParams.START);
      rowsS = localParams.get(CommonParams.ROWS);

      // if any of these parameters are present, don't go back to the global params
      if (sortStr != null || startS != null || rowsS != null) {
        useGlobalParams = false;
      }
    }

    if (useGlobalParams) {
      if (sortStr ==null) {
          sortStr = params.get(CommonParams.SORT);
      }
      if (startS==null) {
        startS = params.get(CommonParams.START);
      }
      if (rowsS==null) {
        rowsS = params.get(CommonParams.ROWS);
      }
    }

    int start = startS != null ? Integer.parseInt(startS) : 0;
    int rows = rowsS != null ? Integer.parseInt(rowsS) : 10;

    Sort sort = null;
    if( sortStr != null ) {
      sort = QueryParsing.parseSort(sortStr, req);
    }
    return new SortSpec( sort, start, rows );
  }

  public String[] getDefaultHighlightFields() {
    return new String[]{};
  }

  public Query getHighlightQuery() throws ParseException {
    Query query = getQuery();
    return query instanceof WrappedQuery ? ((WrappedQuery)query).getWrappedQuery() : query;
  }

  public void addDebugInfo(NamedList<Object> debugInfo) {
    debugInfo.add("QParser", this.getClass().getSimpleName());
  }

  /** Create a <code>QParser</code> to parse <code>qstr</code>,
   * assuming that the default query type is <code>defaultType</code>.
   * The query type may be overridden by local parameters in the query
   * string itself.  For example if defaultType=<code>"dismax"</code>
   * and qstr=<code>foo</code>, then the dismax query parser will be used
   * to parse and construct the query object.  However
   * if qstr=<code>{!prefix f=myfield}foo</code>
   * then the prefix query parser will be used.
   */
  public static QParser getParser(String qstr, String defaultType, SolrQueryRequest req) throws ParseException {
    // SolrParams localParams = QueryParsing.getLocalParams(qstr, req.getParams());

    String stringIncludingLocalParams = qstr;
    SolrParams localParams = null;
    SolrParams globalParams = req.getParams();
    boolean valFollowedParams = true;
    int localParamsEnd = -1;

    if (qstr != null && qstr.startsWith(QueryParsing.LOCALPARAM_START)) {
      Map<String, String> localMap = new HashMap<String, String>();
      localParamsEnd = QueryParsing.parseLocalParams(qstr, 0, localMap, globalParams);

      String val = localMap.get(QueryParsing.V);
      if (val != null) {
        // val was directly specified in localParams via v=<something> or v=$arg
        valFollowedParams = false;
      } else {
        // use the remainder of the string as the value
        valFollowedParams = true;
        val = qstr.substring(localParamsEnd);
        localMap.put(QueryParsing.V, val);
      }
      localParams = new MapSolrParams(localMap);
    }


    String type;
   
    if (localParams == null) {
      type = defaultType;
    } else {
      type = localParams.get(QueryParsing.TYPE,defaultType);
      qstr = localParams.get("v");
    }

    type = type==null ? QParserPlugin.DEFAULT_QTYPE : type;

    QParserPlugin qplug = req.getCore().getQueryPlugin(type);
    QParser parser =  qplug.createParser(qstr, localParams, req.getParams(), req);

    parser.stringIncludingLocalParams = stringIncludingLocalParams;
    parser.valFollowedParams = valFollowedParams;
    parser.localParamsEnd = localParamsEnd;
    return parser;
  }

}
TOP

Related Classes of org.apache.solr.search.QParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.