static TimelineFilterList parseMetricFilters(String expr)
      throws TimelineParseException {
    return parseFilters(new TimelineParserForNumericFilters(expr));
  }
@Test
  void testMetricFiltersParsing() throws Exception {
    String expr = "(((key11 ne 234 AND key12 gt 23) AND " +
        "(key13 lt 34 OR key14 ge 567)) OR (key21 lt 24 OR key22 le 45))";
    TimelineFilterList expectedList = new TimelineFilterList(
        Operator.OR,
        new TimelineFilterList(
            Operator.AND,
            new TimelineFilterList(
                Operator.AND,
                new TimelineCompareFilter(TimelineCompareOp.NOT_EQUAL,
                    "key11", 234, false),
                new TimelineCompareFilter(TimelineCompareOp.GREATER_THAN,
                    "key12", 23, true)
            ),
            new TimelineFilterList(
                Operator.OR,
                new TimelineCompareFilter(TimelineCompareOp.LESS_THAN,
                    "key13", 34, true),
                new TimelineCompareFilter(TimelineCompareOp.GREATER_OR_EQUAL,
                    "key14", 567, true)
            )
        ),
        new TimelineFilterList(
            Operator.OR,
            new TimelineCompareFilter(TimelineCompareOp.LESS_THAN,
                "key21", 24, true),
            new TimelineCompareFilter(TimelineCompareOp.LESS_OR_EQUAL,
                "key22", 45, true)
        )
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseMetricFilters(expr), expectedList);

    expr = "abc ene 234";
    expectedList = new TimelineFilterList(
        new TimelineCompareFilter(TimelineCompareOp.NOT_EQUAL,
            "abc", 234, true)
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseMetricFilters(expr), expectedList);

    expr = "abc ne 234";
    expectedList = new TimelineFilterList(
        new TimelineCompareFilter(TimelineCompareOp.NOT_EQUAL,
            "abc", 234, false)
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseMetricFilters(expr), expectedList);

    expr = "abc ne 234 AND def gt 23";
    expectedList = new TimelineFilterList(
        new TimelineCompareFilter(TimelineCompareOp.NOT_EQUAL,
            "abc", 234, false),
        new TimelineCompareFilter(TimelineCompareOp.GREATER_THAN,
            "def", 23, true)
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseMetricFilters(expr), expectedList);

    expr = "(abc ne 234 AND def gt 23)";
    expectedList = new TimelineFilterList(
        new TimelineCompareFilter(TimelineCompareOp.NOT_EQUAL,
            "abc", 234, false),
        new TimelineCompareFilter(TimelineCompareOp.GREATER_THAN,
            "def", 23, true)
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseMetricFilters(expr), expectedList);

    expr = "abc ne 234 AND def gt 23 OR rst lt 24";
    expectedList = new TimelineFilterList(
        Operator.OR,
        new TimelineFilterList(
            new TimelineCompareFilter(TimelineCompareOp.NOT_EQUAL,
                "abc", 234, false),
            new TimelineCompareFilter(TimelineCompareOp.GREATER_THAN,
                "def", 23, true)
        ),
        new TimelineCompareFilter(TimelineCompareOp.LESS_THAN,
            "rst", 24, true)
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseMetricFilters(expr), expectedList);

    expr = "abc ne 234 AND def gt 23 OR rst lt 24 OR xyz le 456";
    expectedList = new TimelineFilterList(
        Operator.OR,
        new TimelineFilterList(
            new TimelineCompareFilter(TimelineCompareOp.NOT_EQUAL,
                "abc", 234, false),
            new TimelineCompareFilter(TimelineCompareOp.GREATER_THAN,
                "def", 23, true)
        ),
        new TimelineCompareFilter(TimelineCompareOp.LESS_THAN,
            "rst", 24, true),
        new TimelineCompareFilter(TimelineCompareOp.LESS_OR_EQUAL,
            "xyz", 456, true)
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseMetricFilters(expr), expectedList);

    expr = "abc ne 234 AND def gt 23 OR rst lt 24 OR xyz le 456 AND pqr ge 2";
    expectedList = new TimelineFilterList(
        new TimelineFilterList(
            Operator.OR,
            new TimelineFilterList(
                new TimelineCompareFilter(TimelineCompareOp.NOT_EQUAL,
                    "abc", 234, false),
                new TimelineCompareFilter(TimelineCompareOp.GREATER_THAN,
                    "def", 23, true)
            ),
            new TimelineCompareFilter(TimelineCompareOp.LESS_THAN,
                "rst", 24, true),
            new TimelineCompareFilter(TimelineCompareOp.LESS_OR_EQUAL,
                "xyz", 456, true)
        ),
        new TimelineCompareFilter(TimelineCompareOp.GREATER_OR_EQUAL,
            "pqr", 2, true)
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseMetricFilters(expr), expectedList);

    // Test with unnecessary spaces.
    expr = "  abc ne   234       AND       def           gt 23 OR     rst lt " +
        "           24     OR xyz     le     456    AND pqr ge 2        ";
    expectedList = new TimelineFilterList(
        new TimelineFilterList(
            Operator.OR,
            new TimelineFilterList(
                new TimelineCompareFilter(TimelineCompareOp.NOT_EQUAL,
                    "abc", 234, false),
                new TimelineCompareFilter(TimelineCompareOp.GREATER_THAN,
                    "def", 23, true)
            ),
            new TimelineCompareFilter(TimelineCompareOp.LESS_THAN,
                "rst", 24, true),
            new TimelineCompareFilter(TimelineCompareOp.LESS_OR_EQUAL,
                "xyz", 456, true)
        ),
        new TimelineCompareFilter(TimelineCompareOp.GREATER_OR_EQUAL,
            "pqr", 2, true)
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseMetricFilters(expr), expectedList);

    expr = "(((key11 ne 234 AND key12 gt 23 OR key13 lt 24 OR key14 le 456 " +
        "AND key15 ge 2) AND (key16 lt 34 OR key17 ge 567)) OR (key21 lt 24 " +
        "OR key22 le 45))";
    expectedList = new TimelineFilterList(
        Operator.OR,
        new TimelineFilterList(
            Operator.AND,
            new TimelineFilterList(
                new TimelineFilterList(
                    Operator.OR,
                    new TimelineFilterList(
                        new TimelineCompareFilter(TimelineCompareOp.NOT_EQUAL,
                            "key11", 234, false),
                        new TimelineCompareFilter(
                            TimelineCompareOp.GREATER_THAN, "key12", 23, true)
                    ),
                    new TimelineCompareFilter(TimelineCompareOp.LESS_THAN,
                        "key13", 24, true),
                    new TimelineCompareFilter(TimelineCompareOp.LESS_OR_EQUAL,
                        "key14", 456, true)
                ),
                new TimelineCompareFilter(TimelineCompareOp.GREATER_OR_EQUAL,
                    "key15", 2, true)
            ),
            new TimelineFilterList(
                Operator.OR,
                new TimelineCompareFilter(TimelineCompareOp.LESS_THAN,
                    "key16", 34, true),
                new TimelineCompareFilter(TimelineCompareOp.GREATER_OR_EQUAL,
                    "key17", 567, true)
            )
        ),
        new TimelineFilterList(
            Operator.OR,
            new TimelineCompareFilter(TimelineCompareOp.LESS_THAN,
                "key21", 24, true),
            new TimelineCompareFilter(TimelineCompareOp.LESS_OR_EQUAL,
                "key22", 45, true)
        )
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseMetricFilters(expr), expectedList);

    expr = "   (  (     (        key11      ne     234    AND key12    gt   " +
        "23    OR    key13    lt    24 OR key14 le 456   AND   key15   ge   2" +
        "   )   AND ( key16 lt 34 OR key17 ge 567 )    )     OR " +
        "(   key21 lt 24 OR key22 le 45 )   )    ";
    expectedList = new TimelineFilterList(
        Operator.OR,
        new TimelineFilterList(
            Operator.AND,
            new TimelineFilterList(
                new TimelineFilterList(
                    Operator.OR,
                    new TimelineFilterList(
                        new TimelineCompareFilter(TimelineCompareOp.NOT_EQUAL,
                            "key11", 234, false),
                        new TimelineCompareFilter(
                            TimelineCompareOp.GREATER_THAN, "key12", 23, true)
                    ),
                    new TimelineCompareFilter(TimelineCompareOp.LESS_THAN,
                        "key13", 24, true),
                    new TimelineCompareFilter(TimelineCompareOp.LESS_OR_EQUAL,
                        "key14", 456, true)
                ),
                new TimelineCompareFilter(TimelineCompareOp.GREATER_OR_EQUAL,
                    "key15", 2, true)
            ),
            new TimelineFilterList(
                Operator.OR,
                new TimelineCompareFilter(TimelineCompareOp.LESS_THAN,
                    "key16", 34, true),
                new TimelineCompareFilter(TimelineCompareOp.GREATER_OR_EQUAL,
                    "key17", 567, true)
            )
        ),
        new TimelineFilterList(
            Operator.OR,
            new TimelineCompareFilter(TimelineCompareOp.LESS_THAN,
                "key21", 24, true),
            new TimelineCompareFilter(TimelineCompareOp.LESS_OR_EQUAL,
                "key22", 45, true)
        )
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseMetricFilters(expr), expectedList);

    expr = "(((key11 ne 234 AND key12 gt 23 OR key13 lt 24 OR key14 le 456 " +
        "AND key15 ge 2) AND (key16 lt 34 OR key17 ge 567)) OR (key21 lt 24 " +
        "OR key22 le 45)";
    try {
      TimelineReaderWebServicesUtils.parseMetricFilters(expr);
      fail("Improper brackers. Exception should have been thrown.");
    } catch (TimelineParseException e) {
    }

    expr = "(((key11 ne 234 AND key12 gt v3 OR key13 lt 24 OR key14 le 456 " +
        "AND key15 ge 2) AND (key16 lt 34 OR key17 ge 567)) OR (key21 lt 24 " +
        "OR key22 le 45))";
    try {
      TimelineReaderWebServicesUtils.parseMetricFilters(expr);
      fail("Non Numeric value. Exception should have been thrown.");
    } catch (TimelineParseException e) {
    }

    expr = "(((key11 ne (234 AND key12 gt 3 OR key13 lt 24 OR key14 le 456 " +
        "AND key15 ge 2) AND (key16 lt 34 OR key17 ge 567)) OR (key21 lt 24 " +
        "OR key22 le 45))";
    try {
      TimelineReaderWebServicesUtils.parseMetricFilters(expr);
      fail("Unexpected opening bracket. Exception should have been thrown.");
    } catch (TimelineParseException e) {
    }

    expr = "(((k)ey11 ne 234 AND key12 gt 3 OR key13 lt 24 OR key14 le 456 " +
        "AND key15 ge 2) AND (key16 lt 34 OR key17 ge 567)) OR (key21 lt 24 " +
        "OR key22 le 45))";
    try {
      TimelineReaderWebServicesUtils.parseMetricFilters(expr);
      fail("Unexpected closing bracket. Exception should have been thrown.");
    } catch (TimelineParseException e) {
    }

    expr = "(((key11 rs 234 AND key12 gt 3 OR key13 lt 24 OR key14 le 456 " +
        "AND key15 ge 2) AND (key16 lt 34 OR key17 ge 567)) OR (key21 lt 24 " +
        "OR key22 le 45))";
    try {
      TimelineReaderWebServicesUtils.parseMetricFilters(expr);
      fail("Improper compare op. Exception should have been thrown.");
    } catch (TimelineParseException e) {
    }

    expr = "(((key11 ne 234 PI key12 gt 3 OR key13 lt 24 OR key14 le 456 " +
        "AND key15 ge 2) AND (key16 lt 34 OR key17 ge 567)) OR (key21 lt 24 " +
        "OR key22 le 45))";
    try {
      TimelineReaderWebServicesUtils.parseMetricFilters(expr);
      fail("Improper op. Exception should have been thrown.");
    } catch (TimelineParseException e) {
    }

    expr = "(((key11 ne 234 PI key12 gt 3 OR key13 lt 24 OR key14 le 456 " +
        "AND key15 ge 2) AND (key16 lt 34 OR key17 ge 567)) OR (key21 lt 24 " +
        "OR key22 le 45))";
    try {
      TimelineReaderWebServicesUtils.parseMetricFilters(expr);
      fail("Improper op. Exception should have been thrown.");
    } catch (TimelineParseException e) {
    }

    expr = "(key11 ne 234 AND key12 gt 3)) OR (key13 lt 24 OR key14 le 456)";
    try {
      TimelineReaderWebServicesUtils.parseMetricFilters(expr);
      fail("Unbalanced brackets. Exception should have been thrown.");
    } catch (TimelineParseException e) {
    }

    expr = "(key11 rne 234 AND key12 gt 3) OR (key13 lt 24 OR key14 le 456)";
    try {
      TimelineReaderWebServicesUtils.parseMetricFilters(expr);
      fail("Invalid compareop. Exception should have been thrown.");
    } catch (TimelineParseException e) {
    }

    expr = "(key11 ne 234 AND key12 gt 3) OR (key13 lt 24 OR key14 le";
    try {
      TimelineReaderWebServicesUtils.parseMetricFilters(expr);
      fail("Compareop cant be parsed. Exception should have been thrown.");
    } catch (TimelineParseException e) {
    }

    assertNull(TimelineReaderWebServicesUtils.parseMetricFilters(null));
    assertNull(TimelineReaderWebServicesUtils.parseMetricFilters("   "));
  }