class StandardPreparedQuery implements PreparedQuery {

    @Override
    public VariableImpact getVariableImpact() {
        final VariableImpact existing = this.variableImpact;
        if (existing != null) {
            return existing;
        }

        final Set<String> variables = new HashSet<>();

        for (final Expression expression : expressions) {
            if (!(expression instanceof CompiledExpression)) {
                continue;
            }

            final CompiledExpression compiled = (CompiledExpression) expression;
            for (final Evaluator<?> evaluator : compiled.getAllEvaluators()) {
                if (evaluator instanceof AttributeEvaluator) {
                    final AttributeEvaluator attributeEval = (AttributeEvaluator) evaluator;
                    final Evaluator<String> nameEval = attributeEval.getNameEvaluator();

                    if (nameEval instanceof StringLiteralEvaluator) {
                        final String referencedVar = nameEval.evaluate(Collections.emptyMap()).getValue();
                        variables.add(referencedVar);
                    }
                } else if (evaluator instanceof AllAttributesEvaluator) {
                    final AllAttributesEvaluator allAttrsEval = (AllAttributesEvaluator) evaluator;
                    final MultiAttributeEvaluator iteratingEval = allAttrsEval.getVariableIteratingEvaluator();
                    if (iteratingEval instanceof MultiNamedAttributeEvaluator) {
                        variables.addAll(((MultiNamedAttributeEvaluator) iteratingEval).getAttributeNames());
                    } else if (iteratingEval instanceof MultiMatchAttributeEvaluator) {
                        return VariableImpact.ALWAYS_IMPACTED;
                    }
                } else if (evaluator instanceof AnyAttributeEvaluator) {
                    final AnyAttributeEvaluator allAttrsEval = (AnyAttributeEvaluator) evaluator;
                    final MultiAttributeEvaluator iteratingEval = allAttrsEval.getVariableIteratingEvaluator();
                    if (iteratingEval instanceof MultiNamedAttributeEvaluator) {
                        variables.addAll(((MultiNamedAttributeEvaluator) iteratingEval).getAttributeNames());
                    } else if (iteratingEval instanceof MultiMatchAttributeEvaluator) {
                        return VariableImpact.ALWAYS_IMPACTED;
                    }
                } else if (evaluator instanceof MappingEvaluator) {
                    final MappingEvaluator<?> allAttrsEval = (MappingEvaluator<?>) evaluator;
                    final MultiAttributeEvaluator iteratingEval = allAttrsEval.getVariableIteratingEvaluator();
                    if (iteratingEval instanceof MultiNamedAttributeEvaluator) {
                        variables.addAll(((MultiNamedAttributeEvaluator) iteratingEval).getAttributeNames());
                    }
                }
            }
        }

        final VariableImpact impact = new NamedVariableImpact(variables);
        this.variableImpact = impact;
        return impact;
    }

    public  StandardPreparedQuery(final List<Expression> expressions);

}