@Override
  public Filter parse(JsonQueryParseContext parseContext)
      throws IOException, QueryParsingException {
    JsonParser jp = parseContext.jp();

    JsonToken token = jp.nextToken();
    assert token == JsonToken.FIELD_NAME;
    String fieldName = jp.getCurrentName();

    jp.nextToken();
    String value = jp.getText();
    // move to the next token (from VALUE)
    jp.nextToken();

    if (value == null) {
      throw new QueryParsingException(index, "No value specified for term filter");
    }

    Filter filter = null;
    MapperService.SmartNameFieldMappers smartNameFieldMappers =
        parseContext.smartFieldMappers(fieldName);
    if (smartNameFieldMappers != null) {
      if (smartNameFieldMappers.hasMapper()) {
        filter = smartNameFieldMappers.mapper().fieldFilter(value);
      }
    }
    if (filter == null) {
      filter = new TermFilter(new Term(fieldName, value));
    }
    filter = parseContext.cacheFilterIfPossible(filter);
    return wrapSmartNameFilter(filter, smartNameFieldMappers, parseContext.indexCache());
  }
  @Override
  public Query parse(JsonQueryParseContext parseContext) throws IOException, QueryParsingException {
    JsonParser jp = parseContext.jp();

    JsonToken token = jp.nextToken();
    assert token == JsonToken.FIELD_NAME;
    String fieldName = jp.getCurrentName();

    String from = null;
    String to = null;
    boolean includeLower = true;
    boolean includeUpper = true;
    float boost = 1.0f;

    String currentFieldName = null;
    while ((token = jp.nextToken()) != JsonToken.END_OBJECT) {
      if (token == JsonToken.FIELD_NAME) {
        currentFieldName = jp.getCurrentName();
      } else {
        if ("from".equals(currentFieldName)) {
          if (jp.getCurrentToken() == JsonToken.VALUE_NULL) {
            from = null;
          } else {
            from = jp.getText();
          }
        } else if ("to".equals(currentFieldName)) {
          if (jp.getCurrentToken() == JsonToken.VALUE_NULL) {
            to = null;
          } else {
            to = jp.getText();
          }
        } else if ("include_lower".equals(currentFieldName)) {
          if (token == JsonToken.VALUE_NUMBER_INT) {
            includeLower = jp.getIntValue() != 0;
          } else if (token == JsonToken.VALUE_STRING) {
            includeLower = Booleans.parseBoolean(jp.getText(), includeLower);
          } else {
            includeLower = token == JsonToken.VALUE_TRUE;
          }
        } else if ("include_upper".equals(currentFieldName)) {
          if (token == JsonToken.VALUE_NUMBER_INT) {
            includeUpper = jp.getIntValue() != 0;
          } else if (token == JsonToken.VALUE_STRING) {
            includeUpper = Booleans.parseBoolean(jp.getText(), includeUpper);
          } else {
            includeUpper = token == JsonToken.VALUE_TRUE;
          }
        } else if ("boost".equals(currentFieldName)) {
          if (token == JsonToken.VALUE_STRING) {
            boost = Float.parseFloat(jp.getText());
          } else {
            boost = jp.getFloatValue();
          }
        } else if ("gt".equals(currentFieldName)) {
          if (jp.getCurrentToken() == JsonToken.VALUE_NULL) {
            from = null;
          } else {
            from = jp.getText();
          }
          includeLower = false;
        } else if ("gte".equals(currentFieldName)) {
          if (jp.getCurrentToken() == JsonToken.VALUE_NULL) {
            from = null;
          } else {
            from = jp.getText();
          }
          includeLower = true;
        } else if ("lt".equals(currentFieldName)) {
          if (jp.getCurrentToken() == JsonToken.VALUE_NULL) {
            to = null;
          } else {
            to = jp.getText();
          }
          includeUpper = false;
        } else if ("lte".equals(currentFieldName)) {
          if (jp.getCurrentToken() == JsonToken.VALUE_NULL) {
            to = null;
          } else {
            to = jp.getText();
          }
          includeUpper = true;
        }
      }
    }

    // move to the next end object, to close the field name
    token = jp.nextToken();
    assert token == JsonToken.END_OBJECT;

    Query query = null;
    MapperService.SmartNameFieldMappers smartNameFieldMappers =
        parseContext.smartFieldMappers(fieldName);
    if (smartNameFieldMappers != null) {
      if (smartNameFieldMappers.hasMapper()) {
        query = smartNameFieldMappers.mapper().rangeQuery(from, to, includeLower, includeUpper);
      }
    }
    if (query == null) {
      query = new TermRangeQuery(fieldName, from, to, includeLower, includeUpper);
    }
    query.setBoost(boost);
    return wrapSmartNameQuery(query, smartNameFieldMappers, parseContext.indexCache());
  }