@Test
public 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("   "));
}