package nl.uva.polyql.ast; import java.awt.Component; import java.util.HashSet; import java.util.Set; import nl.uva.polyql.ast.expressions.Expression; import nl.uva.polyql.ast.values.BooleanValue; import nl.uva.polyql.ast.values.Type; import nl.uva.polyql.validation.InvalidIfStatementError; import nl.uva.polyql.validation.ValidationErrors; import nl.uva.polyql.view.IfStatementView; public class IfStatement extends RuleContainer implements Rule, Question.ValueListener { private final RuleContainer mParent; private final Expression mExpression; private boolean mSatisfied; private LineInfo mLineInfo; private final Set<SatisfactionListener> mSatisfactionListeners = new HashSet<>(); protected IfStatement(final RuleContainer parent, final Expression expression) { mParent = parent; mExpression = expression; for (final Question question : mExpression.getReferencedQuestions()) { question.addUpdateListener(this); } } @Override public Component getView() { final IfStatementView view = new IfStatementView(this); mSatisfactionListeners.add(view); view.onSatisfactionUpdate(this); return view.getComponent(); } @Override public void onQuestionUpdate(final Question question) { mExpression.validate(); final boolean satisfied = checkSatisfaction(); if (satisfied != mSatisfied) { mSatisfied = satisfied; for (final SatisfactionListener listener : mSatisfactionListeners) { listener.onSatisfactionUpdate(this); } } } @Override public ValidationErrors validate() { // Validate expression final ValidationErrors errors = mExpression.validate(); if (!errors.isFatal()) { if (mExpression.getReturnType() != Type.BOOLEAN) { errors.add(new InvalidIfStatementError(this)); } else { mSatisfied = checkSatisfaction(); } } // Validate children for (final Rule rule : getRules()) { errors.merge(rule.validate()); } return errors; } private boolean checkSatisfaction() { return ((BooleanValue) mExpression.getValue()).getValue(); } public Expression getExpression() { return mExpression; } @Override public void setLineInfo(final LineInfo lineInfo) { mLineInfo = lineInfo; } @Override public LineInfo getLineInfo() { return mLineInfo; } @Override public RuleContainer getParent() { return mParent; } public boolean isSatisfied() { return mSatisfied; } @Override public String toString() { return "IF " + mExpression; } /** * The interface for objects wanting to be notified of satisfaction changes of the if-statement. */ public interface SatisfactionListener { /** * Called when an if-statement's visibility changed. * * @param ifStatement * The caller */ public void onSatisfactionUpdate(final IfStatement ifStatement); } }