All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ly.invoker.builder.compiler.Compiler Maven / Gradle / Ivy

package com.ly.invoker.builder.compiler;

import com.ly.invoker.builder.template.Template;
import com.ly.invoker.builder.validator.Validator;
import com.ly.invoker.core.ICoordinator;
import com.ly.invoker.core.IRouter;
import com.ly.invoker.core.ISelector;
import com.ly.invoker.core.ISingleSelector;
import com.ly.invoker.core.coordinator.Coordinator;
import com.ly.invoker.core.handler.Handler;
import com.ly.invoker.core.handler.HandlerFunction;
import com.ly.invoker.core.payload.Path;
import com.ly.invoker.core.payload.Payload;
import com.ly.invoker.core.router.NameRouter;
import com.ly.invoker.core.router.VersionRouter;
import com.ly.invoker.core.stack.StackElement;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Compiler {
    private final Validator validator;

    private final List elements = new ArrayList<>();
    private final Coordinator coordinator;
    private final LinkedList stack;
    private final LinkedList path;

    public Compiler(String structure) {
        coordinator = new Coordinator();
        this.stack = new LinkedList<>();
        path = new LinkedList<>();
        validator = new Validator(structure);
    }

    public Compiler(Template template) {
        this(template.structure().toString());
    }

    public void compile(Context context) {
        stack.clear();
        path.clear();
        elements.clear();
        validator.reset();

        for (Object element : context.elements()) {
            validate(element);
        }

        newStack(coordinator);
        for (Element element : elements) {
            switch (element.getType()) {
                case NAME_ROUTER:
                case VERSION_ROUTER:
                case HANDLER:
                    helper(element);
                    break;
                case LP:
                    helper(element);
                    newStack(stack.peekFirst().get(1));
                    break;
                case RP:
                    stack.removeFirst();
                    break;
            }
        }
        context.reset();
    }

    public Coordinator coordinator() {
        return coordinator;
    }

    public void validate(Object element) {
        if (element instanceof Element) {
            Element e = (Element) element;
            validator.validate(e);
            elements.add(e);
        } else if (element instanceof Context) {
            Context c = (Context) element;
            for (Object e : c.elements()) {
                validate(e);
            }
        }
    }

    private void helper(Element element) {
        ISelector next = null;
        StackElement current = stack.peekFirst();
        if (current.get(0) == current.get(1)) {
            next = ((Coordinator) current.get(0)).root();
            if (next == null) {
                next = product(element);
                ((ICoordinator) current.get(0)).setRoot(next);
            }
        } else if (current.get(1) instanceof IRouter) {
            IRouter r = current.get(1);
            String p = path.pollFirst();
            if (!r.has(p)) {
                next = product(element);
                r.add(p, next);
            } else {
                next = r.route(new Payload().setPath(new Path(new String[]{p})));
            }
        } else if (current.get(1) instanceof ISingleSelector) {
            ISingleSelector s = current.get(1);
            next = s.next();
            if (next == null) {
                next = product(element);
                s.setNext(next);
            }
        }
        switch (element.getType()) {
            case NAME_ROUTER:
            case VERSION_ROUTER:
                path.addFirst((String) element.getValue());
        }
        check(next, element);
        current.setIndex(1, next);
    }

    private void check(ISelector selector, Element element) {
        if (selector instanceof Handler) {
            Handler h = (Handler) selector;
            if (h.isEmpty() && !element.isEmpty()) {
                h.setFunction((HandlerFunction) element.getValue());
            }
        }
    }

    private ISelector product(Element element) {
        switch (element.getType()) {
            case NAME_ROUTER:
                return new NameRouter();
            case VERSION_ROUTER:
                return new VersionRouter();
            case HANDLER:
                return Handler.of((HandlerFunction) element.getValue());
        }
        return new Coordinator();
    }

    private void newStack(ICoordinator coordinator) {
        if (coordinator == null) {
            coordinator = new Coordinator();
        }
        stack.addFirst(new StackElement(coordinator, coordinator));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy