private AbstractDistanceScoreFunction parseDateVariable(
      XContentParser parser,
      QueryShardContext context,
      DateFieldMapper.DateFieldType dateFieldType,
      MultiValueMode mode)
      throws IOException {
    XContentParser.Token token;
    String parameterName = null;
    String scaleString = null;
    String originString = null;
    String offsetString = "0d";
    double decay = 0.5;
    while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
      if (token == XContentParser.Token.FIELD_NAME) {
        parameterName = parser.currentName();
      } else if (DecayFunctionBuilder.SCALE.equals(parameterName)) {
        scaleString = parser.text();
      } else if (DecayFunctionBuilder.ORIGIN.equals(parameterName)) {
        originString = parser.text();
      } else if (DecayFunctionBuilder.DECAY.equals(parameterName)) {
        decay = parser.doubleValue();
      } else if (DecayFunctionBuilder.OFFSET.equals(parameterName)) {
        offsetString = parser.text();
      } else {
        throw new ElasticsearchParseException("parameter [{}] not supported!", parameterName);
      }
    }
    long origin;
    if (originString == null) {
      origin = context.nowInMillis();
    } else {
      origin = dateFieldType.parseToMilliseconds(originString, false, null, null);
    }

    if (scaleString == null) {
      throw new ElasticsearchParseException(
          "[{}] must be set for date fields.", DecayFunctionBuilder.SCALE);
    }
    TimeValue val =
        TimeValue.parseTimeValue(
            scaleString,
            TimeValue.timeValueHours(24),
            DecayFunctionParser.class.getSimpleName() + ".scale");
    double scale = val.getMillis();
    val =
        TimeValue.parseTimeValue(
            offsetString,
            TimeValue.timeValueHours(24),
            DecayFunctionParser.class.getSimpleName() + ".offset");
    double offset = val.getMillis();
    IndexNumericFieldData numericFieldData = context.getForField(dateFieldType);
    return new NumericFieldDataScoreFunction(
        origin, scale, decay, offset, getDecayFunction(), numericFieldData, mode);
  }
 private AbstractDistanceScoreFunction parseNumberVariable(
     XContentParser parser,
     QueryShardContext context,
     NumberFieldMapper.NumberFieldType fieldType,
     MultiValueMode mode)
     throws IOException {
   XContentParser.Token token;
   String parameterName = null;
   double scale = 0;
   double origin = 0;
   double decay = 0.5;
   double offset = 0.0d;
   boolean scaleFound = false;
   boolean refFound = false;
   while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
     if (token == XContentParser.Token.FIELD_NAME) {
       parameterName = parser.currentName();
     } else if (DecayFunctionBuilder.SCALE.equals(parameterName)) {
       scale = parser.doubleValue();
       scaleFound = true;
     } else if (DecayFunctionBuilder.DECAY.equals(parameterName)) {
       decay = parser.doubleValue();
     } else if (DecayFunctionBuilder.ORIGIN.equals(parameterName)) {
       origin = parser.doubleValue();
       refFound = true;
     } else if (DecayFunctionBuilder.OFFSET.equals(parameterName)) {
       offset = parser.doubleValue();
     } else {
       throw new ElasticsearchParseException("parameter [{}] not supported!", parameterName);
     }
   }
   if (!scaleFound || !refFound) {
     throw new ElasticsearchParseException(
         "both [{}] and [{}] must be set for numeric fields.",
         DecayFunctionBuilder.SCALE,
         DecayFunctionBuilder.ORIGIN);
   }
   IndexNumericFieldData numericFieldData = context.getForField(fieldType);
   return new NumericFieldDataScoreFunction(
       origin, scale, decay, offset, getDecayFunction(), numericFieldData, mode);
 }
 private AbstractDistanceScoreFunction parseGeoVariable(
     XContentParser parser,
     QueryShardContext context,
     BaseGeoPointFieldMapper.GeoPointFieldType fieldType,
     MultiValueMode mode)
     throws IOException {
   XContentParser.Token token;
   String parameterName = null;
   GeoPoint origin = new GeoPoint();
   String scaleString = null;
   String offsetString = "0km";
   double decay = 0.5;
   while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
     if (token == XContentParser.Token.FIELD_NAME) {
       parameterName = parser.currentName();
     } else if (DecayFunctionBuilder.SCALE.equals(parameterName)) {
       scaleString = parser.text();
     } else if (DecayFunctionBuilder.ORIGIN.equals(parameterName)) {
       origin = GeoUtils.parseGeoPoint(parser);
     } else if (DecayFunctionBuilder.DECAY.equals(parameterName)) {
       decay = parser.doubleValue();
     } else if (DecayFunctionBuilder.OFFSET.equals(parameterName)) {
       offsetString = parser.text();
     } else {
       throw new ElasticsearchParseException("parameter [{}] not supported!", parameterName);
     }
   }
   if (origin == null || scaleString == null) {
     throw new ElasticsearchParseException(
         "[{}] and [{}] must be set for geo fields.",
         DecayFunctionBuilder.ORIGIN,
         DecayFunctionBuilder.SCALE);
   }
   double scale = DistanceUnit.DEFAULT.parse(scaleString, DistanceUnit.DEFAULT);
   double offset = DistanceUnit.DEFAULT.parse(offsetString, DistanceUnit.DEFAULT);
   IndexGeoPointFieldData indexFieldData = context.getForField(fieldType);
   return new GeoFieldDataScoreFunction(
       origin, scale, decay, offset, getDecayFunction(), indexFieldData, mode);
 }