package edu.parser.QLS;
import com.sun.javaws.exceptions.InvalidArgumentException;
import edu.Widgets;
import edu.exceptions.ParseException;
import edu.nodes.QuestionType;
import edu.nodes.styles.*;
import edu.parser.QLS.antlrGenerated.QLSBaseVisitor;
import edu.parser.QLS.antlrGenerated.QLSParser;
import edu.parser.QLS.nodes.AbstractNode;
import edu.parser.QLS.nodes.QLSIdentifier;
import edu.parser.QLS.nodes.Section;
import edu.parser.QLS.nodes.Stylesheet;
import edu.parser.QLS.nodes.statement.Default;
import edu.parser.QLS.nodes.statement.Page;
import edu.parser.QLS.nodes.statement.QLSQuestion;
import edu.parser.QLS.nodes.statement.Statement;
import org.antlr.v4.runtime.misc.NotNull;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* Created by Steven Kok on 28/02/2015.
*/
public class ParseTreeVisitor extends QLSBaseVisitor<AbstractNode> {
@Override
public Stylesheet visitStylesheet(@NotNull QLSParser.StylesheetContext ctx) {
QLSIdentifier QLSIdentifier = (QLSIdentifier) visitIdentifier(ctx.identifier());
List<Page> questions = collectPages(ctx.stylesheet_element());
List<Default> globalDefaultStatements = collectGlobalDefaultStatements(ctx.stylesheet_element());
return new Stylesheet(QLSIdentifier, questions, globalDefaultStatements);
}
private List<Default> collectGlobalDefaultStatements(List<QLSParser.Stylesheet_elementContext> stylesheet_elementContexts) {
return stylesheet_elementContexts.stream()
.map(statement -> statement.accept(this))
.filter(statement -> statement instanceof Default)
.map(defaultStatement -> (Default) defaultStatement)
.collect(Collectors.toList());
}
public List<Page> collectPages(List<QLSParser.Stylesheet_elementContext> stylesheetElements) {
if (isPopulated(stylesheetElements)) {
return getPages(stylesheetElements);
}
return Collections.emptyList();
}
private List<Page> getPages(List<QLSParser.Stylesheet_elementContext> stylesheetElements) {
return stylesheetElements.stream()
.map(statement -> (Statement) statement.accept(this))
.filter(statement -> statement instanceof Page)
.map(question -> (Page) question)
.collect(Collectors.toList());
}
private boolean isPopulated(List<QLSParser.Stylesheet_elementContext> stylesheetElements) {
return stylesheetElements != null && !stylesheetElements.isEmpty();
}
@Override
public AbstractNode visitColor(@NotNull QLSParser.ColorContext ctx) {
return new Color(Integer.parseInt(ctx.NUMBERS().getText()));
}
@Override
public AbstractNode visitFont(@NotNull QLSParser.FontContext ctx) {
String text = ctx.STRING().getText();
return new Font(removeQuotesFromString(text));
}
@Override
public AbstractNode visitWidth(@NotNull QLSParser.WidthContext ctx) {
return new Width(Integer.parseInt(ctx.NUMBERS().getText()));
}
@Override
public AbstractNode visitWidget(@NotNull QLSParser.WidgetContext ctx) {
try {
Widgets widget = Widgets.getWidget(ctx.UPPERCASE().getText());
return new Widget(widget);
} catch (InvalidArgumentException e) {
throw new ParseException(e);
}
}
@Override
public AbstractNode visitIdentifier(@NotNull QLSParser.IdentifierContext ctx) {
return new QLSIdentifier(ctx.getText());
}
@Override
public AbstractNode visitStatement(@NotNull QLSParser.StatementContext ctx) {
if (ctx.default_statement() != null) {
return visitDefault_statement(ctx.default_statement());
} else if (ctx.question() != null) {
return visitQuestion(ctx.question());
}
throw new ParseException("Couldn't parse statement for input: " + ctx.getText());
}
@Override
public AbstractNode visitDefault_statement(@NotNull QLSParser.Default_statementContext ctx) {
QuestionType questionType = (QuestionType) visitQuestion_type(ctx.question_type());
List<Style> styles = collectStyles(ctx.style());
return new Default(questionType, styles);
}
@Override
public AbstractNode visitQuestion_type(@NotNull QLSParser.Question_typeContext ctx) {
try {
return QuestionType.getType(ctx.getText());
} catch (InvalidArgumentException e) {
throw new ParseException(e);
}
}
@Override
public AbstractNode visitPage(@NotNull QLSParser.PageContext ctx) {
List<Section> sections = collectSections(ctx.section());
return new Page(sections);
}
@Override
public AbstractNode visitSection(@NotNull QLSParser.SectionContext ctx) {
String title = ctx.STRING().getSymbol().getText();
List<QLSQuestion> questions = collectQuestions(ctx.statement());
List<Default> defaultStatements = collectDefaultStatements(ctx.statement());
return new Section(removeQuotesFromString(title), questions, defaultStatements);
}
private List<Default> collectDefaultStatements(List<QLSParser.StatementContext> statements) {
return statements.stream()
.filter(statement -> statement.default_statement() != null)
.map(statement -> (Default) statement.default_statement().accept(this))
.collect(Collectors.toList());
}
private List<QLSQuestion> collectQuestions(List<QLSParser.StatementContext> statements) {
return statements.stream()
.filter(statement -> statement.question() != null)
.map(statement -> (QLSQuestion) statement.question().accept(this))
.collect(Collectors.toList());
}
private String removeQuotesFromString(String title) {
return title.substring(1, title.length() - 1);
}
private List<Section> collectSections(List<QLSParser.SectionContext> elements) {
return elements.stream()
.map(statement -> (Section) statement.accept(this))
.collect(Collectors.toList());
}
@Override
public AbstractNode visitQuestion(@NotNull QLSParser.QuestionContext ctx) {
QLSIdentifier QLSIdentifier = (QLSIdentifier) visitIdentifier(ctx.identifier());
List<Style> styles = collectStyles(ctx.style());
return new QLSQuestion(QLSIdentifier, styles);
}
private List<Style> collectStyles(List<QLSParser.StyleContext> elements) {
return elements.stream()
.map(element -> (Style) this.visit(element))
.collect(Collectors.toList());
}
}