aboutsummaryrefslogtreecommitdiffstats
path: root/container-search/src/main/java/com/yahoo/search/query/ParameterParser.java
blob: 714e296b02389e26f369bc45c26e5a1cc1e2848e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.search.query;

import com.yahoo.processing.IllegalInputException;

/**
 * Wrapper class to avoid code duplication of common parsing requirements.
 *
 * @author Steinar Knutsen
 */
public class ParameterParser {

    /**
     * Tries to return the given object as a Long. If it is a Number, treat it
     * as a number of seconds, i.e. get a Long representation and multiply by
     * 1000. If it has a String representation, try to parse this as a floating
     * point number, followed by by an optional unit (seconds and an SI prefix,
     * a couple of valid examples are "s" and "ms". Only a very small subset of
     * SI prefixes are supported). If no unit is given, seconds are assumed.
     *
     * @param value some representation of a number of seconds
     * @param defaultValue returned if value is null
     * @return value as a number of milliseconds
     * @throws NumberFormatException if value is not a Number instance and its String
     *         representation cannot be parsed as a number followed optionally by time unit
     */
    public static Long asMilliSeconds(Object value, Long defaultValue) {
        if (value == null) return defaultValue;
        if (value instanceof Number) return ((Number)value).longValue() * 1000L;
        return parseTime(value.toString());
    }

    private static Long parseTime(String time) throws NumberFormatException {
        time = time.trim();
        try {
            int unitOffset = findUnitOffset(time);
            double measure = Double.valueOf(time.substring(0, unitOffset));
            double multiplier = parseUnit(time.substring(unitOffset));
            return (long) (measure * multiplier);
        } catch (RuntimeException e) {
            throw new IllegalInputException("Error parsing '" + time + "'", e);
        }
    }

    private static int findUnitOffset(String time) {
        int unitOffset = 0;
        while (unitOffset < time.length()) {
            char c = time.charAt(unitOffset);
            if (c == '.' || (c >= '0' && c <= '9')) {
                unitOffset += 1;
            } else {
                break;
            }
        }
        if (unitOffset == 0) {
            throw new IllegalInputException("Invalid number '" + time + "'");
        }
        return unitOffset;
    }

    private static double parseUnit(String unit) {
        unit = unit.trim();
        final double multiplier;
        if ("ks".equals(unit)) {
            multiplier = 1e6d;
        } else if ("s".equals(unit)) {
            multiplier = 1000.0d;
        } else if ("ms".equals(unit)) {
            multiplier = 1.0d;
        } else if ("\u00B5s".equals(unit)) {
            // microseconds
            multiplier = 1e-3d;
        } else {
            multiplier = 1000.0d;
        }
        return multiplier;
    }

}