Search code examples
jooq

Jooq order precedence


I have a list of conditions which contains

pair<And, a>, <Or, b>, <And, c>, <Or, d>, <And, e>, <And,f>.

I would like to create one condition from it where all are just next to each other on same level without any parentheses.

So:

a OR b AND c OR d AND e AND f.

The list can contain any number of conditions with mixed operators(And, Or).

Currently if I chain it together in Jooq it generates (a OR b) and c.. etc which is not what I want.


Solution

  • This is a fun algorithm. Your list is like a sequence of tokens, similar to what a parser would encounter. You could implement something like a recursive descent parser, similar to jOOQ's own parser. This would make sense if you add more operands to your stream, e.g. Not or arithmetic operators, as well as the possibility of nesting operations, etc.

    With only two types of operators, it's probably simpler to just loop over your list like this. Assuming these auxiliary types:

    enum Op { And, Or }
    record Pair(Op op, Condition c) {}
    

    Write this:

    List<Pair> list = List.of(
        new Pair(And, condition("a")),
        new Pair(Or, condition("b")),
        new Pair(And, condition("c")),
        new Pair(Or, condition("d")),
        new Pair(And, condition("e")),
        new Pair(And, condition("f"))
    );
    
    Condition or = list.get(0).c;
    
    for (int i = 1; i < list.size(); i++) {
        Pair p = list.get(i);
        Condition and = p.c;
    
        for (int j = i + 1; j < list.size(); j++) {
            Pair q = list.get(j);
    
            if (q.op == And) {
                and = and.and(q.c);
                i = j;
            }
            else
                break;
        }
    
        or = or.or(and);
    }
    
    System.out.println(or);
    

    This then prints:

    (
      (a)
      or (
        (b)
        and (c)
      )
      or (
        (d)
        and (e)
        and (f)
      )
    )