class RuleBasedOptimizer implements Optimizer {

    @Override
    public PlanNode optimize( QueryContext context,
                              PlanNode plan ) {
        LinkedList<OptimizerRule> rules = new LinkedList<OptimizerRule>();
        populateRuleStack(rules, context.getHints());

        Problems problems = context.getProblems();
        while (rules.peek() != null && !problems.hasErrors()) {
            OptimizerRule nextRule = rules.poll();
            LOGGER.trace("Running query optimizer rule {0}", nextRule);
            plan = nextRule.execute(context, plan, rules);
            LOGGER.trace("Plan after running query optimizer rule {0}: \n{1}", nextRule, plan);
        }

        return plan;
    }

}