public interface Formula { public visit(Visitor visitor); /** * A Visitor to perform case analysis on Formula. This is * intended to be exhaustive; an implementation of this * interface must say how to handle all of the subcaes. The * variable is the result type of the Visitor. */ public static interface Visitor { public R visitVariable(Variable var); public R visitNot(Not var); public R visitAnd(And var); public R visitOr(Or var); } public static final class Variable implements Formula { private final T tag; public Variable(T tag) { this.tag = tag; } public T getTag() { return tag; } public visit(Visitor visitor) { visitor.visitVariable(this); } } public static final class Not implements Formula { private final Formula subformula; public Not(Formula subformula) { this.subformula = subformula; } public Formula getSubformula() { return subformula; } public visit(Visitor visitor) { visitor.visitNot(this); } } public static final class And implements Formula { private final Formula left; private final Formula right; public And(Formula left, Formula right) { this.left = left; } public Formula getLeft() { return left; } public Formula getRight() { return right; } public visit(Visitor visitor) { visitor.visitAnd(this); } } public static final class Or implements Formula { private final Formula left; private final Formula right; public Or(Formula left, Formula right) { this.left = left; } public Formula getLeft() { return left; } public Formula getRight() { return right; } public visit(Visitor visitor) { visitor.visitOr(this); } } }