static TimelineFilterList parseEventFilters(String expr)
      throws TimelineParseException {
    return parseFilters(new TimelineParserForExistFilters(expr,
        TimelineParseConstants.COMMA_CHAR));
  }
@Test
  void testEventFiltersParsing() throws Exception {
    String expr = "abc,def";
    TimelineFilterList expectedList = new TimelineFilterList(
        new TimelineExistsFilter(TimelineCompareOp.EQUAL, "abc"),
        new TimelineExistsFilter(TimelineCompareOp.EQUAL, "def")
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseEventFilters(expr), expectedList);

    expr = "(abc,def)";
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseEventFilters(expr), expectedList);

    expr = "(abc,def) OR (rst, uvx)";
    expectedList = new TimelineFilterList(Operator.OR,
        new TimelineFilterList(
            new TimelineExistsFilter(TimelineCompareOp.EQUAL, "abc"),
            new TimelineExistsFilter(TimelineCompareOp.EQUAL, "def")
        ),
        new TimelineFilterList(
            new TimelineExistsFilter(TimelineCompareOp.EQUAL, "rst"),
            new TimelineExistsFilter(TimelineCompareOp.EQUAL, "uvx")
        )
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseEventFilters(expr), expectedList);

    expr = "!(abc,def,uvc) OR (rst, uvx)";
    expectedList = new TimelineFilterList(Operator.OR,
        new TimelineFilterList(
            new TimelineExistsFilter(TimelineCompareOp.NOT_EQUAL, "abc"),
            new TimelineExistsFilter(TimelineCompareOp.NOT_EQUAL, "def"),
            new TimelineExistsFilter(TimelineCompareOp.NOT_EQUAL, "uvc")
        ),
        new TimelineFilterList(
            new TimelineExistsFilter(TimelineCompareOp.EQUAL, "rst"),
            new TimelineExistsFilter(TimelineCompareOp.EQUAL, "uvx")
        )
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseEventFilters(expr), expectedList);

    expr = "(((!(abc,def,uvc) OR (rst, uvx)) AND (!(abcdefg) OR !(ghj,tyu)))" +
        " OR ((bcd,tyu) AND uvb))";
    expectedList = new TimelineFilterList(Operator.OR,
        new TimelineFilterList(
            new TimelineFilterList(Operator.OR,
                new TimelineFilterList(
                    new TimelineExistsFilter(
                        TimelineCompareOp.NOT_EQUAL, "abc"),
                    new TimelineExistsFilter(
                        TimelineCompareOp.NOT_EQUAL, "def"),
                    new TimelineExistsFilter(TimelineCompareOp.NOT_EQUAL, "uvc")
                ),
                new TimelineFilterList(
                    new TimelineExistsFilter(TimelineCompareOp.EQUAL, "rst"),
                    new TimelineExistsFilter(TimelineCompareOp.EQUAL, "uvx")
                )
            ),
            new TimelineFilterList(Operator.OR,
                new TimelineFilterList(
                    new TimelineExistsFilter(
                        TimelineCompareOp.NOT_EQUAL, "abcdefg")
                ),
                new TimelineFilterList(
                    new TimelineExistsFilter(
                        TimelineCompareOp.NOT_EQUAL, "ghj"),
                    new TimelineExistsFilter(
                        TimelineCompareOp.NOT_EQUAL, "tyu")
                )
            )
        ),
        new TimelineFilterList(
            new TimelineFilterList(
                new TimelineExistsFilter(TimelineCompareOp.EQUAL, "bcd"),
                new TimelineExistsFilter(TimelineCompareOp.EQUAL, "tyu")
            ),
            new TimelineExistsFilter(TimelineCompareOp.EQUAL, "uvb")
        )
    );
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseEventFilters(expr), expectedList);

    expr = "  (  (  (  !  (  abc , def  ,   uvc)   OR   (   rst  ,   uvx )  )" +
        "  AND   (  !  (  abcdefg ) OR  !   (  ghj,  tyu)  ) )  OR   (   (" +
        "   bcd   ,   tyu  )   AND   uvb  )   )";
    verifyFilterList(expr,
        TimelineReaderWebServicesUtils.parseEventFilters(expr), expectedList);

    expr = "(((!(abc,def,uvc) OR (rst, uvx)) AND (!(abcdefg) OR !(ghj,tyu)))" +
        " OR ((bcd,tyu) AND uvb)";
    try {
      TimelineReaderWebServicesUtils.parseEventFilters(expr);
      fail("Improper brackets. Exception should have been thrown");
    } catch (TimelineParseException e) {
    }

    expr = "(((!(abc,def,uvc) (OR (rst, uvx)) AND (!(abcdefg) OR !(ghj,tyu)))" +
        " OR ((bcd,tyu) AND uvb))";
    try {
      TimelineReaderWebServicesUtils.parseEventFilters(expr);
      fail("Unexpected opening bracket. Exception should have been thrown");
    } catch (TimelineParseException e) {
    }

    expr = "(((!(abc,def,uvc) OR) (rst, uvx)) AND (!(abcdefg) OR !(ghj,tyu)))" +
        " OR ((bcd,tyu) AND uvb))";
    try {
      TimelineReaderWebServicesUtils.parseEventFilters(expr);
      fail("Unexpected closing bracket. Exception should have been thrown");
    } catch (TimelineParseException e) {
    }

    expr = "(((!(abc,def,uvc) PI (rst, uvx)) AND (!(abcdefg) OR !(ghj,tyu)))" +
        " OR ((bcd,tyu) AND uvb))";
    try {
      TimelineReaderWebServicesUtils.parseEventFilters(expr);
      fail("Invalid op. Exception should have been thrown");
    } catch (TimelineParseException e) {
    }

    expr = "(((!(abc,def,uvc) !OR (rst, uvx)) AND (!(abcdefg) OR !(ghj,tyu)))" +
        " OR ((bcd,tyu) AND uvb))";
    try {
      TimelineReaderWebServicesUtils.parseEventFilters(expr);
      fail("Unexpected ! char. Exception should have been thrown");
    } catch (TimelineParseException e) {
    }

    expr = "abc,def,uvc) OR (rst, uvx)";
    try {
      TimelineReaderWebServicesUtils.parseEventFilters(expr);
      fail("Unexpected closing bracket. Exception should have been thrown");
    } catch (TimelineParseException e) {
    }

    expr = "abc,def,uvc OR )rst, uvx)";
    try {
      TimelineReaderWebServicesUtils.parseEventFilters(expr);
      fail("Unexpected closing bracket. Exception should have been thrown");
    } catch (TimelineParseException e) {
    }

    expr = "abc,def,uvc OR ,rst, uvx)";
    try {
      TimelineReaderWebServicesUtils.parseEventFilters(expr);
      fail("Unexpected delimiter. Exception should have been thrown");
    } catch (TimelineParseException e) {
    }

    expr = "abc,def,uvc OR !  ";
    try {
      TimelineReaderWebServicesUtils.parseEventFilters(expr);
      fail("Unexpected not char. Exception should have been thrown");
    } catch (TimelineParseException e) {
    }

    expr = "(abc,def,uvc)) OR (rst, uvx)";
    try {
      TimelineReaderWebServicesUtils.parseEventFilters(expr);
      fail("Unbalanced brackets. Exception should have been thrown");
    } catch (TimelineParseException e) {
    }

    expr = "(((! ,(abc,def,uvc) OR (rst, uvx)) AND (!(abcdefg) OR !(ghj,tyu" +
        "))) OR ((bcd,tyu) AND uvb))";
    try {
      TimelineReaderWebServicesUtils.parseEventFilters(expr);
      fail("( should follow ! char. Exception should have been thrown");
    } catch (TimelineParseException e) {
    }

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