package qls.ast.visitor.widgetbinder;
import ql.ast.QLType;
import ql.ast.expression.Identifier;
import ql.ast.type.QLBoolean;
import ql.ast.type.QLFloat;
import ql.ast.type.QLInteger;
import ql.ast.type.QLMoney;
import ql.ast.type.QLString;
import ql.ast.visitor.TypeVisitor;
import ql.ast.visitor.typechecker.TypeEnvironment;
import qls.ast.Statement;
import qls.ast.statement.Block;
import qls.ast.statement.DefaultStyle;
import qls.ast.statement.DefaultWidget;
import qls.ast.statement.Question;
import qls.ast.statement.widget.Widget;
import qls.ast.statement.widget.type.Checkbox;
import qls.ast.statement.widget.type.Default;
import qls.ast.statement.widget.type.Spinbox;
import qls.ast.statement.widget.type.TextField;
import qls.ast.statement.widget.type.parameterised.Dropdown;
import qls.ast.statement.widget.type.parameterised.RadioButton;
import qls.ast.statement.widget.type.parameterised.Slider;
import qls.ast.visitor.ExpressionVisitor;
import qls.ast.visitor.StatementVisitor;
import qls.ast.visitor.WidgetEnvironment;
import qls.gui.WidgetBuilder;
import qls.gui.WidgetFactory;
import qls.gui.builder.BooleanWidgetBuilder;
import qls.gui.builder.FloatWidgetBuilder;
import qls.gui.builder.IntegerWidgetBuilder;
import qls.gui.builder.MoneyWidgetBuilder;
import qls.gui.builder.StringWidgetBuilder;
import qls.gui.factory.CheckboxFactory;
import qls.gui.factory.DefaultFactory;
import qls.gui.factory.DropdownFactory;
import qls.gui.factory.RadioButtonFactory;
import qls.gui.factory.SliderFactory;
import qls.gui.factory.SpinboxFactory;
import qls.gui.factory.TextFieldFactory;
import qls.gui.widget.InputWidget;
public class WidgetBinder extends StatementVisitor<Object> implements ExpressionVisitor<QLType>, TypeVisitor<WidgetBuilder> {
private DefaultWidgetEnvironment defaultWidgets;
private WidgetEnvironment widgetEnvironment;
private TypeEnvironment typeEnvironment;
private UnboundQuestionRegister unboundQuestions;
private WidgetBinder(TypeEnvironment typeEnvironment) {
super.setExpressionVisitor(this);
super.setTypeVisitor(this);
this.typeEnvironment = typeEnvironment;
defaultWidgets = new DefaultWidgetEnvironment();
widgetEnvironment = new WidgetEnvironment();
unboundQuestions = new UnboundQuestionRegister();
}
public WidgetEnvironment getWidgetEnvironment() {
return widgetEnvironment;
}
public static WidgetEnvironment bind(Statement statement, TypeEnvironment typeEnvironment) {
WidgetBinder binder = new WidgetBinder(typeEnvironment);
statement.accept(binder);
return binder.getWidgetEnvironment();
}
private void scopeDown() {
defaultWidgets = new DefaultWidgetEnvironment(defaultWidgets);
unboundQuestions = new UnboundQuestionRegister(unboundQuestions);
}
private void scopeUp() {
defaultWidgets = defaultWidgets.getParent();
unboundQuestions = unboundQuestions.getParent();
}
public Void visit(Block blockNode) {
scopeDown();
super.visit(blockNode);
scopeUp();
return null;
}
@Override
public QLType visit(Identifier identifierNode) {
return typeEnvironment.resolve(identifierNode);
}
@Override
public WidgetBuilder visit(QLBoolean booleanNode) {
return new BooleanWidgetBuilder();
}
@Override
public WidgetBuilder visit(QLFloat floatNode) {
return new FloatWidgetBuilder();
}
@Override
public WidgetBuilder visit(QLInteger integerNode) {
return new IntegerWidgetBuilder();
}
public WidgetBuilder visit(QLMoney moneyNode) {
return new MoneyWidgetBuilder();
}
@Override
public WidgetBuilder visit(QLString stringNode) {
return new StringWidgetBuilder();
}
@Override
public WidgetFactory visit(Checkbox checkboxNode) {
return new CheckboxFactory();
}
@Override
public WidgetFactory visit(Default dropdownNode) {
return new DefaultFactory(defaultWidgets);
}
@Override
public WidgetFactory visit(Dropdown dropdownNode) {
return new DropdownFactory(dropdownNode.getFirstValue(), dropdownNode.getSecondValue());
}
@Override
public WidgetFactory visit(RadioButton radioButtonNode) {
return new RadioButtonFactory(radioButtonNode.getFirstValue(), radioButtonNode.getSecondValue());
}
@Override
public WidgetFactory visit(TextField textFieldNode) {
return new TextFieldFactory();
}
@Override
public WidgetFactory visit(Spinbox spinnerNode) {
return new SpinboxFactory();
}
@Override
public WidgetFactory visit(Slider sliderNode) {
return new SliderFactory(sliderNode.getFirstValue(), sliderNode.getSecondValue());
}
public Void visit(DefaultStyle defaultNode) {
defaultWidgets.storeDefaultStyle(defaultNode.getType(),
defaultNode.getStyleProperties());
unboundQuestions.bindWidgets(defaultNode.getType(),
widgetEnvironment, defaultWidgets);
super.visit(defaultNode);
return null;
}
public Void visit(DefaultWidget defaultNode) {
WidgetFactory factory = (WidgetFactory) defaultNode.getWidget().accept(this);
WidgetBuilder builder = defaultNode.getType().accept(this);
InputWidget<?> widget = factory.create(builder, defaultNode.getWidget().getStyleRules());
defaultWidgets.store(defaultNode.getType(), widget);
unboundQuestions.bindWidgets(defaultNode.getType(), widgetEnvironment, defaultWidgets);
return null;
}
@Override
public WidgetFactory visit(Widget widgetNode) {
widgetNode.getStyleRules().accept(this);
return (WidgetFactory) widgetNode.getWidgetType().accept(this);
}
@Override
public Void visit(Question questionNode) {
QLType questionType = questionNode.getIdentifier().accept(this);
if(questionNode.hasDefaultWidget()) {
unboundQuestions.register(questionType, questionNode);
}
WidgetBuilder builder = questionType.accept(this);
WidgetFactory factory = (WidgetFactory) questionNode.getWidget().accept(this);
InputWidget<?> questionWidget = factory.create(builder, questionNode.getWidget().getStyleRules());
widgetEnvironment.store(questionNode.getIdentifier(), questionWidget);
return null;
}
}