'Moves every not operator to the leafs.
Moving is going by applying the De Morgan rules and annihilating
double negations.'

@staticmethod
def _move_negation_to_leaf(condition):

    def _apply_de_morgan(tree, negated_subtree, negated_op):
        if (negated_op == 'and'):
            new_op = 'or'
        else:
            new_op = 'and'
        tree[new_op] = [{'not': child} for child in negated_subtree[negated_op]]
        del tree['not']
    def transform(subtree):
        op = list(subtree.keys())[0]
        if (op in ['and', 'or']):
            [transform(child) for child in subtree[op]]
        elif (op == 'not'):
            negated_tree = subtree[op]
            negated_op = list(negated_tree.keys())[0]
            if (negated_op == 'and'):
                _apply_de_morgan(subtree, negated_tree, negated_op)
                transform(subtree)
            elif (negated_op == 'or'):
                _apply_de_morgan(subtree, negated_tree, negated_op)
                transform(subtree)
            elif (negated_op == 'not'):
                value = list(negated_tree.values())[0]
                new_op = list(value.keys())[0]
                subtree[new_op] = negated_tree[negated_op][new_op]
                del subtree['not']
                transform(subtree)
    transform(condition)
