MessageVisitor.java

package de.schegge.rosinante.generator;

import de.schegge.rosinante.parser.Node;
import de.schegge.rosinante.parser.Token;
import de.schegge.rosinante.parser.ast.Field;
import de.schegge.rosinante.parser.ast.FieldOption;
import de.schegge.rosinante.parser.ast.FieldOptions;
import de.schegge.rosinante.parser.ast.MessageBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

import static de.schegge.rosinante.generator.FieldOptionsVisitor.MESSAGE_FIELD_OPTION_VISITOR;

public class MessageVisitor implements ProtoVisitor<MessagePatternWithContext, Void> {
    private static final Logger logger = LoggerFactory.getLogger(MessageVisitor.class);

    private static final NameVisitor NAME_VISITOR = new NameVisitor();

    @Override
    public Void visit(MessageBody messageBody, MessagePatternWithContext context) {
        List<Node> children = messageBody.children();
        children.subList(1, children.size() - 1).forEach(node -> node.accept(this, context));
        return null;
    }

    @Override
    public Void visit(Field field, MessagePatternWithContext context) {
        context.pattern().addField(createFieldPattern(field, context));
        return null;
    }

    public Void visit(FieldOption fieldOption, MessagePatternWithContext context) {
        String name = fieldOption.get(0).toString();
        Object constant = fieldOption.get(2).accept(ConstantVisitor.INSTANCE, null);
        logger.debug("field option: name={}, value={}", name, constant);
        return null;
    }

    @Override
    public Void visit(FieldOptions fieldOptions, MessagePatternWithContext context) {
        fieldOptions.childrenOfType(FieldOption.class).forEach(x -> x.accept(this, context));
        return null;
    }

    private FieldPattern createFieldPattern(Field field, MessagePatternWithContext context) {
        List<Node> children = field.children();
        Node first = children.getFirst();
        boolean repeated = first.getType() == Token.TokenType.REPEATED;
        boolean optional = first.getType() == Token.TokenType.OPTIONAL;
        int index = repeated || optional ? 1 : 0;
        FieldType type = context.context().getType(children.get(index).toString());
        int assignIndex = field.indexOf(field.firstChildOfType(Token.class, x1 -> x1.getType() == Token.TokenType.ASSIGN));
        Node integerLiteral = children.get(assignIndex + 1);
        String fieldName = children.get(index + 1).accept(NAME_VISITOR, null);
        FieldPattern fieldPattern = new FieldPattern(fieldName, type, Integer.parseInt(integerLiteral.toString()), optional, repeated);
        field.childrenOfType(FieldOptions.class).forEach(x -> x.accept(MESSAGE_FIELD_OPTION_VISITOR, fieldPattern));
        return fieldPattern;
    }
}